Skip to content

Instantly share code, notes, and snippets.

@solarce
Forked from craigbruce/awsadvent
Created December 5, 2014 19:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save solarce/cb488547fde80041c9b3 to your computer and use it in GitHub Desktop.
Save solarce/cb488547fde80041c9b3 to your computer and use it in GitHub Desktop.

Using IAM to secure your account and resources

AWS Identity and Access Management (IAM) is a service from AWS to aid you in securing your AWS resources. This is accomplished by creating users and roles with specific permissions for both API endpoints and AWS resources.

Ultimately, IAM is a security tool and like all security tools there is a balance of security and practicality (no one wants to enter an MFA code for every single API request). IAM is an optional and free service, but users that do not use IAM have been bitten - most recently BrowserStack (see here). If BrowserStack had followed the IAM best practices it could of avoided this incident.

This article will cover a few areas of IAM.

  • Best practices. There is really no excuse not to follow these.
  • Where your user identities can originate from. AWS offer multiple options now.
  • Various tips and tricks for using IAM.

Best practices

IAM has a best practice guide which is easy to implement. Also when you access IAM via the AWS management console it highlights some best practices and if you have implemented them.

Here is a brief summary of the IAM best practices:

  • Lock away your AWS account access keys

    Ideally just delete the root access keys. Your root user (with a physical MFA) is only required to perform IAM actions via the AWS management console. Create power users for all other tasks, everything except IAM.

  • Create individual IAM users

    Every user has their own access keys/credentials.

  • Use groups to assign permissions to IAM users

    Even if you think a policy is just for one user, still make a group. You'll be amazed how quickly user policies become forgotten.

  • Grant least privilege

    If a user asks for read access to a single S3 bucket, do not grant s3:* on all resources, be specific with s3:GetObject and select the specific resource. It is easy to add further access later than restrict from wildcard.

  • Configure a strong password policy for your users

    Do you users even need access to the AWS Management console? If they do make sure the passwords are strong (and preferably stored in a password manager, not a post-it).

  • Use roles for applications that run on Amazon EC2 instances

    Roles on EC2 remove the need for ever, ever including access keys on the instance or in code (which can all too easily end up in version control). Roles let you give the same permissions as a user but AWS rotates the keys three times a day. All AWS SDK's can obtain credentials from the instance meta-data, you do not need any extra code.

  • Delegate by using roles instead of by sharing credentials

    If you have multiple AWS accounts (common in larger companies) you can authenticate users from the other account to use your resources.

  • Rotate credentials regularly

    For users with access keys rotate them. This is a manual step, but you can have two active keys per user to enable a more seamless transition.

  • Remove unnecessary credentials

    If a user has left, or access requirements change delete the user, alter group memberships and edit the policies by group (so much easier when all your policies are in groups, not users).

  • Use policy conditions for extra security

    Conditions can include specific IP ranges or authenticated via MFA requirements. You can apply these to specific actions to ensure they are only performed from behind your corporate firewall, for example.

  • Keep a history of activity in your AWS account

    CloudTrail is a separate service but having a log of all API access (which includes IAM user information) is incredibly useful for an audit log and even debugging issues with your policies.

Federated users

The default in IAM is to create a new user, which is internal to AWS. You can use this user for any part of AWS. When an IAM user logs in they get a special login screen (via a special URL) to provide their username/password (not email address like the root account). To provide flexibility IAM can utilize 3rd party services for identity, for example Amazon/Facebook/Google (and other SAML providers). Another recent product is AWS Directory Service which lets you use your on-premise corporate identity (Microsoft Active Directory for example) as your identity provider. For mobile applications you should explore Amazon Cognito as this is especially designed for mobile and includes IAM integration. Regardless of your identity source, IAM is still core to managing the access to your AWS resources.

General tips

MFA (multi factor authentication) is available with IAM and highly recommended. One approach you could adopt is:

  • Physical for the root account, they are not expensive.
  • Power users (what ever you define as a power user) use a virtual MFA (like Google Authenticator or Duo Security).
  • Users will less potential destructive access have no MFA.

A power user could have access to everything except IAM, as shown below. Learn more about the policy grammar, which is JSON based, on this blog post.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "NotAction": "iam:*",
          "Resource": "*"
        }
      ]
    }

Advanced policies include the use of resource-level permissions and tags, a good example from the EC2 documentation looks like:

{
   "Version": "2012-10-17",
   "Statement": [
   {
   "Effect": "Allow",
      "Action": "ec2:DescribeInstances",
      "Resource": "*"
   },
   {
      "Effect": "Allow",
      "Action": [
        "ec2:StopInstances", 
        "ec2:StartInstances"
      ],
      "Resource": [
      "arn:aws:ec2:us-east-1:123456789012:instance/i-123abc12",
      "arn:aws:ec2:us-east-1:123456789012:instance/i-4c3b2a1"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "ec2:TerminateInstances",
      "Resource": "arn:aws:ec2:us-east-1:123456789012:instance/*",
      "Condition": {
         "StringEquals": {
            "ec2:ResourceTag/purpose": "test"
         }
      }
   }

   ]
}

This policy allows the user to describe any EC2 instance, to stop or start two instances (i-123abc12 and i-4c3b2a1) and to terminate any instance with the tag purpose set to test. This is particularly useful if you want to restrict your users to your development EC2 instances, but not have access to your production instances. Resource-level permissions often a great deal of flexibility in your policies. A combination of tags and resource-level permissions are AWS preferred approach to writing these more complex policies.

While the policies can get complex here are some final tips:

  • When writing your policies AWS provides templates which can be a good starting place.
  • The IAM Policy Simulator is very handy at testing your policies.
  • Changes to IAM can take a few minutes to propagate, but IAM is not a service you should be changing constantly.
  • 3rd party resources that require access to your AWS resources should each use their own IAM account and access keys.
  • Use IAM in preference to S3 ACL or bucket policies (although there are specific exceptions - such as CloudFront access)
  • IAM support is not complete across all AWS products, get the latest information here.

Conclusions

IAM is a powerful service that can assist you manage and restrict access to your AWS resources. While the initial setup can be tricky getting the correct policies, once saved as groups you will be set. Time invested in IAM now could save you from an embarrassing situation later. Hopefully this article touches on the various aspects of IAM and some are directly appropriate for your use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment