How To: Remove Developers from the AWS Console

By Blog, Integrations, Security
Gone are the days of sharing AWS root account credentials in a shared 1Password vault. Or worse, via email. Bringing new developers to the team increases our chances of the main credentials leaking or getting into the wrong hands. A root credential compromise is game over: an attacker has full access to your AWS account and can wreak havoc.On top of that, most employees don’t even need direct access to production systems in their day-to-day jobs. Having that access does nothing but significantly increase the risk of a security incident.We want to protect our sensitive systems, configure our accounts with a good baseline security posture, and engineer our security model in a way that ensures compromises are contained. The smaller the blast radius, the better. With this in mind, one of the first steps to securing our AWS account is setting up AWS IAM.

The Bare Minimum— locking down your AWS Account with IAM

IAM stands for identity and access management. IAM is at the core of the AWS permissions model, and is our first line of defense for securing sensitive resources in AWS. IAM allows us to create a directory of users within our AWS account, and we can apply carefully-crafted policies directly to users, or to groups in which users reside.Most importantly, IAM allows us to build our permission structure according to the principle of least privilege. What’s the principle of least privilege? It’s the practice of limiting access rights for users to the bare minimum permissions they need to perform their work.For example, if Developer A needs access to a development environment to SSH into servers and debug their application— they should have the ability to do so! But if we give them root account access, that developer would have superuser-level credentials and would be able to do anything within AWS: view billing information, delete databases, restart production instances, download S3 data, and more. With IAM, we can craft a specific set of permissions that give Developer A everything they need to get their job done, and nothing more.Let’s mock out an IAM policy for Developer A. We’ve identified that they need read-only access to the development environment, so they can look up IPs and SSH into development instances.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CanOnlyReadDevEnv",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeTags",
                "ec2:DescribeScheduledInstances",
                "ec2:DescribeInstances"
            ],
            "Resource": "*",
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "aws:RequestTag/env": "dev*"
                }
            }
        }
    ]
}
Applied to a user or group, this policy will allow Developer A to view the information they need, and restrict them from seeing any EC2 instance without the tag env == dev*. IAM is “deny by default,” meaning that a user is implicitly denied from any API operations unless a policy explicitly permits it.A few weeks later, Developer A requests access to the development database so they can make queries against the development database and gather data for the new feature branch that they’re building. The following policy allows read-only access (the Describe* suite of API calls) that can be applied to this developer’s AWS IAM user account.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ReadOnlyRDS",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBClusterParameters",
                "rds:DescribeDBEngineVersions",
                "rds:DescribeDBClusters",
                "rds:DescribeDBClusterParameterGroups"
            ],
            "Resource": "arn:aws:rds:*::cluster:dev*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "rds:DescribeDBInstances",
            "Resource": "*"
        }
    ]
}
It’s generally advised to keep IAM policies as small and cleanly-scoped as possible. With this, they can be combined together with multiple policies to build out a fully-featured permissions set for your developers.

CLI Tools Keep Credentials Siloed and Developers out of the Console

The second great advantage that AWS IAM gives us is a unique API keypair for each user provisioned within our account. With this, the blast radius of any developer’s keys getting compromised is limited to the permission scope that that developer has access to.Per-developer keypairs combined with CLI tools allow us to restrict or even completely eliminate console access for most users within the organization. There is an abundance of both first-party and third-party AWS tools that give developers access to the information that they need.

First-Party CLI Tooling

The AWS CLI, known in most package managers as awscli, is the first-party CLI for AWS built and maintained by a team at Amazon. It’s a Linux/Unix CLI that uses the powerful backend AWS SDK under the hood. This program is the Swiss Army Knife for anyone working with the AWS API. The AWS CLI has many advantages. First, all AWS services are supported on their launch day. This might seem like a minor point, but the ability to support script-based automation on day zero is a game-changer for many development teams. The AWS CLI also natively supports several methods of authentication: API Keys via environment variables, a credentials file stored on disk (usually in $HOME/.aws/credentials), or even an IAM instance profile assigned to an EC2 instance.However, the tool doesn’t come without downsides: it can be cumbersome to use. It’s not unusual for several options and arguments to be required for even the simplest of tasks. In most cases, the CLI returns large JSON blobs that require a bit of extra processing before they’re useful. For example, here’s the output from the command to describe EC2 instances.
$ aws ec2 describe-instances
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-deadbeef",
                    "InstanceId": "i-deadbeef",
                    "InstanceType": "c4.large",
                    "KeyName": "foo",
                    "LaunchTime": "2018-04-09T22:03:18.000Z",
                    "Monitoring": {
                        "State": "disabled"
                    },
                    "Placement": {
                        "AvailabilityZone": "us-east-1b",
                        "GroupName": "",
                        "Tenancy": "default"
                    },
                    "PrivateDnsName": "ip-127-0-0-1.ec2.internal",
                    "PrivateIpAddress": "127.0.0.1",
                    "ProductCodes": [],
                    "PublicDnsName": "",
                    "State": {
                        "Code": 16,
                        "Name": "running"
                    },
                    "StateTransitionReason": "",
                    "SubnetId": "subnet-deadbeef",
                    "VpcId": "vpc-deadbeef",
                    "Architecture": "x86_64",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2015-08-18T15:24:31.000Z",
                                "DeleteOnTermination": false,
                                "Status": "attached",
                                "VolumeId": "vol-deadbeef"
                            }
                        }
                    ],
...

...

...

And that’s just half of the data included in one instance’s JSON blob!

Third-Party CLI Tooling

Thankfully, due to the awesome nature of open source software, there are countless third-party tools that are available for developers who need to work with AWS. awless is a tool written for AWS’s EC2, VPC, and S3 APIs.The awless CLI tool provides a much simpler interface and returns data in an easy-to-read format, with the caveat that some of the data that AWS sends on-the-wire won’t be supported. Additionally, the maintainers of awless may decide to omit new information that is released with new versions of the API specifications.While third party tools can be great for ease-of-use and extra features, it’s always important to audit anything that uses your API keys to access remote resources.

Custom Tooling

If your organization is large enough to support a dedicated platform or tools team, then a bespoke CLI tool might be the best option. Creating a custom tool allows you to control the entire experience with regards to what services or API endpoints you expose to the tool’s users. WIth this, you can also restrict the tool’s API access to a specific user or role, allowing you complete control over the exact permissions scope.

Removing AWS from the equation— strongDM

Since we’ve identified our hypothetical developer’s primary AWS use-case as looking up server and database information, we can ask ourselves the question: do they even need AWS access at all?StrongDM provides us four things that satisfy all of our developer requirements:
  1. Server Inventory – servers registered with strongDM are visible the sdm CLI
  2. Database inventory – databases registered with strongDM are visible the sdm CLI. Both traditional SQL-based databases and noSQL (e.g. DynamoDB) are supported!
  3. RBAC (role-based access control) – administrators can choose to hide/show servers and datasources based on a user’s role membership
  4. Auditability – all SSH and database sessions are tracked and auditable

Wrapping Up

Talk to any security engineer about securing Amazon Web Services and they’ll tell you that the safest AWS account is one that doesn’t exist. While this is both funny and accurate, as much as it pains me to admit, it’s certainly not realistic. We need our developers to access remote cloud resources to get their jobs done, and ultimately get their features shipped.With that said, we have options! The bare minimum is securing our AWS account with IAM users, roles, and policies. From there, we can take advantage of the powerful AWS API by using either first-party tools (awscli) or open-source third-party tools made by other developers. For the folks who are determined to completely remove their development team from the AWS console, strongDM provides a perfect way to facilitate access without having them directly touch anything Amazon.
New call-to-action

Tagged under: