AWS Security Token Service

The AWS STS service is a core security service that issues temporary credentials. It is the central component of multi-account authentication and single sign-on. In this post, I compare the permanent credentials of IAM users vs the temporary credentials of roles. I also describe the six methods that can be used to request temporary credentials, and how those credentials can be used to access AWS services and the console.

IAM Users – Permanent Credentials

Users are the basic entity used to managed permissions. When creating a new AWS account, a “root” user is created. The root user is a special user that has unrestricted access to the account. The root account should not be used. Instead, it is recommended to assign a hardware MFA to the root user to prevent unauthorized access, and to only use IAM users to access the account.

IAM users can access the console with a username and password and/or can access AWS resources programmatically (through the API, SDK, or CLI) by using an access key and a secret key. Each IAM user can have up to 10 policies attached to it, to restrict the actions it can perform. Moreover, each IAM user can be part of up to 10 groups, each group having up to 10 policies each.

IAM users are a convenient way to access a single AWS account, but they suffer from several drawbacks, including:

  1. One IAM user per account. With multiple accounts (e.g. dev, staging, prod), separate IAM users would have to be created for each account. This quickly becomes cumbersome, as one might forgot to create or delete a user. Moreover, it can become difficult to ensure that the policies of each IAM user are consistent between accounts.
  2. IAM users have permanent credentials. The credentials assigned to an IAM user are permanent (i.e. the password and the access key/secret key). This implies that a set of stolen credentials could be used to access AWS resources for an unlimited amount of time. It is recommended to enforce a strong password policy, to require IAM users to use multi-factor authentication, and to require frequent credentials rotation to properly secure IAM users.

STS Roles – Temporary Credentials

It quickly becomes obvious that after a user is authenticated, we want to grant temporary credentials to that user to perform a certain set of actions for a limited period of time. Under that scenario, the user could request temporary credentials in different accounts, and the risk of compromised credentials would be minimized because the credentials are temporary. This is exactly what roles are, temporary credentials used to perform only one set of actions. The workflow to use a role would be:

Source: https://aws.amazon.com/blogs/security/how-to-use-a-single-iam-user-to-easily-access-all-your-accounts-by-using-the-aws-cli/

To assume the role in the same or a different AWS account, the following 3 components are always required:

1. Authentication. The user requesting to assume a role must be authenticated either directly through AWS (e.g. an IAM user, or an IAM role) or through a third-party identity provider. A user could be authenticated through SAML Federation (e.g. Okta or Google Apps), through Active Directory Federation Services (ADFS), through a JSON Web Token issued through OIDC.

For the authentication step, we want a confirmation from a trusted source that the user is known and has shown proper credentials. We can them request the temporary role credentials using this proof of authentication.

2. Assume Role Permission. The authenticated user must also have the proper permission to issue an AssumeRole operation. For an IAM user or IAM role, this means that the AssumeRole action is authorized in the policy attached to the authenticated user. For SAML federation, this can mean that the user has the right to use the AWS SAML application and has the target role attached to his profile.

3. Trust Policy. After the user has been authenticated and has the permission to assume the role, the target role must explicitly trust the source user directly (e.g. IAM user or IAM role) or the source user identity provider (e.g. AWS account, SAML provider, or OIDC issuer) to authorize the source user to assume the desired role.

When the 3 components are present, the STS service will be able to issue a set of temporary credentials (Access Key, Secret Key, Session Key) that can be used to perform the actions authorized under the target role’s policy for limited duration of up to 12 hours. The temporary credentials can be used directly with the SDK or CLI, and can also be converted to a SignIn token to access the AWS Console.

The 6 Ways to Assume a Role

The AWS API has 6 workflows that can be used to assume a role.

1) AssumeRole

The AssumeRole API workflow is the simplest and probably the most widely used workflow. Given an authenticated user (as an IAM user or IAM role), the user can request to assume the role in the same account or in another account by providing his current credentials. This is the workflow that is used by the “Switch Roles” option in the AWS console, and by the “role_arn” option in the ~/.aws/config file. Roles can be chained using this method, meaning that Role A can assume Role B then assume Role C.

A valid trust policy for AssumeRole could trust either an entire AWS account, an AWS service, a particular user, or a particular role. If the role trusts an entire AWS account, then it is expected that policies in the source account would prevent unauthorized users from assuming the role in the destination account.

{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Principal": {
         "AWS": "arn:aws:iam::000000000000:user/username"
       },
       "Action": "sts:AssumeRole"
     }
   ]
 }

Given the trust policy above, the trusted user can simply select “Switch Roles” in the top left corner of the AWS console, enter the role name and the target AWS account, and should be able to assume the role if the 3 conditions mentioned above are present.

2) AssumeRoleWithSAML

Security Assertion Markup Language (SAML) is an open standard for exchanging authentication and authorization information between parties. The AssumeRoleWithSAML workflow is mostly used for single sign-on. Given a trusted identity provider (IdP), we can create a SAML provider on AWS that uses the public certificate of the IDP. We then create a role that trusts the identity provider using a trust policy similar to the following:

{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Principal": {
         "Federated": "arn:aws:iam::000000000000:saml-provider/saml-provider-name"
       },
       "Action": "sts:AssumeRoleWithSAML",
       "Condition": {
         "StringEquals": {
           "SAML:aud": "https://signin.aws.amazon.com/saml"
         }
       }
     }
   ]
 }

Each user would have a list of allowed roles stored on its profile in the identity provider, and the identity provider would simply forward a signed SAML response to AWS confirming the the user was properly authenticated and that it can assume a certain list of allowed roles. The authenticated user would then be able to select with role to assume using the SAML response.

3) AssumeRoleWithWebIdentity

The AssumeRoleWithWebIdentity complements the OAuth workflow. A user can login on public websites (Google, Facebook, Amazon) using OAuth and be issued a JSON web token that confirms his identity. A role can be created that trusts the issuer and audience of the JWT, and the user will then be able to assume to target role by providing his JWT. This workflow can also be used by pods running on EKS, to assume the role they need to perform actions on AWS resources by trusting the EKS certificate authority. A trust policy for this workflow might look like:

{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Principal": {
         "Federated": "arn:aws:iam::000000000000:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/00000000000000000000000000000000"
       },
       "Action": "sts:AssumeRoleWithWebIdentity",
       "Condition": {
         "StringEquals": {
           "oidc.eks.us-east-1.amazonaws.com/id/00000000000000000000000000000000:sub": "system:serviceaccount:default:role-ROLENAME"
         }
       }
     }
   ]
 }

4) GetFederationToken

The GetFederationToken workflow is an older workflow that can be used to authenticate users through ADFS or through methods other than SAML or OIDC. It works by creating a super user with a wide range of permissions that can create temporary credentials for authenticated users by providing a session policy for the user.

In other words, if a user is able to be authenticated, the super user is able to request temporary, and restricted credentials by calling the GetFederationToken API and by passing a policy that restricts the temporary credentials to a subset of the actions it can do. This way, if a billing user logs in, we can create temporary credentials to perform billing actions, and if a developer logs in, we create another set of credentials with a completely different policy. The policy of the authenticated user must be a subset of the policy of the super user. In order words, the super user must be able to do everything it grants access to.

5) GetSessionToken

The GetSessionToken is a workflow that is used by an IAM user to temporarily authenticate using a MFA device. By providing his credentials and the MFA secret value, a temporary MFA session is created. This can allow the IAM user to perform MFA-restricted actions, such as S3:Delete*.

6) GetCredentialsForIdentity

Finally, GetCredentialsForIdentity is a workflow that converts AWS Cognito credentials to the credentials of an IAM role. With the Cognito GetCredentialsForIdentity, you do not have to be concerned about the actual authentication mechanism of the user since it implements a unified API for obtaining temporary credentials for any user signed with the Cognito service.GetCallerIdentity (e.g. Cognito User Pools, Google, Facebook, etc.)

Conclusion

IAM users offer a simple mechanism to enforce authentication and authorization, but roles are often better suited for fine-grained controls, because they allow the issuance of temporary credentials and can be used across accounts (e.g. for SSO). In a multi-account setup, it is recommended to create one security account with IAM users and/or SAML-trusted roles, and then trust those roles in other accounts, so that users can safely switch between them. Using this workflow, credentials only have to be revoked in a single account in case an employee leaves the organization.

Reach out to us

Tell us about your situation and we’ll figure out the best option for you and your project