How to Use CDK Outputs in Your InSpec Tests
Tags: aws, iac, cdk, inspec
Published: 2021-07-29 18:59:59

---
title: How to Use CDK Outputs in Your InSpec Tests
published: true
description: As a programmer, hard-coding values in my code, even test code, feels dirty and it's usually not a scalable practice. Instead of hard-coding resource IDs in your InSpec tests, you can add Outputs to a CDK app and push those values to a JSON file that your InSpec tests can use.
tags: ["aws", "iac", "cdk", "inspec"]
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5pssq9gut380njwyu37.png
canonical_url: https://jennapederson.com/blog/2021/7/29/how-to-use-cdk-outputs-in-your-inspec-tests/
---

As a programmer, hard-coding values in my code, even test code, feels dirty and it's usually not a scalable practice. I've built an AWS CDK app to manage my infrastructure with code and I'm starting to write some integration tests with [InSpec](https://docs.chef.io/inspec/), an open-source testing and auditing framework. Unlike my Jest unit tests that test the infrastructure code, these tests compare the desired state (what's in my InSpec test code) with the current state (what's in the cloud). This means they are testing directly against the cloud resources and I'll need access to the IDs of the resources I'm writing tests against. I could hard-code these IDs in my tests, like this:

```ruby
describe aws_ec2_instance("i-1234567890abcdef0") do
  it { should be_running }
end
```

Yuck!

As soon as I re-deploy the CDK code, these resources can be re-provisioned and the IDs can change. And if I'm running my CDK code through a CI/CD pipeline I'll need to run infrastructure tests against resources in different environments. Resource IDs will differ across environments and accounts, also making it difficult for another developer on my team to run the tests against their account. Either way, as a programmer, hard-coding these resource IDs in my test code doesn't feel right and it won't scale.

Instead, I can add Outputs to our CDK app and push those values to a JSON file that my InSpec tests can use. Let's take a look how to do that.

## Add CDK Outputs

First, I'll add an output to the CDK code to output the resource's ID, the EC2 instance ID.

```javascript
const ec2Instance = new ec2.Instance(this, 'ec2-instance', {
  ...
});
new cdk.CfnOutput(this, 'InstanceId', {
  value: ec2Instance.instanceId
});
```

## Deploy CDK App to Get Outputs.json

Next, I'll deploy the CDK app and push the output values to a JSON file that the InSpec profile can use. InSpec expects this file to be located in the profile's `files` directory.

```bash
$ cdk deploy --outputs-file inspec/files/outputs.json
```

## Use CDK Outputs as Inputs in InSpec

Finally, to use the CDK output values in the InSpec test control, I need to read this file using `inspec.profile.file`, parse the JSON, and reference the value in the test.

```ruby
control "01-ec2-instance" do
  impact 1.0
  title "Verify EC2 Instance is Running"

  json = inspec.profile.file('outputs.json')
  outputs = JSON.parse(json)

  INSTANCE_ID = outputs['MyStack']['InstanceId']

  describe aws_ec2_instance(INSTANCE_ID) do
    it { should be_running }
  end
end
```

## Wrapping Up

Now my tests rely on dynamic values rather than hard-coded values. These tests won't break the moment a resource gets swapped out or when I run tests in a different environment. If you're not using the CDK, you can follow the same process with other infrastructure as code frameworks as well.

Grab the code [here](https://github.com/jennapederson/infrastructure-test-examples) to get started with the CDK, Jest unit tests, or InSpec infrastructure testing.

_Like what you read? Follow me here on the [Dev.to community](https://dev.to/jennapederson) or give me a follow on [Twitter](https://twitter.com/jennapederson) to stay updated!_