Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing Cloud Provisioning with Terraform and InSpec

Testing Cloud Provisioning with Terraform and InSpec

This talks looks into Terraform and InSpec and how they can be combined effectively.

https://www.continuouslifecycle.de

Christoph Hartmann

November 15, 2018
Tweet

More Decks by Christoph Hartmann

Other Decks in Technology

Transcript

  1. @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?
  2. @chri_hartmann Agenda • Challenges with High-Velocity Deployments • Manage changes

    safely over time • Ensure that your deployments are configured securely • Summary
  3. @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?
  4. @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"
  5. @chri_hartmann Execute Deployment $ terraform apply plan.out digitalocean_ssh_key.key: Creating... fingerprint:

    "" => "<computed>" 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
  6. @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.
  7. @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"
  8. @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
  9. @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.
  10. @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
  11. @chri_hartmann Verify instances describe http('http://0.0.0.0/') do its('status') { should eq

    200 } its('body') { should match /<title>InSpec landing<\/title>/ } end
  12. @chri_hartmann InSpec Operating System Support Amazon Linux CentOS HP UX

    IBM AIX RHEL SLES Ubuntu Windows Debian Cisco IOS
  13. @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
  14. @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" } }
  15. @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" } }
  16. @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
  17. @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 ✗ ✔
  18. @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
  19. @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
  20. 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
  21. @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
  22. 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
  23. @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
  24. @chri_hartmann OpenSource Resources inspec.io • Hands on tutorials • Extensive

    documentation • Code examples dev-sec.io • Chef Cookbooks • InSpec Baselines