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
    Testing Cloud
    Provisioning with
    Terraform and InSpec
    Christoph Hartmann

    View full-size slide

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

    View full-size slide

  3. @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?

    View full-size slide

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

    View full-size slide

  5. @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?

    View full-size slide

  6. Deployment Setup
    Provisioning Verification

    View full-size slide

  7. @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"

    View full-size slide

  8. @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

    View full-size slide

  9. @chri_hartmann

    View full-size slide

  10. @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.

    View full-size slide

  11. @chri_hartmann
    Change Firewall Rules

    View full-size slide

  12. @chri_hartmann
    Change Firewall Rules

    View full-size slide

  13. @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"

    View full-size slide

  14. @chri_hartmann
    Terraform found the change!

    View full-size slide

  15. @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

    View full-size slide

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

    View full-size slide

  17. @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.

    View full-size slide

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

    View full-size slide

  19. @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

    View full-size slide

  20. @chri_hartmann
    Shared Testing Tooling & Language
    SECURITY
    DEVOPS
    COMPLIANCE

    View full-size slide

  21. @chri_hartmann
    Verify the provisioned infra with InSpec

    View full-size slide

  22. Deployment Setup
    Provisioning Verification

    View full-size slide

  23. @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

    View full-size slide

  24. @chri_hartmann
    Verify instances

    View full-size slide

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

    View full-size slide

  26. @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

    View full-size slide

  27. @chri_hartmann
    Verify cloud security

    View full-size slide

  28. Deployment Setup
    Provisioning Verification

    View full-size slide

  29. @chri_hartmann
    Let’s do this again

    View full-size slide

  30. @chri_hartmann
    InSpec Terraform Provisioner

    View full-size slide

  31. @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"
    }
    }

    View full-size slide

  32. @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"
    }
    }

    View full-size slide

  33. @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

    View full-size slide

  34. Deployment Setup
    Provisioning Verification

    View full-size slide

  35. @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 ✗ ✔

    View full-size slide

  36. @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

    View full-size slide

  37. @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

    View full-size slide

  38. All successfully tested with Terraform and InSpec
    Provisioning Verification

    View full-size slide

  39. 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

    View full-size slide

  40. @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

    View full-size slide

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

    View full-size slide

  42. 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

    View full-size slide

  43. InSpec helps to shift security concerns to the left
    Compliance
    DevOps

    View full-size slide

  44. @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

    View full-size slide

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

    View full-size slide