How to check programmatically if an IAM user signing in AWS console without MFA? - amazon-web-services

I want to use an AWS service or a combination of services to check if the signed-in IAM user used MFA or not.
I tried with cloud watch Events and Lambda. By using this, I could check the details of the user sign in the event object. But, I cannot able to check whether he signed in using MFA or not.
Any Suggestions?
UPDATE:
I used, CloudWatch Event rules -> Source: Build Event by Service (Service Name:AWS Console Sign-in, Event Type: Sign-in) -> Target: Lambda/SNS email. Then I got he below information:
sample Event object which I got:
{
"version":"0",
"id":"XXXX-XXX-XXX-XXX-XXX",
"detail-type":"AWS Console Sign In via CloudTrail",
"source":"aws.signin",
"account":"XXXXXXXXX",
"time":"2020-12-14T12:03:43Z",
"region":"us-east-2",
"resources":[
],
"detail":{
"eventVersion":"1.05",
"userIdentity":{
"type":"IAMUser",
"principalId":"XXXXXXXX",
"arn":"arn:aws:iam::XXXXXXX:user/XXXXX",
"accountId":"XXXXX",
"userName":"XXXX"
},
"eventTime":"2020-12-14T12:03:43Z",
"eventSource":"signin.amazonaws.com",
"eventName":"ConsoleLogin",
"awsRegion":"us-east-2",
"sourceIPAddress":"XX.XX.XX.XX",
"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) ",
"requestParameters":null,
"responseElements":{
"ConsoleLogin":"Success"
},
"additionalEventData":{
"LoginTo":"https://XXXXXXXXXXX.XXX.XXXX.XXXXXXXXXXXXXXXXXXXXX"
},
"eventID":"XXXXX-XXXX-XXXX-XXXX-XXXXXXX",
"eventType":"AwsConsoleSignIn"
}
}

Your example event indicates that the user did not login with MFA. If they had, the additionalEventData would include an MFAUsed value, like this:
"additionalEventData": {
"LoginTo": "https://console.aws.amazon.com/console/home?region=us-east-1&state=hashArgs%23&isauthcode=true",
"MobileVersion": "No",
"MFAUsed": "Yes"
},
I suspect, however, that this data is less useful than you might think. For example, if you use SAML-based authentication, or even (I believe) AWS Single SignOn, you won't see this information. The reason is that such authentication methods -- even if they support MFA -- do not convey that information to AWS.
It can be even more complicated if you use assumed roles, where the indication of AWS MFA is in the userIdentity object.
If you're looking for users that don't have MFA enabled, the best solution imo is to go to the Console's user list.

I would suggest using AWS CloudTrail combined with LookupEvents API using SDK of your choice (Python, JS, Java etc).
First one will capture any IAM calls, even multi-regionally if required, and second will query the results of the capture. You should be able to see the required MFA info in the event body.
https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html
https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_LookupEvents.html

Related

Cognito User Migration Trigger - Exception during user migration - Exception Location

We're using a lambda function to respond to the 'User Migration' trigger in AWS Cognito. When something like a syntax error occurs, you can see it in cloud watch logs. However, "Exception during user migration" errors seen on the login page are no where to be found in the cloud watch logs.
Where are we supposed to look for these? I can't find any anything in the documentation and assumed it would have gone to cloud watch.
I can't test it in the lambda interface because one of the parameters being passed into the lambda function will have a function nested within the object and I can't create a test JSON setup that has that. There's also no test trigger for user migration that is pre-built.
Any ideas as to why I can't see this in cloud watch or where the exceptions would be shown would be greatly appreciated.
Unfortunately Cogntio doesn't expose any logs (or metrics, for that matter!).
The closest you can get is to view the lambda's logs in CloudWatch. If you log your response, and watch your lambda's error metric then you should mostly be able to debug issues internal to the lambda.
This does leave a few edge cases:
You won't see anything if the lambda can't be invoked (this would only happen under heavy concurrent loads either on that single lambda, or on all lambdas across your account)
If you return a bad response the lambda will succeed but the trigger action will fail and Cognito will give you a fairly generic message. At this point you're at the mercy of AWS' documentation to work out what's wrong (which can be a bit hit and miss- although StackOverflow always helps!).
You can find an example payload for the lambda in the trigger documentation:
{
"userName": "THE USERNAME",
"request": {
"password": "THE PASSWORD"
},
"response": {
// it is your responsibility to fill this bit in and return the completed object back:
"userAttributes": {
"string": "string",
...
},
"finalUserStatus": "string",
"messageAction": "string",
"desiredDeliveryMediums": [ "string", ... ],
"forceAliasCreation": boolean
}
}
n.b. As an aside, which you might know, but Lambda payloads always have to be in JSON, which does not store functions. So you should always be able to derive a test payload to use in the console.

AWS Cognito is sending SMS messages without my permission

I noticed a strange charge for SMS messages being sent a few months back and since our code doesn't yet support sending SMS messages, I have been investigating it.
It turns out AWS Cognito is sending text messages when we call "UpdateUserPool" to +12064350128 (206-435-0128). This is not a phone number associated with our account, in our code, or with any of our personnel. What's worse is that this AWS account hosts only development environments where the public doesn't have access. So we know it's either an Amazon employee's number or a security leak (or both).
Has anybody else had this happen? A google for that phone number turned up nothing, other than it is probably from somebody in Seattle.
Does anybody know what kind of data is being sent in these messages or how to figure out what's in them? Is it passwords & confidential info?
I turned on SMS logging and this is all of the data I could gather:
{
"notification": {
"messageId": "975e37a9-a5f1-5397-b6d0-63fdbad40d83",
"timestamp": "2018-10-31 21:21:41.756"
},
"delivery": {
"destination": "+12064350128",
"priceInUSD": 0.00645,
"smsType": "Transactional",
"providerResponse": "Message has been accepted by phone",
"dwellTimeMs": 168,
"dwellTimeMsUntilDeviceAck": 2514670
},
"status": "SUCCESS"
}
I received the following from AWS support. Looks like it's innocuous. Whew!
I completely understand your concern of AWS Cognito sending messages
to phone number +12064350128. I got in touch with the Cognito team and
found that it is an expected behaviour that when you make an
UpdateUserPool API call, a message is sent out to +12064350128 and
this applies to all AWS accounts. The phone number +12064350128 is an
internal number and a message to this number is sent out to verify if
Cognito and SNS are integrated correctly so that Cognito can send SMS
to other numbers. Please note that no security information including
passwords is being passed in the content of this SMS message, It's
just a sample message indicating SNS is integrated with Cognito
correctly.
Please be rest assured that we treat customer's data with utmost
privacy and we have a strict security mechanism in place to check any
fraudulent activities.
I also completely agree that the above behavior needs to be documented
and hence I will be reaching out to the Cognito team to get this
updated in our docs to avoid further confusion.

How can I opt back in to receive SMS messages via Amazon Pinpoint

As part of some testing that I was doing, I replied STOP to an SMS message that was sent via Amazon's Pinpoint service. I received the acknowledgement that I had been removed from further notifications.
I want to opt back in to receiving those messages, but I can't figure out how to do that. I looked at the Pinpoint documentation and I did not see a way to do it. I looked in the Amazon Pinpoint Console and I did not see a way to remove a number from the blacklist. I have tried the standard terms that other SMS providers use such as UNSTOP, UNBLOCK, and START, but none of those work either. Does anyone have any suggestions. I do not want to contact Amazon support about this unless I have to.
As described here: https://docs.aws.amazon.com/cli/latest/reference/sns/opt-in-phone-number.html
aws sns opt-in-phone-number --phone-number ###-###-####
You can also use AWS Console -> Amazon SNS -> Mobile -> Text Messaging(SMS) section to see a list of opt-out phone numbers that was done through Pinpoint and choose to opt-in these numbers...
AWS Pinpoint has not come up with the APIs to check if the number is opted out or not. You can use the AWS SNS APIs for checking this as well for marking a mobile number as active again.
I've been trying to figure this out as well and I think I have a solution from a set of documentation I found about setting up Pinpoint. Below is python pseudocode; from my understanding we just have to update the "OptOut" status for the endpoint (i.e. the phone number that originally opted out).
# Python pseudo code with comments
import boto 3
import datetime
pinpoint = boto3.Session(**login_kwargs).client("pinpoint")
opt_in_response = pinpoint.update_endpoint(
ApplicationId="<App ID from your project>",
EndpointId="<Endpoint you are updating>", # Same as your phone number?
EndpointRequest={
"Address": "<Phone you are updating>",
"ChannelType": 'SMS',
"OptOut": "NONE", # Change from "ALL" (which is opt-out) to "NONE", opt-in
"EffectiveDate": datetime.datetime.utcnow().isoformat(),
"Attributes": {
"OptInTimestamp": [datetime.datetime.utcnow().isoformat()]
}
}
)
I attempted to follow this documentation https://docs.aws.amazon.com/pinpoint/latest/developerguide/pinpoint-dg.pdf (the relevant stuff starts on page 92), which happens to not be in Python.
I wasn't successful but I'm pretty sure this is how you should be able to opt back in (if anyone who knows node.js can verify this solution that'd be awesome).

Yodlee MFA site flow

The yodlee documentation about the MFA flow is a bit blurry/outdated.
I am following this flow chart to refresh a site with MFA: http://developer.yodlee.com/Aggregation_API/Aggregation_Services_Guide/API_Flow/Refresh_Site_Account
On the flow chart, after calling getMFAResponseForSite, we are supposed to check if there is an errorCode field in the response, I don't see such field in the documentation of the getMFAResponseForSite method. Because without this error code field, we cannot go back into the regular flow and wait for the refresh to be completed.
Also what is the difference between retry and isMessageAvailable?
The documentation specify to call stopSiteRefresh method, I don't see it in the flow, it sounds weird for me to call it but the documentation says:
Note that this is one of the APIs that is required to refresh MFA accounts.
Can somebody give me a clear flow when I have to deal with MFA sites? when and how can we go back on the regular process (getSiteRefreshInfo) and wait for the end of the refresh? thanks in advance.
The "errorCode" field only comes when there is no MFA question available and hence you are not seeing it in the sample of the API documentation as the sample contains the response with MFA question.
If you follow the flow closely you can see that you have to call getMFAResponseForSite in a loop and check for errorCode. So please call the API as depicted in the API flow documentation.
Here is a sample with errorCode field present after successfully answering the MFA question.
{
"isMessageAvailable": true,
"fieldInfo": {
"questionAndAnswerValues": [],
"numOfMandatoryQuestions": -1,
"mfaFieldInfoType": "SECURITY_QUESTION"
},
"timeOutTime": 97690,
"itemId": 0,
"errorCode": 0,
"memSiteAccId": xxxxxxxxxx,
"retry": false
}
Please also ignore the stopSiteRefresh API call, we will rectify the API reference documentation, as that API call should not be made in case of getMFAResponseForSite API.

How to check if email is valid before send through Amazon SES

I am fresh in implementing Amazon Web services. I am working on implementing an application for sending bulk emails from a queue. I have to check emails and remove non-verified emails from the queue before sending.
My question is: Is there any method available in Amazon to check whether emails are valid or not?
From your question, it is not clear whether you want to:
1-avoid sending messages to malformed email addresses; or
2-avoid sending messages to email addresses which are not verified under your AWS account.
The answer for 1 is spread in different forms accross forums, SO, etc. You either do it simple, i.e., craft a short and clear regular expression which validates roughly 80% of the cases, or you use a very complex regular expression (in order to validate against the full compliance -- good luck, check this example), check whether the domain is not only valid but also up and running, and, last but not least, check if the account is valid under that domain. Up to you. I'd go with a simple regex.
The answer for 2 is available at Verifying Email Addresses in Amazon SES -- the Amazon SES API and SDKs support the operations below, so you should be covered in any case:
Using the Amazon SES API
You can also manage verified email addresses with the Amazon SES API. The following actions are available:
VerifyEmailIdentity
ListIdentities
DeleteIdentity
GetIdentityVerificationAttributes
Note
The API actions above are preferable to the following older API actions, which are deprecated as of the May 15, 2012 release of Domain Verification.
VerifyEmailAddress
ListVerifiedEmailAddresses
DeleteVerifiedEmailAddress
You can use these API actions to write a customized front-end application for email address verification. For a complete description of the API actions related to email verification, go to the Amazon Simple Email Service API Reference.
You can use the "getIdentityVerificationAttributes" operation to check whether emails are valid or not. You can use this as shown below:
var params = {
Identities: arr // It is a required field (array of strings).
};
ses.getIdentityVerificationAttributes(params, function(err, data) {
if(err)
console.log(err, err.stack); // an error occurred
else
console.log(data); // successful response
});
And the Response will be:
{ ResponseMetadata: { RequestId: '7debf2356-ddf94-1dsfe5-bdfeb-efsdfb5b653' },
VerificationAttributes:
{ 'abc#gmail.com': { VerificationStatus: 'Pending' },
'xyz#gmail.com': { VerificationStatus: 'Success' } } }
If there is an email-id which is not sent previously for email verification request, then there is no key present in 'VerificationAttributes' object.
AmazonSimpleEmailServiceClient ses= new AmazonSimpleEmailServiceClient(credentials);
List lids = ses.listIdentities().getIdentities();
if (lids.contains(address)) {
//the address is verified so
return true;
}