Skip to main content

Managing roles

So far we have only used the role root to do API calls. root is a special role that has all permissions, it can use any endpoint. We're going to create to new roles to show you how you can restrict access to endpoints for your users.

Creating a new role

In this tutorial, we're going to create a role marketing.

Before creating a new role, we need to create a trustpolicy. A trustpolicy is a special kind of policy that is used to define who can or cannot assume a role.

Use the following command to create a trustpolicy:

 # Replace with the ARN that you retrieved in the previous part of the tutorial when you created a new OIDC provider
ARN="arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/idp.astran.io/auth/realms/demo-demo"
ACCOUNT_ID=$(echo -n $ARN | cut -d':' -f5)
PARTITION=$(echo -n $ARN | cut -d':' -f2)
# Replace with the URL or your identity provider WITHOUT THE SCHEME
PROVIDER="demo-idp.astran.io/auth/realms/astran-demo"
cat << EOF > trustpolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${ARN}"
},
"Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
"Condition": {
"StringEquals": {
"${PROVIDER}:aud": "astran"
},
"ForAnyValue:StringEquals": {
"aws:RequestTag/role": "arn:${PARTITION}:iam::${ACCOUNT_ID}:role/marketing"
}
}
}
]
}
EOF

This will create a file trustpolicy.

Let's go through that trustpolicy to see what it does.

        "Version": "2012-10-17",

This just specify which version of the policy specification is used in this policy. Astran's APIs only supports the 2012-10-17 version which is the current one used by AWS.

        "Statement": [

The Statement element is the main element for a policy.

                "Effect": "Allow",

The Effect element determines whether this statement is allowed or denied. Possible values are Allow or Deny.

                "Principal": {
"Federated": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/demo-idp.astran.io/auth/realms/demo-demo"
},

In a trust policy, the Principal determines who can assume the role. In this case we are saying only federated users (e.g users that are using this specific identity provider) can assume this role.

                "Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],

The Action element specifies on which endpoints this statement applies. In this case the endpoint is sts:AssumeRoleWithWebIdentity, since the Effect is Allowed, it means that this trustpolicy allows users that are authenticated from the "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/demo-idp.astran.io/auth/realms/astran-demo" to do an sts assume-role-with-web-identity API call.

The sts:TagSession is an action that enables the person trying to assume the role to use the principal_tags in the JWT token. Without it, any condition that uses the key aws:RequestTag would fail to evaluate and therefore would end up being not true.

            "Condition": {
"StringEquals": {
"demo-idp.astran.io/auth/realms/astran-demo:aud": "astran"
},
"ForAnyValue:StringEquals": {
"aws:RequestTag/role": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
}

The Condition element adds additional constraint to this policy. In this case there are two constraints:

  1. The aud field (audience) in the JWT must be astran. It means only access tokens retrieved from the client astran can be used to do a sts assume-role-with-web-identity.
  2. The "https://aws.amazon.com/tags"."principal_tags"."role" field in the JWT must contain "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing". Note the difference with the previous condition, in this one we have a ForAnyValue prefix. This means that the value linked to the key "aws:RequestTag/role" is an array, therefore we want one of the values in this array to be equal to "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing". This condition is here to make sure that not any user from this identity provider can assume the marketing role.

Now that we have our trustpolicy, we can use the following command to create our new marketing role:

aws --profile astran iam create-role --role-name marketing --assume-role-policy-document file://trustpolicy

Which gives us the following output:

{
"Role": {
"Path": "/",
"RoleName": "marketing",
"RoleId": "AROAASDLFKJ3434KFS43249FSDL43423W26D",
"Arn": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing",
"CreateDate": "0001-01-01T00:00:00+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/demo-idp.astran.io/auth/realms/demo-demo"
},
"Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
"Condition": {
"StringEquals": {
"demo-idp.astran.io/auth/realms/astran-demo:aud": "astran"
},
"ForAnyValue:StringEquals": {
"aws:RequestTag/role": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
}
}
}
]
},
"Description": "",
"MaxSessionDuration": 3600,
"PermissionsBoundary": {
"PermissionsBoundaryType": "",
"PermissionsBoundaryArn": ""
},
"Tags": []
}
}

Authenticating to Astran API's with a new role

note

First make sure that you have created a user, created a group, mapped a group with the marketing role you have just created using the arn, and finally added that user to the group.

If you're using your own identity provider, make sure that in the JWT returned by your client, the field "https://aws.amazon.com/tags"."principal_tags"."role" is set with the ARNs of the roles you want this user to be able to assume.

The decoded JWT must look like something like this:

{
"exp": 1724308670,
"iat": 1724308370,
"jti": "b1594437-d4f4-4b5c-b228-8698ebb04910",
"iss": "https://astran.cloud-iam.com/auth/realms/root-accounts",
"aud": "root-client",
"sub": "ce04d61d-afac-504f-a96b-ebbbced80013",
"typ": "Bearer",
"azp": "root-client",
"session_state": "104b7eb9-c3ba-4384-9d19-931e7ecc2205",
"acr": "1",
"scope": "email",
"sid": "104b7eb9-c3ba-4384-9d19-931e7ecc2205",
"email_verified": true,
"https://aws.amazon.com/tags": {
"principal_tags": {
"role": [
"arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
]
}
},
"email": "demo@astran.io"
}

Now that we have created our marketing role we can use it to authenticate ourself.

# Replace with the email address of the user you want to use
USERNAME="demo@astran.io"
# Replace PARTITION with the name of the partition you are using
# If you are using your own identity provider, use the access token endpoint for OIDC
URL="https://demo-idp.astran.io/auth/realms/PARTITION-demo/protocol/openid-connect/token"
# If you are using your own identity provider, use the client_id you have created
CLIENT_ID="astran"
# Prompt the user for their root account's password
read -rp "Password: " -s PASSWORD
curl -X POST --data-urlencode "client_id=$CLIENT_ID&grant_type=password&username=$USERNAME&password=$PASSWORD" "$URL"

You should have an input similar to this:

{
"access_token": "YOUR_ACCESS_TOKEN",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "YOUR_REFRESH_TOKEN",
"token_type": "Bearer",
"not-before-policy": 0,
"session_state": "faeee2cb-423b-4f6b-a833-7b0eeda28db2",
"scope": "email"
}

Copy the access token. We now have everything we need to retrieve our temporary credentials:

# Use the access token you've retrieved in the previous step
ACCESS_TOKEN="YOUR_ACCESS_TOKEN"
ARN="arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
aws --profile astran sts assume-role-with-web-identity --role-arn "$ARN" --role-session-name marketingSession --web-identity-token "$ACCESS_TOKEN")

Which will give you an output similar to this:

{
"Credentials": {
"AccessKeyId": "ASIAEXAMPLE12344567890",
"SecretAccessKey": "asdfkj234LKJfslkdn34slkfdu9FDjkj423cwjke",
"SessionToken": "SOME_SESSION_TOKEN",
"Expiration": "2024-08-22T08:32:56+00:00"
},
"SubjectFromWebIdentityToken": "ce04d61d-afac-504f-a96b-ebbbced80013",
"AssumedRoleUser": {
"AssumedRoleId": "AROACLKWSDQRAOEXAMPLE:marketingSession",
"Arn": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
},
"Provider": "https://demo-idp.astran.io/auth/realms/PARTITION-demo/protocol/openid-connect/token",
"Audience": "astran",
"SourceIdentity": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/demo-idp.astran.io/auth/realms/PARTITION-demo"
}

We're going to copy the "Credentials"."AccessKeyId" "Credentials"."SecretAccessKey" and "Credentials"."SessionToken" properties to export them in environment variables used by the CLI. We'll then attempt to create a bucket test to test that everything is working as intended:

export AWS_ACCESS_KEY_ID="ASIAEXAMPLE12344567890"
export AWS_SECRET_ACCESS_KEY="asdfkj234LKJfslkdn34slkfdu9FDjkj423cwjke"
export AWS_SESSION_TOKEN="SOME_SESSION_TOKEN"
aws --endpoint-url https://demo.s3.astran.io s3 mb s3://test

If you've done everything properly you should get the following error:

make_bucket failed: s3://test An error occurred (AccessDenied) when calling the CreateBucket operation: You don't have permission to access this resource

That's because a new role has no policies whatsoever attached to it and by default, you automatically get a Deny for an endpoint if there's no policy related to it. We'll see how we can create a policy and attach it to a role in the next part of this tutorial.

Listing all roles

You can list all the roles available with the following command:

aws --profile astran iam list-roles

Which should give you the following output:

{
"Role": {
"Path": "/",
"RoleName": "marketing",
"RoleId": "AROAASDLFKJ3434KFS43249FSDL43423W26D",
"Arn": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing",
"CreateDate": "0001-01-01T00:00:00+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:oidc-provider/demo-idp.astran.io/auth/realms/demo-demo"
},
"Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
"Condition": {
"StringEquals": {
"demo-idp.astran.io/auth/realms/astran-demo:aud": "astran"
},
"ForAnyValue:StringEquals": {
"aws:RequestTag/role": "arn:demo:iam::ce04d61d-afac-504f-a96b-ebbbced80013:role/marketing"
}
}
}
]
},
"Description": "",
"MaxSessionDuration": 3600,
"PermissionsBoundary": {
"PermissionsBoundaryType": "",
"PermissionsBoundaryArn": ""
},
"Tags": []
}
}

Deleting a role

To delete a role, you can run the following command:

# Replace `nameOfTheRole` with the name of the role you want to delete
aws --profile astran iam delete-role --role-name nameOfTheRole

Updating a role

Unfortunately, there's no way to update the trustpolicy of a role. The only way to do so is to delete the role and then recreate it with the new trustpolicy. Luckily the ARN would not change. However you would have to reattach all the policies to the role.