In my first post on AWS security, I discussed how to secure AWS accounts and services from a high level, so this time, let’s take a closer look at IAM Identity Center. Did you know there are multiple ways someone can login to the AWS management console, each of which can have their own IAM access keys for API access?

Let’s see:

  • root user
    ❌ not recommended in any circumstance
  • IAM user
    ⚠️ deprecated
  • federated OIDC identity
    • IAM Identity Center (SSO)
      ✅ recommended (can also use external IdP)
    • external OIDC
      🧑‍🏫 advanced use cases

AWS recommends that “workforce users,” also known as humans, who need access to AWS and cloud apps be added as users in Identity Center instead of directly in IAM, which is now deprecated for users and groups.

You’ll want to enable IAM Identity Center at the organization level, which means it’ll be in the management account for all intents and purposes.

Next, create any relevant permission sets, such as:

  • Administrator: AdministratorAccess AWS-managed policy
  • SystemAdministrator: SystemAdministrator AWS-managed policy
  • Billing: Billing AWS-managed policy

If you need to grant trusted developers admin privileges, it’s better to use SystemAdministrator than AdministratorAccess, since the former is intended for software development operations, whereas the latter provides root-like access to all of AWS. In later policies, we’ll exclude the Administrator permission set (role) from many of the restrictions we’ll implement using SCPs, so it’s best to avoid using it in day-to-day operations.

At this stage, if you go look in IAM, you’ll see that a few entities were created:

  • AWSSSO_<random>_DO_NOT_DELETE SAML identity provider—this is what enables the configuration for the portal at https://<your slug>.awsapps.com/start
  • AWSReservedSSO_<permission set name>_<random> role for each permission set

IAM Identity Center was formerly known as Single-Sign On (SSO).

IAM Identity Center’s abstraction over IAM is a bit leaky 💦, so don’t mess with those IAM objects. What we really want is to block direct access to IAM to ensure all user and permission management happens exclusively in IAM Identity Center, even if someone has a high level of access, or is granted direct access to IAM through another policy.

Having said that, if you’re using an external identity source (i.e., not the built-in directory), it’s a good idea to create an IAM user for emergency access when your identity provider is down, even though it creates yet another all-powerful IAM user.

Groups

In “classic” IAM, groups are a way to organize sets of users together, for when you don’t want to directly assign roles to users. For the finance team, for example, you could have a Finance group, assign the Billing role (permission set in Identity Center parlance) to it, and add users to that group.

Roughly, the equivalent steps in Identity Center are:

  1. Create groups based on job function
  2. Create permission sets based on job personas (this creates the underlying IAM roles)
  3. Assign users to groups
  4. Attach permission sets to groups

IMHO, adding permissions to a group in Identity Center isn’t intuitive: you have to go into the AWS accounts list, check the accounts to edit, and then click the Assign users or groups button.

Billing Access for IAM Users and Roles

By default, only the root user is allowed to view billing and cost information, even if you’ve created a user with administrator access. If you’re seeing errors accessing the Billing and Cost Management section of the AWS console, then it’s likely that you haven’t enabled IAM user and role access to billing information.

If you’re an organization of any size, really, you likely want to hide billing and cost information even from admin users, who don’t have a business need to see it.

Service Control Policies

I briefly mentioned SCPs before, and will do an entire post about them soon!

After enabling IAM Identity Center, AWS recommends you create an SCP to prevent multiple instances of Identity Center. This is to ensure no additional access is granted through other Identity Center instances, which indirectly add roles and identity providers to IAM.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyMemberAccountInstances",
            "Effect": "Deny",
            "Action": [
                "sso:CreateInstance"
            ],
            "Resource": "*"
        }
    ]
}

Attaching this SCP to the root OU of your organization prevents any member account from creating another instance, which would open up another path of access into member accounts.

Next, we’ll create an SCP that restrict administrators from seeing billing and cost information. Remember, an administrator is a role, not a user! Of course, any user who has permission to assume the Billing role can see it. With the following SCP, we’re adding this billing guardrail:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "aws-portal:*",
                "ce:*",
                "cur:*",
                "billingconductor:*",
                "budgets:*",
                "marketplacecommerceanalytics:*",
                "purchase-orders:*",
                "pricing:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:PrincipalArn": ["arn:aws:iam::ACCOUNT_ID:role/Billing"]
                }
            }
        }
    ]
}

It denies all but the Billing role from accessing billing and cost-related services. A user with AdministratorAccess in a member account now won’t be able to see this information in that account.

Remember, granting a user permission to assume the AdministratorAccess role in the management account bypasses all SCPs. Don’t do that.

Next Steps

IAM Identity Center’s built-in directory may not always be suitable, especially if you’re a large organization, in which case you’ll use an existing Active Directory instance or an external identity provider.

Another option is to create a trusted token issuer to allow simultaneous authentication with both the built-in directory and an external IdP using OpenID Connect as an alternative to a SAML integration.