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"
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.
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"
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
'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
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
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 ✗ ✔
before the old is destroyed resource "digitalocean_droplet" "web" { ... lifecycle { create_before_destroy = true } } https://www.hashicorp.com/blog/zero-downtime-updates-with-terraform
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