Getting started with InSpec for AWS. Testing for the cloud!

With the introduction of InSpec 2.0, we got the ability to test AWS environments. Within the next 5 minutes, you are ready to write InSpec tests to verify your AWS environment. Let’s start.

Background

Dominik already introduced the new concepts of InSpec 2.0. He and I created InSpec for machine testing but abstracted InSpec’s test syntax from specific test targets. This is very helpful, since the same language can be used to describe tests for machine and api testing.

A simple test for an operating system package can be written like:

# test for os package
describe package('telnetd') do
  it { should_not be_installed }
end

InSpec CLI can easily execute this test locally or remotely with:

# run test locally, local execution is implicit
inspec exec test.rb

# run test on docker container
inspec exec test.rb -t docker://container_id

A test to verify that a EC2 instance exists and is running is written as following:

# test for aws ec2
describe aws_ec2_instance('i-01a2349e94458a507') do
  it { should exist }
  it { should be_running }
end

Now, we target the AWS api instead of local, ssh, winrm or docker:

# run a profile targeting AWS using env vars
inspec exec test.rb -t aws://

While the first example is a test for an operating system, the second is a test for the AWS API. They follow the same concepts, you either target your tests to an operating system or an AWS API. InSpec is smart enough to know that a resource works for a given target.

InSpec detects the target platform
InSpec detects the target platform

In case you just want to play with InSpec for testing, I recommend using my inspec-playgroud container, since it includes InSpec and AWS CLI:

$ docker run -it chrisrock/inspec-playground
[root@b7a17c8c6dd4 /]# inspec version
2.1.10
[root@b7a17c8c6dd4 /]# aws --version
aws-cli/1.14.63 Python/2.7.5 Linux/4.9.60-linuxkit-aufs botocore/1.9.16

Create an AWS IAM user

To allow InSpec to talk to AWS, we need to create an IAM user in AWS console. If you have credentials already, skip to the next section. The following commands are executed on Linux but work similar on Windows and macOS. If you’ve never run AWS cli before, you should see an error message like:

[root@b7a17c8c6dd4 /]# aws iam get-user
Unable to locate credentials. You can configure credentials by running "aws configure".

Create new credentials within the IAM console by clicking on “add user”. Now enter your username and select programmatic access.

Create a new user
Create a new user

As the second step, we need to provide permissions to the user. Since InSpec is for testing only, ReadOnlyAccess is all you need.

Select IAM permissions
Select IAM permissions

Now, we need to confirm the configuration.

Review configuration
Review configuration

If everything goes well, you should see the confirmation page with the AWS Access Key and AWS Secret Access Key. Both are required for the next step.

IAM user creation confirmation
IAM user creation confirmation

Configure your AWS CLI

The AWS cli makes it very easy to configure AWS settings. InSpec is reading the same configuration files, therefore the AWS CLI works hand-in-hand with InSpec. No seperate configuration required.

[root@b7a17c8c6dd4 /]#  aws configure
AWS Access Key ID [None]:  AKIAXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: l1g3J+BAI1EWyyWR4c5n5xxxxxxxxxxxxxxxx
Default region name [None]: us-east-1
Default output format [None]:

Now, the aws cli created two config files:

[root@b7a17c8c6dd4 /]# ls ~/.aws/            
config  credentials
[root@b7a17c8c6dd4 /]# cat ~/.aws/config 
[default]
region = us-east-1
[root@b7a17c8c6dd4 /]# cat ~/.aws/credentials 
[default]
aws_access_key_id =  AKIAXXXXXXXXXXXXXXXXX
aws_secret_access_key = l1g3J+BAI1EWyyWR4c5n5xxxxxxxxxxxxxxxx

Verify that aws iam get-user can connect to AWS. You get a response, everything is configure properly.

[root@b7a17c8c6dd4 /]# aws iam get-user
{
    "User": {
        "UserName": "chris-rock", 
        "Path": "/", 
        "CreateDate": "2018-03-27T12:06:32Z", 
        "UserId": "AKIAXXXXXXXXXXXXXXXXX", 
        "Arn": "arn:aws:iam::112758395563:user/chris-rock"
    }
}

Run first AWS InSpec check

InSpec does not rely on AWS cli. It re-uses the same configuration files located in ~/.aws/config and ~/.aws/credentials though. Since we configured them already, we are ready to go.

Let’s create a new InSpec test file iam.rb with the following content

describe aws_iam_user(username: 'chris-rock') do
    it { should have_mfa_enabled }
    it { should_not have_console_password }
end

Execute that test with InSpec:

$ inspec exec iam.rb -t aws://

And voilà!

InSpec reports DevSec SSH Baseline to Chef Automate
InSpec reports DevSec SSH Baseline to Chef Automate

If you are using multiple AWS profiles you can define those in your ~/.aws/credentials file.

$ cat ~/.aws/credentials 
[auditing]
aws_access_key_id = AKIA....
aws_secret_access_key = 1234....abcd

You can use the AWS profile as an option for the inspec target -t aws://region/profile. For example, to connect to the Ohio region using a profile named auditing, use inspec exec iam.rb -t aws://us-east-2/auditing. Please have a look look at the InSpec Docs for more information.

Summary

Yeah! Within 5 minutes, we wrote our first InSpec test for AWS. InSpec ships with a lot of built-in AWS resources. You may also be interested to combine Terraform with InSpec as the next step.

Happy Wednesday! - Chris