Slide 1

Slide 1 text

@chri_hartmann Testing Cloud Provisioning with Terraform and InSpec Christoph Hartmann

Slide 2

Slide 2 text

@chri_hartmann Christoph Hartmann Co-Creator InSpec & Dev-Sec.io Project Engineering Director Twitter: @chri_hartmann Github: chris-rock

Slide 3

Slide 3 text

@chri_hartmann Assumptions ● You use a tool like Terraform for your deployments ● You agree on infrastructure as code ● You agree that code should be tested ● How can we combine Terraform with testing?

Slide 4

Slide 4 text

@chri_hartmann Agenda ● Challenges with High-Velocity Deployments ● Manage changes safely over time ● Ensure that your deployments are configured securely ● Summary

Slide 5

Slide 5 text

@chri_hartmann High-Velocity Deployments QUALITY/COMPLIANCE RATE OF INNOVATION ● How do you automate your deployment? ● How do I introduce changes and updates safely? ● How do I make sure deployment updates are reliable?

Slide 6

Slide 6 text

Deployment Setup Provisioning Verification

Slide 7

Slide 7 text

@chri_hartmann Plan Deployment $ terraform plan -out plan.out Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ... Plan: 7 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ This plan was saved to: plan.out To perform exactly these actions, run the following command to apply: terraform apply "plan.out"

Slide 8

Slide 8 text

@chri_hartmann Execute Deployment $ terraform apply plan.out digitalocean_ssh_key.key: Creating... fingerprint: "" => "" name: "" => "Terraform Example" ... Apply complete! Resources: 6 added, 0 changed, 0 destroyed. Outputs: Id = 118465877 Load Balancer Public ip = 178.128.139.19 Name = nginx-web-ams3 Public ip = 206.189.101.99

Slide 9

Slide 9 text

@chri_hartmann

Slide 10

Slide 10 text

@chri_hartmann Verify Deployment $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. null_resource.inspec: Refreshing state... (ID: 917976163460846921) digitalocean_ssh_key.key: Refreshing state... (ID: 23510906) digitalocean_tag.web: Refreshing state... (ID: inspec-web) digitalocean_certificate.web: Refreshing state... (ID: 8a81fce0-9788-417d-92bf-4c7d5e37ecca) digitalocean_loadbalancer.public: Refreshing state... (ID: a5d6877e-7360-49b8-95ee-fdd128540ac1) digitalocean_droplet.crown: Refreshing state... (ID: 118465875) digitalocean_droplet.web: Refreshing state... (ID: 118465877) ------------------------------------------------------------------------ No changes. Infrastructure is up-to-date. This means that Terraform did not detect any differences between your configuration and real physical resources that exist. As a result, no actions need to be performed.

Slide 11

Slide 11 text

@chri_hartmann Change Firewall Rules

Slide 12

Slide 12 text

@chri_hartmann Change Firewall Rules

Slide 13

Slide 13 text

@chri_hartmann Change Firewall Rules $ terraform plan ... ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: ~ digitalocean_firewall.web inbound_rule.1029929102.port_range: "80" => "80" inbound_rule.1029929102.protocol: "tcp" => "tcp" inbound_rule.1029929102.source_addresses.#: "2" => "2" inbound_rule.1029929102.source_addresses.217649824: "0.0.0.0/0" => "0.0.0.0/0" inbound_rule.1029929102.source_addresses.4017721845: "::/0" => "::/0" inbound_rule.1029929102.source_droplet_ids.#: "0" => "0" inbound_rule.1029929102.source_load_balancer_uids.#: "0" => "0"

Slide 14

Slide 14 text

@chri_hartmann Terraform found the change!

Slide 15

Slide 15 text

@chri_hartmann There are shortcoming ... ● It can only test what is part of the deployment ● It can only do positive testing ● It is not testing the instances, or provisioned services itself

Slide 16

Slide 16 text

@chri_hartmann InSpec turns infrastructure testing, compliance and security requirements into code

Slide 17

Slide 17 text

@chri_hartmann Test: Documentation SSH supports two different protocol versions. The original version, SSHv1, was subject to a number of security issues. Please use SSHv2 instead to avoid these.

Slide 18

Slide 18 text

@chri_hartmann Test: InSpec describe sshd_config do its('Protocol') { should eq('2') } end

Slide 19

Slide 19 text

@chri_hartmann Test: Inspec + Metadata control 'sshd-10' do impact 1.0 title 'Server: Specify protocol version 2' desc "Only SSH protocol version 2 connections should be permitted. Version 1 of the protocol contains security vulnerabilities. Don't use legacy insecure SSHv1 connections anymore." describe sshd_config do its('Protocol') { should eq('2') } end end

Slide 20

Slide 20 text

@chri_hartmann Shared Testing Tooling & Language SECURITY DEVOPS COMPLIANCE

Slide 21

Slide 21 text

@chri_hartmann Verify the provisioned infra with InSpec

Slide 22

Slide 22 text

Deployment Setup Provisioning Verification

Slide 23

Slide 23 text

@chri_hartmann Verify instances describe http('http://0.0.0.0/') do its('status') { should eq 200 } its('body') { should match /InSpec landing<\/title>/ } end

Slide 24

Slide 24 text

@chri_hartmann Verify instances

Slide 25

Slide 25 text

@chri_hartmann InSpec Operating System Support Amazon Linux CentOS HP UX IBM AIX RHEL SLES Ubuntu Windows Debian Cisco IOS

Slide 26

Slide 26 text

@chri_hartmann Verify cloud security control 'only use https' do title 'verify that only https is used for load balancers' only_if { digitalocean_loadbalancers.exists? } digitalocean_loadbalancers.forwarding_rules.flatten.each { |rule| describe rule do its('entry_protocol') { should eq 'https' } its('entry_port') { should eq 443 } end } end

Slide 27

Slide 27 text

@chri_hartmann Verify cloud security

Slide 28

Slide 28 text

Deployment Setup Provisioning Verification

Slide 29

Slide 29 text

@chri_hartmann Let’s do this again

Slide 30

Slide 30 text

@chri_hartmann InSpec Terraform Provisioner

Slide 31

Slide 31 text

@chri_hartmann Verify Instance Deployment resource "digitalocean_droplet" "web" { ... provisioner "inspec" { profiles = [ "https://github.com/chris-rock/testing-4-cloud/blob/do_droplet_profile-0.1.0.tar.gz?raw=true", "supermarket://dev-sec/linux-baseline", "supermarket://dev-sec/ssh-baseline", ] reporter { name = "cli" } connection { type = "ssh" private_key = "${file("./id_rsa")}" user = "root" timeout = "2m" } on_failure = "continue" } }

Slide 32

Slide 32 text

@chri_hartmann Verify Cloud Deployment resource "null_resource" "inspec" { // runs inspec profile against digitial ocean cloud services provisioner "inspec" { profiles = [ "../do-security-profile", ] target { backend = "digitalocean" } reporter { name = "cli" } // we allow failures for now on_failure = "continue" } }

Slide 33

Slide 33 text

@chri_hartmann Verify Cloud Deployment droplet = attribute('digitalocean_droplet.web') loadbalancer = attribute('digitalocean_loadbalancer.public') describe digitalocean_droplet(id: droplet['id']) do it { should exist } its('name') { should eq 'nginx-web-ams3' } its('image') { should eq 'ubuntu-16-04-x64' } its('region') { should eq 'ams3' } its('size') { should eq 's-1vcpu-1gb' } end describe digitalocean_loadbalancer(name: 'loadbalancer-1') do it { should exist } its('name') { should eq 'loadbalancer-1' } its('status') { should eq 'active' } its('algorithm') { should eq 'round_robin' } its('ip') { should eq loadbalancer['ip'] } end

Slide 34

Slide 34 text

Deployment Setup Provisioning Verification

Slide 35

Slide 35 text

@chri_hartmann What to validate? Concern Terrafrom InSpec Type of instance requested ✔ ✔ Verify instances ✗ ✔ All instances are part of an app ✗ ✔ Security groups are correct ✔ ✔ No security group allows world access ✗ ✔ Load Balancer is setup correctly ✔ ✔ Ensure only one load balancer is used ✗ ✔

Slide 36

Slide 36 text

@chri_hartmann Bonus: Zero Downtime Updates Ensure new infrastructure is created before the old is destroyed resource "digitalocean_droplet" "web" { ... lifecycle { create_before_destroy = true } } https://www.hashicorp.com/blog/zero-downtime-updates-with-terraform

Slide 37

Slide 37 text

@chri_hartmann Bonus: Zero Downtime Updates Ensure instances are deployed properly: resource "digitalocean_droplet" "web" { … provisioner "inspec" { profiles = [ "https://profiles/do_droplet_profile-0.1.0.tar.gz", "supermarket://dev-sec/linux-baseline", "supermarket://dev-sec/ssh-baseline", ] lifecycle { create_before_destroy = true } } https://www.hashicorp.com/blog/zero-downtime-updates-with-terraform

Slide 38

Slide 38 text

All successfully tested with Terraform and InSpec Provisioning Verification

Slide 39

Slide 39 text

InSpec’s Extension Mechanism CLI and Platform Plugins Terraform Provisioner Plugin terraform plugin github: inspec/terraform-provisioner-inspec inspec terraform cli plugin github: inspec/inspec-iggy

Slide 40

Slide 40 text

@chri_hartmann Cloud Platform Support ● InSpec is integrated in Azure Shell and part of Azure Policy's Guest Configuration ● InSpec is Integrated into AWS EC2 Run Command ● InSpec integrates with PowerClI

Slide 41

Slide 41 text

@chri_hartmann New: Support for Google Cloud Platform github: inspec/inspec-gcp

Slide 42

Slide 42 text

InSpec’s Extension Mechanism (Current) My CIS L1 (inspec overlay) CIS Lvl1 (inspec) DevSec Windows Patch Baseline DevSec Linux Baseline DevSec Windows Baseline DevSec Linux Patch Baseline Profile 1 Profile 2 Resource Pack Profile Inheritance Wrapper Profiles Resource Packs

Slide 43

Slide 43 text

InSpec helps to shift security concerns to the left Compliance DevOps

Slide 44

Slide 44 text

@chri_hartmann Wrap-up ● You’ve seen how Terraform and InSpec work hand-in-hand ● The approach works with AWS, Azure, GCP etc as well. ● It makes your cloud deployments more reliable ● By combining Terraform with InSpec, you can ensure deployments are secure ● It’s easy to verify instance provisioning during a Terraform run ● Bonus: It helps to align DevOps, Security and Compliance teams

Slide 45

Slide 45 text

@chri_hartmann OpenSource Resources inspec.io • Hands on tutorials • Extensive documentation • Code examples dev-sec.io • Chef Cookbooks • InSpec Baselines