Centrally manage AWS root credentials

Published on 2024-12-31
Last modified on 2024-12-31

Introduction

This article will describe the following features:

  • Central management of root user credentials (IAMAuditRootUserCredentials, IAMCreateRootUserPassword, and IAMDeleteRootUserCredentials)
  • Temporary root sessions for task-specific access (S3UnlockBucketPolicy and SQSUnlockQueuePolicy)

Basic concepts

AWS Organizations

AWS Organizations is used to centrally manage multiple AWS accounts, with features such as consolidated billing, security controls, resource sharing, etc. It should be enabled by any entity managing more than one AWS account.

Management account

The Management Account is the account used to create the AWS Organization. The account is the organization owner and can perform major actions for any account in the Organization such as closing existing accounts or adding new accounts. Due to the elevated access possible through this account, access to this account should be minimized.

AWS Account Root User

When creating an AWS account, the email and password used to create the account become the credentials for the root user of that account. The root user has access to every service and resource in this account. Due to this, it is recommended to lock down the usage of this user as far as possible. Root user best practices.

Only a root user can perform some privileged actions. Performing these actions requires logging in as a root user.

Prerequisite

Trusted access for IAM in AWS Organizations should be enabled for central management of root credentials and temporary root sessions.

The following steps need to be performed in the Management Account of the AWS Organization.

1aws organizations enable-aws-service-access --service-principal iam.amazonaws.com

To verify:

1aws organizations list-aws-service-access-for-organization

The output will include the IAM service:

1{
2 "EnabledServicePrincipals": [
3 ...
4 {
5 "ServicePrincipal": "iam.amazonaws.com",
6 "DateEnabled": "1970-01-01T00:00:00.000000+00:00"
7 },
8 ...
9 ]
10}

Alternatively, if you are already managing your AWS Organization configuration using the aws_organizations_organization block in Terraform, you can add "iam.amazonaws.com" to the aws_service_access_principals array:

1resource "aws_organizations_organization" "organization" {
2 aws_service_access_principals = [<other services>, "iam.amazonaws.com"]
3 feature_set = "ALL"
4 ... other attributes
5}

CAUTION: This resource is used to enable AWS Organizations. Enabling AWS Organizations is a major change and should not be done for experimentation. Use the CLI method unless you are already using this resource block to manage your AWS Organization.

Enable central management of root credentials and temporary root sessions

The following steps need to be performed in the Management Account of the AWS Organization.

1$ aws iam enable-organizations-root-credentials-management
2{
3 "OrganizationId": "o-abcxyz",
4 "EnabledFeatures": [
5 "RootCredentialsManagement"
6 ]
7}
8$ aws iam enable-organizations-root-sessions
9{
10 "OrganizationId": "o-abcxyz",
11 "EnabledFeatures": [
12 "RootSessions",
13 "RootCredentialsManagement"
14 ]
15}

Terraform alternative:

1resource "aws_iam_organizations_features" "root" {
2 enabled_features = [
3 "RootCredentialsManagement",
4 "RootSessions"
5 ]
6}

Assume Root credentials

The following command is used for both RootCredentialsManagement and RootSessions.

1aws sts assume-root --target-principal <account-id> --task-policy-arn arn=arn:aws:iam::aws:policy/root-task/<TaskPolicy>

If RootCredentialsManagement is enabled, the following TaskPolicies can be used:

arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials
arn:aws:iam::aws:policy/root-task/IAMCreateRootUserPassword
arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials

If RootSessions is enabled, the following TaskPolicies can be used:

arn:aws:iam::aws:policy/root-task/S3UnlockBucketPolicy
arn:aws:iam::aws:policy/root-task/SQSUnlockQueuePolicy

A detailed reference for what is allowed for each policy can be found here.

Delegate Centralized Root access (Recommended)

To minimize logins to the Organization Management account for the use of this feature, it is recommended that delegated access be enabled so that another account can also assume root access. This account can be any other account in the AWS Organization.

1aws organizations register-delegated-administrator --service-principal iam.amazonaws.com --account-id <account_id>

Terraform alternative:

1resource "aws_organizations_delegated_administrator" "delegate_iam" {
2 account_id = "<account_id>"
3 service_principal = "iam.amazonaws.com"
4}

Based on my experimentation, delegated accounts:

  • Can execute aws sts assume-root
  • Can execute aws iam disable-organizations-root-credentials-management
  • Can execute aws iam disable-organizations-root-sessions
  • Cannot execute aws iam enable-organizations-root-credentials-management
  • Cannot execute aws iam enable-organizations-root-sessions

Deleting Root Credentials for all non-Management accounts

The following script demonstrates the deletion of root credentials from all non-Management accounts in an AWS organization using aws sts assume-root. It can also be modified to perform similar actions in one or more accounts using one of the above task policies.

1#!/bin/bash
2
3# Backup original credentials if they were set via variables
4export BACKUP_AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
5export BACKUP_AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
6export BACKUP_AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN
7
8MANAGEMENT_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account')
9
10# Get all account IDs except management account
11AWS_ACCOUNT_IDS=($(aws organizations list-accounts | jq -r '.Accounts[].Id | select(. != $MANAGEMENT_ACCOUNT_ID)' --arg MANAGEMENT_ACCOUNT_ID $MANAGEMENT_ACCOUNT_ID))
12
13for AWS_ACCOUNT_ID in "${AWS_ACCOUNT_IDS[@]}"
14do
15 CREDENTIALS=$(aws sts assume-root --target-principal ${AWS_ACCOUNT_ID} --task-policy-arn arn=arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials)
16 # Set credentials for a specific account
17 export AWS_ACCESS_KEY_ID=$(echo $CREDENTIALS | jq -r '.Credentials.AccessKeyId')
18 export AWS_SECRET_ACCESS_KEY=$(echo $CREDENTIALS | jq -r '.Credentials.SecretAccessKey')
19 export AWS_SESSION_TOKEN=$(echo $CREDENTIALS | jq -r '.Credentials.SessionToken')
20 # This will delete root credentials for the account
21 aws iam delete-login-profile
22 # Restore backed-up values
23 export AWS_ACCESS_KEY_ID=$BACKUP_AWS_ACCESS_KEY_ID
24 export AWS_SECRET_ACCESS_KEY=$BACKUP_AWS_SECRET_ACCESS_KEY
25 export AWS_SESSION_TOKEN=$BACKUP_AWS_SESSION_TOKEN
26done
27

References