Getting AWS IAM user by access key id using sdk - amazon-web-services

I'm trying to verify that an IAM user exists with an access key using the AWS SDK(js).
I am trying to build an access control module for an API. I can't deploy it on AWS. Instead of trying to build the whole thing, I want to handle user management using IAM but will need to build a custom module to check if current IAM user has access to resources.
I've checked the docs and looks like you can only get user by username. I thought maybe I can list the users and filter the user array by access key but obviously the list does not have access key info.

The AWS Identity and Access Management (IAM) service is designed specifically for granting access to AWS resources. It is not designed as an authentication system for applications.
A more appropriate product would be Amazon Cognito:
Amazon Cognito lets you easily add user sign-up and sign-in and manage permissions for your mobile and web apps. You can create your own user directory within Amazon Cognito. You can also choose to authenticate users through social identity providers such as Facebook, or Amazon; with SAML identity solutions; or by using your own identity system. In addition, Amazon Cognito enables you to save data locally on users' devices, allowing your applications to work even when the devices are offline. You can then synchronize data across users' devices so that their app experience remains consistent regardless of the device they use.
With Amazon Cognito, you can focus on creating great app experiences instead of worrying about building, securing, and scaling a solution to handle user management, authentication, and synchronization across devices.

You can check whether the user exist or not by IAM User's credentials using AWS CLI/SDK
Attach iam:GetUser and iam:SimulatePrincipalPolicy policies to your IAM user.
Here iam:GetUser will be used to check the user existence and iam:SimulatePrincipalPolicy will be used to check the resource access.
1. Check existence:
You can use getUser() function of AWS-IAM to verify whether user exist or not
const iam = new AWS.IAM({
// Iam User access and secret Key
})
iam.getUser({}, (err,data)=>{
if(err)
console.log("User not exist");
else
console.log("User exist ", data);
})
if user exists:=>
`{
"User": {
"Path": "/",
"UserName": "userName",
"UserId": "AIDAY357ZXJ7ADSEWNGWA3",
"Arn": "arn:aws:iam::60977878822:user/userName", // required this in simulator
"CreateDate": "2020-08-05T14:48:49Z"
}
}`
2. For resource access you can use simulatePrincipalPolicy() function of AWS-IAM.
let params = {
PolicySourceArn = "Paste IAM user arn", // arn:aws:iam::60977878822:user/userName
ActionNames = ["ec2:RunInstances"]
}
iam.simulatePrincipalPolicy(params, (err, data)=> {
if(err)
console.log("Error", err);
else
console.log("Data ", data);
})
output:=>
`{
ResponseMetadata: { RequestId: '3e7cbc9a-ed7b-472a-b054-a6f3f37bf8c4' },
EvaluationResults:
[ { EvalActionName: 'iam:SimulatePrincipalPolicy',
EvalResourceName: '*',
**EvalDecision: 'allowed',** // check this
MatchedStatements: [Array],
MissingContextValues: [],
ResourceSpecificResults: [] },
],
IsTruncated: false
}`
If the EvalDecision is 'allowed' means your IAM User have the access to create new instances.

Related

Executing `import amplify auth` for `Cognito User Pool and Identity Pool` and passing on the `Web Client` as well as the `Native client` fails

Executing import amplify auth for Cognito User Pool and Identity Pool and passing on the Web Client as well as the Native client fails with the below Error. Is there something that is missing please let me know. TIA
Cannot import Identity Pool without roles.
Error: Cannot import Identity Pool without roles.
at IdentityPoolService.getIdentityPoolRoles (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/amplify-provider-awscloudformation/src/aws-utils/IdentityPoolService.ts:88:13)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at importServiceWalkthrough (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:322:74)
at Object.importResource (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:45:42)
at Object.executeAmplifyCommand (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/index.js:421:3)
at executePluginModuleCommand (/usr/local/lib/node_modules/#aws-amplify/cli/src/execution-manager.ts:178:3)
at executeCommand (/usr/local/lib/node_modules/#aws-amplify/cli/src/execution-manager.ts:30:5)
at Object.run (/usr/local/lib/node_modules/#aws-amplify/cli/src/index.ts:205:5)
Ran into this issue as well.
The Amplify Auth import docs mention the following:
Your Identity Pool needs:
an Authenticated Role with a trust relationship to your Identity Pool
an optional Unauthenticated Role if you want to use any guest user access for your Amplify categories. (Example: Guest access for your S3 buckets or REST API endpoints)
However, I:
Using an identity pool with an "authenticated" role with proper trust relationship intact (role, policy, identity pool role attachment).
Made sure the IAM role I was using to deploy this change had proper permissions to list and read identity pools & roles.
Still no help.
I then enabled "Allow unauthenticated identities" (although I did not want this) and things worked smoothly. This is because this setting will automatically generate two authenticated and unauthenticated roles and attach them for you.
However, as I did not want unauthenticated identity access, I disabled that again. Based off that setting working, I wondered if that Unauthenticated Role was truly optional, well it turns out it's not. At least not in the latest Amplify system. Someone must have changed this behaviour without updating the docs.
Solution:
Your Identity Pool needs:
an Authenticated Role with a trust relationship to your Identity Pool
an Unauthenticated Role with a trust relationship to your Identity Pool
To check if your identity pool is set up properly run this function in the AWS CLI:
aws cognito-identity get-identity-pool-roles --identity-pool-id "your identity pool id here"
You should get something like this:
{
"IdentityPoolId": "your identity pool id here",
"Roles": {
"authenticated": "your authenticated role ARN here"
"unauthenticated": "your authenticated role ARN here"
}
}

AWS Pinpoint updating user attributes when unauthenticated - security issue?

I'm looking at using AWS Pinpoint to send push notifications to my react native app. However it seems that unauthenticated users are able to update user attributes for any user they wish, ie there is no access control. I'm new to mobile development, but isn't putting stuff like that into the frontend a security issue? If it were a web application, people would be able to inspect network calls to obtain credentials and make any call they wish to updateEndpoint. Is this not applicable to mobile apps or am I misunderstanding something?
Details:
There's a step in the setup that says Edit the IAM policy document for unauthenticated identities to allow permissions for the mobiletargeting:PutEvents and mobiletargeting:UpdateEndpoint actions
And react native code snippet provided goes as follows:
import Analytics from '#aws-amplify/analytics';
import Auth from '#aws-amplify/auth';';
const amplifyConfig = {
Auth: {
identityPoolId: 'COGNITO_IDENTITY_POOL_ID',
region: 'ap-south-1'
}
}
//Initialize Amplify
Auth.configure(amplifyConfig);
const analyticsConfig = {
AWSPinpoint: {
// Amazon Pinpoint App Client ID
appId: 'cd73a57d200e49e2bc4b97d6ebf63cd4',
// Amazon service region
region: 'ap-south-1',
mandatorySignIn: false,
}
}
Analytics.configure(analyticsConfig)
Analytics.updateEndpoint({
attributes: {
interests: ['science', 'politics', 'travel'],
//..
},
userId: 'UserIdValue',
userAttributes: {
username: 'ilovethecloud'
}
});
I'm not sure if this will help,
But you have 2 IAM policies (in Cognito Identity-pool), 1 for authenticated users and 1 for unauth. users.
You should restrict the IAM policy for unauth users, so they can't edit other users info.
Also, the credentials that you are given by Cognito, are temporal, they expire (and get renewed by your react-native app), so in that way you are safe.

AWS Amplify 'currentUserCredentials()' returns unexpected authenticated value, bug?

When calling Auth.currentUserCredentials() after Auth.signIn() I get valid valid credentials, but for an unauthenticated user, why?
Code:
async signIn({ dispatch, state }, { email, password }) {
try {
const user = await Auth.signIn(email, password);
console.log("User state after login")
const userCredentialsAfterLogin = await Auth.currentUserCredentials();
console.log(userCredentialsAfterLogin)
} catch (error) {
console.log("error")
console.log(error)
return
}
await dispatch('fetchUser')
},
Expected behaviour:
After signing in with a valid user, Auth.currentUserCredentials() should return an authenticated set of Credentials.
Actual behaviour:
Auth.currentUserCredentials() returns an unauthenticated user with the authenticated property set to false and a 400 error, "ResourceNotFoundException: IdentityPool 'eu-west-1:62dab5ed-5a84-4064-a7a2-87d1d0df511b'
System:
authenticationFlowType: "USER_SRP_AUTH"
Versions: "aws-amplify": "^3.3.14", "aws-amplify-vue": "^2.1.4", amplify version 4.42.0
config
{
"authSelections": "userPoolOnly",
"resourceName": "testapp89e81d50",
"serviceType": "imported",
"region": "eu-west-1"
}
I understand where you're coming from, and honestly I can't really show you clear documentation that exactly states why this won't work. AWS documentation on Cognito and Amplify is difficult to piece together, both because the Amplify framework still uses an old library under the hood ('amazon-cognito-identity-js') and Cognito is the name for both a connect-login-with-IAM and signup/signin-as-a-service offering. Cognito is super powerful and rock solid in terms of security if done right, but the setup is a bit of a pain.
There's a bit of documentation, e.g. the API docs of Amplify Auth here. You can see there that currentCredentials / currentUserCredentials gives you some object which contains among other things an 'identitiId'. Credentials, in the Amplify Auth framework, refer to AWS IAM credentials that refer to an Cognito Identity.
You seem to be using Amplify to login to a Cognito User Pool, using email/password. A Cognito User Pool can be connected to a Cognito Identify pool, to 'exchange' a Cognito JWT token for some credentials that can be used to use AWS resources (IAM credentials). This is not needed to have a normal sign in / sign up flow working though.
So, the question is: what do you want?
Do you want to know about the currently logged in Cognito User Pool user, e.g. his email, JWT token and other fields that are stored in the JWT token? Use 'currentUserInfo' or 'currentUserSession'
Do you actually want to have some IAM credentials to invoke AWS resources? Make sure to create and connect your Cognito User Pool with a Cognito Identity Pool and configure your Identity Pool id in your frontend settings. If you've done that, you should be able to use 'currentCredentials'.

Creating AWS IAM user access key specifically for SES

I'm tracking how to send an Email Using the AWS SDK for Python (Boto).
At the AWS Developer Guide using-credentials page I read that:
For security best practice, use AWS Identity and Access Management (IAM) user access keys instead of AWS account access keys [emphasis added].
Then at the Managing Access Keys for IAM Users I am eventually led to this section and I duly confirm using
aws iam list-access-keys
that I have just created (in JSON form):
{
"AccessKeyMetadata": [
{
"UserName": "My_User_Name",
"Status": "Active",
"CreateDate": "2018-09-03T00:43:37Z",
"AccessKeyId": "JRUFKDHUWHE8DD495CHD"
}
]
}
but I lack clarity about whether this identity is the "AWS account access keys" that I was earlier warned does not fall in the "security best practice".
How do I create an IAM identity (user access + password) for sending email through SES and boto (while eliminating the chance I am exposing the entire AWS account)?
Ranting (and a constructive suggestion to AWS staff writers, if here): Specific branding would help. At Ikea I might order a chair or a table with the meaningless name Fjorstuvstok, but I know with certainty that I am ordering the chair I want.
The AWS account access keys are the ones owned by the root account user. To check what these are, you need to know your root account user name. This can be checked using the aws cli using the AWS root credentials, or loging in with your root account credentials to the AWS Console and clicking "My Security Credentials" under your username in the top right corner.
Assuming you use the cli, make sure you've configured the root credentials in ~/.aws/credentials. Then run:
aws iam get-user
{
"User": {
"UserName": "my_root_user_name",
"PasswordLastUsed": "2018-09-03T06:40:38Z",
"CreateDate": "2017-03-01T08:53:36Z",
"UserId": "9XXXXXXXXXXX",
"Arn": "arn:aws:iam::9XXXXXXXXXXX:root"
}
}
This will provide you with details of your root user. This username can then be used to query for access keys:
aws iam list-access-keys --user-name my_root_user_name
If any of the keys listed from this result are being used for SES, then that's bad news. AWS reccomends that you use Access Keys assigned to IAM Users (non-root).
The AWS account access keys mean the Root account access /secret keys of your AWS account. When you register yourself with aws using your email, the account created is Root account. There is key associated with that, which needs to be removed. (As this is Root account, it provides unrestricted access to all AWS services. Check AWS Account Root User Credentials vs. IAM User Credentials
The warning suggested to use IAM user access keys. So you can create IAM user in your aws account and create associated access key id and secret access key and configure that on your machine from where you are running your code. ( This is not good practice in higher deployment environment. If the machine gets compromised then access key will be exposed)
As its unclear how you are running your application code (from ECS or EC2 or AWS Lambda), You should create IAM role to grant access to SES from where you are going to run your code. This will avoid exposing IAM access key Id and Secret access key from your application code / machine.

How to use the Amazon web services credentials (Access keys) in my project?

We want to use AWS services via API calls, CLI, Etc., from our on-premise infrastructure as well as from AWS cloud infrastructure.
As we know, we can use the AWS access key as follow:
This is a snippet from an example
// Setup AWS SNS
AWS.config.update({
region: 'eu-west-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
});
var sns = new AWS.SNS();
var params = {
Message: "SMS message test",
MessageStructure: 'string',
PhoneNumber: '0045xxxxxxxx',
Subject: 'Alarm',
MessageAttributes :{
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': 'MySender'
},
'AWS.SNS.SMS.SMSType': 'Transactional'
}
};
sns.publish(params, function(err_publish, data) {
if (err_publish) {}
});
This code uses the access keys through the environment variables. That approach is partially accepted because you're tied to modify those environment variables to update access keys.
So, what are the best practices or different approaches for using the access keys in a good manner?
AWS Documentation
Access keys consist of an access key ID (for example, AKIAIOSFODNN7EXAMPLE) and a secret access key (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY). You use access keys to sign programmatic requests that you make to AWS if you use the AWS SDKs, REST, or Query API operations. The AWS SDKs use your access keys to sign requests for you, so that you don't have to handle the signing process. You can also sign requests manually. For more information, see Signing AWS API Requests.
Access keys are also used with command line interfaces (CLIs). When you use a CLI, the commands that you issue are signed by your access keys. You can pass access keys either with the command or store as configuration settings on your computer.
Temporary access keys, known as temporary security credentials
In addition to the access key ID and secret access key, temporary security credentials include a security token that you must send to AWS when you use temporary security credentials
Advantages
They are short term.
After they expire, they're no longer valid.
You can use temporary access keys in less secure environments or distribute them to grant users temporary access to resources in your AWS account.
For example, you can grant entities from other AWS accounts access to resources in your AWS account (cross-account access). You can also grant users who don't have AWS security credentials access to resources in your AWS account (federation). For more information, see Temporary Security Credentials in the IAM User Guide.
Approaches for using Access keys
Access keys in Environment variables
This approach is the most common for development and testing environments because they will test their developments using a close scope, likewise for scenarios where our apps are deployed within an on-premise infrastructure.
Usage of Access keys through Environment variables (NodeJs)
// Setup AWS SNS
AWS.config.update({
region: 'eu-west-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
});
var sns = new AWS.SNS();
var params = {...});
sns.publish(params, function(err_publish, data) {...});
Access keys through instance metadata
This is the most secure way to use the Access keys within an EC2 or container because you don't need to put any Access keys neither in your code nor in Environment variables.
Retrieving Security Credentials from Instance Metadata
The following command retrieves the security credentials for an IAM role named s3access.
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access
The following is an example output
{
"Code" : "Success",
"LastUpdated" : "2012-04-26T16:39:16Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAIOSFODNN7EXAMPLE",
"SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Token" : "token",
"Expiration" : "2017-05-17T15:09:54Z"
}
IAM Roles
The IAM Roles provide a good and secure way to grant permissions to your services.
IAM Role console: This is how looks like
The IAM Role allows you to describe a policy with the specific permissions. That role could be attached to an EC2 instance and automatically the service within it will be granted with those permissions. So, we can execute API calls without the need to put the Access keys:
var s3 = new AWS.S3({params:{Bucket: 'bucketname', Key: 'filename'}});
var body = fs.createReadStream('file_to_upload');
s3.upload({Body:body})
.on('httpUploadProgress',function(evt){
console.log(evt);
})
.send(function(err,data){
console.log(err,data);
});
As you can see, there is any Access keys in that code because the SDK will get the Access keys from /latest/meta-data/iam/security-credentials/s3access.
Access keys within Named Profiles
The Named profiles are used for CLI (Command line interface), so you can create profiles with different usages. For example, you can use the AWS access keys from a specific region.
The AWS CLI supports named profiles stored in the config and credentials files. You can configure additional profiles by using aws configure with the --profile option or by adding entries to the config and credentials files.
The following example shows a credentials file with two profiles:
~/.aws/credentials
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[user2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
Each profile uses different credentials—perhaps from two different IAM users—and can also use different regions and output formats.
~/.aws/config
[default]
region=us-west-2
output=json
[profile user2]
region=us-east-1
output=text
Using Profiles with the AWS CLI
$ aws ec2 describe-instances --profile user2
The command above will use the credentials within profile user2
Best practices for using Access keys
Remove (or Don't Generate) Account Access Key
An access key is required in order to sign requests that you make using the AWS Command Line Tools, the AWS SDKs, or direct API calls. Anyone who has the access key for your AWS account root user has unrestricted access to all the resources in your account, including billing information. You cannot restrict the permissions for your AWS account root user.
Use Temporary Security Credentials (IAM Roles) Instead of Long-Term Access Keys
In many scenarios, you don't need a long-term access key that never expires (as you have with an IAM user). Instead, you can create IAM roles and generate temporary security credentials. Temporary security credentials consist of an access key ID and a secret access key, but they also include a security token that indicates when the credentials expire.
Manage IAM User Access Keys Properly
If you do need to create access keys for programmatic access to AWS, create an IAM user and grant that user only the permissions he or she needs. Then generate an access key for that user. For details, see Managing Access Keys for IAM Users in the IAM User Guide.
Precautions when using access keys
Don't embed access keys directly into code.
Use different access keys for different applications.
Rotate access keys periodically.
Remove unused access keys.
Configure multi-factor authentication for your most sensitive operations.
Resources
AWS Security Credentials
AWS Account Root User Credentials vs. IAM User Credentials
AWS Security Audit Guidelines
AWS Account Identifiers
Using Instance Profiles