Publish SMS messages through master account in AWS - python

We have a multi-account setup on AWS. There is a master account and separated accounts for dev, staging and prod. We have enabled sending SMS messages on the master account (exited the SMS sandbox).
I would like now to send sms message through the master account from the dev one. In a standard case, I would just publish a message to the correct ARN (and make sure earlier that proper permissions exist). However, while sending SMS messages, there is no ARN, so I am stuck. Is there a way to achieve it?
For the reference, this is how I can send a message on dev (with the sandbox mode on):
client = boto3.client("sns")
try:
client.publish(
PhoneNumber=recipient,
Message=message,
MessageAttributes={
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': sender
}
}
)
except botocore.exceptions.ClientError as error: # noqa
logger.error(f'An error occurred while sending SMS message: {error}')
Is there a way to target different account? I was thinking about providing a aws_access_key_id and aws_secret_access_key but maybe there is another way?

You should:
Create an IAM Role in the master account that has permissions to send the SMS message, and a trust policy that allows the IAM Role to be 'assumed' from the child account
Grant permission to the appropriate IAM User or IAM Role in the child account to assume the IAM Role in the master account
The code would then call AssumeRole() to assume the IAM Role from the master account and then use the returned credentials to send the SMS message

Related

unauthorized_client error when trying to impersonate an account

On Google Business Profile API (Google MyBusiness), I am getting following error when I try to impersonate with an email address:
('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', {'error': 'unauthorized_client', 'error_description': 'Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.'})
I am trying to achieve this using a Python script which is using Google API Client Library:
file_location = '/some/folder/file.json'
impersonated_email = 'abc#abc.com'
scope = ["https://www.googleapis.com/auth/business.manage"]
credentials = ServiceCredentials.from_service_account_file(file_location, scopes=scope, subject=impersonated_email)
If I try to access the endpoint without using the subject parameter, it is working. But of course the main purpose here is impersonating. And the Google documentation says it is possible to impersonate with the subject parameter (or via with_subject function).
By the way, if I tried some invalid mail address, my error is changing to: ('invalid_grant: Invalid email or User ID', {'error': 'invalid_grant', 'error_description': 'Invalid email or User ID'})
So I assume that I can get the user credentials; but have no idea what could have been wrong.
Does anybody have any idea about the issue? What could be the possible issues?
Well, Google explains that JWT error code like that:
error field: unauthorized_client
error_description field: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
Meaning:
A service account was authorized using the client email address rather than the client ID (numeric) in the Admin console.
How to resolve:
In the Domain-wide delegation page in the Admin console, remove the client, and re-add it with the numeric ID.
I tried that but I still got the error.
Then, after some digging; I saw that you only can impersonate G-Suite accounts.
So, after that I tried same code with another real-person mail which is a G-Suite account and it worked.

Azure chat bot fails to authenticate

I'm trying to create a chat bot using the Bot Framework with Python. I had this working a few days ago but now I'm getting an error when I test in Azure web chat: KeyError: 'access_token'. This problem is reproducible using sample code from here.
If I remove the app ID and password in config.py and test with the Bot Emulator on localhost then it works fine. When I change these variables to the correct values and test through ngrok it fails with the same exception.
I tried checking the credentials with curl as described here and it returned this error.
{
"error": "unauthorized_client",
"error_description": "AADSTS700016: Application with identifier 'd720efc0-d9a3-4c7a-86ab-deed1a27739c' was not found in the directory 'botframework.com'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.\r\nTrace ID: de49aeb5-f200-4427-89f9-973fe2d10701\r\nCorrelation ID: 400d7c55-5854-44a6-a1f1-5a1eb74889da\r\nTimestamp: 2021-04-28 00:00:44Z",
"error_codes": [
700016
],
"timestamp": "2021-04-28 00:00:44Z",
"trace_id": "de49aeb5-f200-4427-89f9-973fe2d10701",
"correlation_id": "400d7c55-5854-44a6-a1f1-5a1eb74889da",
"error_uri": "https://login.microsoftonline.com/error?code=700016"
}
That sounds like the App ID is wrong, but I verified it by copying the Microsoft App ID from the Azure portal, Bot Channels Registration, configuration page. I guess it's possible I have the wrong password, but if that's the case I don't know how to change it.
May be check Messaging endpoint (ngrok url its correct or not)
Changing password
Azure -> Bot Channels Registration -> configuration -> Micrsoft Id(Manage) Click Manage link
Client secrets -> New Client secret

MSAL Authentication with Python Showing Unauthorized Client?

I am trying to authenticate an Azure app that has application-level permissions. All the permissions have been granted by an admin, and the app has both a client id and a client secret. I'm running the following code based on the Daemon-api documentation from Microsoft graph:
import msal
config = {
"authority": "https://login.microsoftonline.com/organizations",
"client_id": CLIENT_ID,
"scope": ["https://graph.microsoft.com/.default"],
"redirect_uri": REDIRECT_URI,
"client_secret": CLIENT_SECRET
}
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["client_secret"] )
result = app.acquire_token_silent(config["scope"], account=None)
import logging
if not result:
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
result = app.acquire_token_for_client(scopes=config["scope"])
If I print result though, it says the following:
{'error': 'unauthorized_client',
'error_description': "AADSTS700016: Application with identifier [IDENTIFIER] was not found in the directory 'microsoft.com'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.\r\nTrace ID: [TRACE ID]\r\nCorrelation ID: [CORRELATION ID]\r\nTimestamp: 2019-08-28 17:14:39Z",
'error_codes': [700016],
'timestamp': '2019-08-28 17:14:39Z',
'trace_id': [TRACE ID],
'correlation_id': [CORRELATION ID],
'error_uri': 'https://login.microsoftonline.com/error?code=700016'}
The app has existed for several days and as I've mentioned, it has had all its permissions authorized by an admin. How come I'm still getting an "unauthorized" error? I check my id and secret, they're correct.
I wonder if it might have something to do with the fact that the error message says it's being sent to the microsoft.com directory? But the only microsoft information I provide is in authority and scope which the api says is needed as-is. I don't see anywhere to provide a directory id. Could that be the issue? If so, how would I rectify it?
Authority field in your config should be
https://login.microsoftonline.com/<directory_id>

Access denied for service account when accessing IAP-protected application

Trying to let a python command line to access(HTTP GET) IAP-protected application.
With https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/iap/make_iap_request.py
But 403 err occurs Exception: Service account xxx#xxxxxxxxx-production.iam.gserviceaccount.com does not have permission to access the IAP-protected application.
Following methods have been tried, but still issue persists as above
1. remove/create the service account
2. re-create the json key file
3. grant the service account project owner permission
if __name__ == '__main__':
os.environ[
"GOOGLE_APPLICATION_CREDENTIALS"] = '/Users/foo/bar.json'
print make_iap_request('https://foo.com/', 'xxxxtheidforthatiapservice.apps.googleusercontent.com')
I think you need to follow the Authenticating from a service account procedure:
Use an OpenID Connect (OIDC) token to authenticate a service account
to a Cloud IAP-secured resource.
Add the service account to the access list for the Cloud IAP-secured project.
Generate a JWT-based access token. This uses a target_audience additional claim that requires a client ID. To find
your client ID, follow the steps below:
a. Go to the Cloud IAP page.
b. Find the resource you want to access, then click More > Edit
OAuth Client.
edit OAuth client on the More menu
c. On the Credentials page that appears, note the client ID.
Request an OIDC token for the Cloud IAP-secured client ID.
Include the OIDC token in an Authorization: Bearer header to make the authenticated request to the Cloud IAP-secured resource.
I faced the same problem.
You have to run the script authenticated as a service account used to access the IAP-protected application programmatically. You can do so either by running script directly from VM which uses that service account as default, or you will need to download SA credentials and do it locally Obtaining an OIDC token from a local service account key file
Besides that, you also need to assign the IAP-secured Web App User role to the desired Service Account for that particular IAP-protected app.
After that, rerun the script.

How to assume a role that requires an MFA from within an EC2 instance with an instance profile attached?

I want to allow an EC2 instance to assume a role from a different account. The EC2 has a role attached that allows it to assume any role from another account called myAdmin. If the myAdmin role on the other accounts has my account number listed as a trusted entity, then I can assume the role successfully.
However, the myAdmin roles on the other accounts also require anyone assuming the role to be authenticated using MFA because the role gives admin access to the account. This condition causes the assume role action to fail.
I am assuming it fails because obviously the EC2 instance did not authenticate using an MFA (the instance profile was just attached to it when it was instantiated). I have tried passing in the MFA serial number and token of the root account using the following python (boto) code but haven't had any luck.
sts_conn = boto.sts.STSConnection()
role_creds = sts_conn.assume_role(role_arn='arn:aws:iam::OTHER_ACCT_NUM:role/myAdmin',
role_session_name='myAdminSession',
mfa_serial_number='arn:aws:iam::MY_ACCT_NUM:mfa/root-account-mfa-device',
mfa_token=TOKEN)
I get the following error:
boto.exception.BotoServerError: BotoServerError: 403 Forbidden
<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<Error>
<Type>Sender</Type>
<Code>AccessDenied</Code>
<Message>MultiFactorAuthentication failed, unable to validate MFA code. Please verify your MFA serial number is valid and associated with this user.</Message>
</Error>
<RequestId>d108e1aa-a2a2-11e5-9bbf-8fce06e22779</RequestId>
</ErrorResponse>
I think this fails because the root MFA credentials isn't really associated with the EC2 instance credentials.
Can MFA credentials be used with an EC2 instance profile to assume a role that requires MFA?
And if so, how would I go about doing this?

Categories