Slide 1

Slide 1 text

Testing Cloud Infrastructure Ladislav Prskavec Ladislav Prskavec - Teststack conference, 6. 6. 2019 1

Slide 2

Slide 2 text

Who Am I 4 SRE Team leader in Oracle + Apiary (Oracle Cloud Development) 4 Twitter: @abtris 4 Blog and talks: https://blog.prskavec.net/ 4 Golang Prague organizer (@GoMeetupPrague) 4 HiveTalks meetups co-founder 4 PragueJS founder (2012-2016) Ladislav Prskavec - Teststack conference, 6. 6. 2019 2

Slide 3

Slide 3 text

Approach to get better reliability 4 Testing 4 Automation 4 Prevention Ladislav Prskavec - Teststack conference, 6. 6. 2019 3

Slide 4

Slide 4 text

Compliance Ladislav Prskavec - Teststack conference, 6. 6. 2019 4

Slide 5

Slide 5 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 5

Slide 6

Slide 6 text

Regulatory Compliance Ladislav Prskavec - Teststack conference, 6. 6. 2019 6

Slide 7

Slide 7 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 7

Slide 8

Slide 8 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 8

Slide 9

Slide 9 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 9

Slide 10

Slide 10 text

Compliance as Code 4 Defining Policies Upfront 4 Automated Gates and Checks 4 Managing Changes in Continuous Delivery 4 Separation of Duties in the DevOps Audit Toolkit 4 Using the Audit Defense Toolkit 4 Code Instead of Paperwork Ladislav Prskavec - Teststack conference, 6. 6. 2019 10

Slide 11

Slide 11 text

Chef Inspec framework www.inspec.io Ladislav Prskavec - Teststack conference, 6. 6. 2019 11

Slide 12

Slide 12 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 12

Slide 13

Slide 13 text

Define policies Ladislav Prskavec - Teststack conference, 6. 6. 2019 13

Slide 14

Slide 14 text

How to start Ladislav Prskavec - Teststack conference, 6. 6. 2019 14

Slide 15

Slide 15 text

DevSec Hardening Framework Baselines Ladislav Prskavec - Teststack conference, 6. 6. 2019 15

Slide 16

Slide 16 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 16

Slide 17

Slide 17 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 17

Slide 18

Slide 18 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 18

Slide 19

Slide 19 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 19

Slide 20

Slide 20 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 20

Slide 21

Slide 21 text

Automate audit Ladislav Prskavec - Teststack conference, 6. 6. 2019 21

Slide 22

Slide 22 text

Metrics # HELP inspec_checks_total Number of inspec checks # TYPE inspec_checks_total gauge inspec_checks_total{profile="ssl-baseline",status="passed"} 6 inspec_checks_total{profile="ssl-baseline",status="failed"} 0 inspec_checks_total{profile="ssl-baseline",status="skipped"} 0 4 prometheus_inspec_exporter by Dave Cadwallader Ladislav Prskavec - Teststack conference, 6. 6. 2019 22

Slide 23

Slide 23 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 23

Slide 24

Slide 24 text

Infrastructure as Software & Code Ladislav Prskavec - Teststack conference, 6. 6. 2019 24

Slide 25

Slide 25 text

Infrastructure as Software 4 Pulumi.io - various languages 4 AWS Cloud Development Kit using CloudFormation - various languages Ladislav Prskavec - Teststack conference, 6. 6. 2019 25

Slide 26

Slide 26 text

$ brew install pulumi $ pulumi version v0.17.14 $ mkdir webserver && cd webserver $ pulumi new aws-javascript ... aws:region: (us-east-1) Ladislav Prskavec - Teststack conference, 6. 6. 2019 26

Slide 27

Slide 27 text

const aws = require("@pulumi/aws"); let size = "t2.micro"; // t2.micro is available in the AWS free tier let ami = "ami-0ff8a91507f77f867"; // AMI for Amazon Linux in us-east-1 (Virginia) let group = new aws.ec2.SecurityGroup("webserver-secgrp", { ingress: [ { protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"] }, ], }); let server = new aws.ec2.Instance("webserver-www", { instanceType: size, securityGroups: [ group.name ], // reference the security group resource above ami: ami, }); exports.publicIp = server.publicIp; exports.publicHostName = server.publicDns; Ladislav Prskavec - Teststack conference, 6. 6. 2019 27

Slide 28

Slide 28 text

$ pulumi up Previewing update of stack 'webserver-dev' Previewing changes: Type Name Plan Info + pulumi:pulumi:Stack webserver-webserver-dev create + ├─ aws:ec2:SecurityGroup webserver-secgrp create + └─ aws:ec2:Instance webserver-www create info: 3 changes previewed: + 3 resources to create Ladislav Prskavec - Teststack conference, 6. 6. 2019 28

Slide 29

Slide 29 text

Infrastructure as Code Ladislav Prskavec - Teststack conference, 6. 6. 2019 29

Slide 30

Slide 30 text

Variety tools for work with infrastructure 4 Chef (ruby) - testing with Kitchen 4 Puppet (DSL based on ruby) - Testing with beaker 4 Redhat Ansible (python) - Testing with molecule 4 Hashicorp Terraform (golang) - testing with Terratest 4 and many others Ladislav Prskavec - Teststack conference, 6. 6. 2019 30

Slide 31

Slide 31 text

Requirements Ladislav Prskavec - Teststack conference, 6. 6. 2019 31

Slide 32

Slide 32 text

Requirements 4 using git or another source control system to track changes 4 declarative syntax 4 easy to start 4 possibility extend and fix tools with you knowledge 4 good documentation, support and community Ladislav Prskavec - Teststack conference, 6. 6. 2019 32

Slide 33

Slide 33 text

Continues Delivery pipelines Ladislav Prskavec - Teststack conference, 6. 6. 2019 33

Slide 34

Slide 34 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 34

Slide 35

Slide 35 text

The Challenge Ladislav Prskavec - Teststack conference, 6. 6. 2019 35

Slide 36

Slide 36 text

The Solution Ladislav Prskavec - Teststack conference, 6. 6. 2019 36

Slide 37

Slide 37 text

Ladislav Prskavec - Teststack conference, 6. 6. 2019 37

Slide 38

Slide 38 text

resource "aws_elb" "frontend" { name = "frontend-load-balancer" listener { instance_port = 8000 instance_protocol = "http" lb_port = 80 lb_protocol = "http" } instances = ["${aws_instance.app.*.id}"] } resource "aws_instance" "app" { count = 5 ami = "ami-408c7f28" instance_type = "t1.micro" } Ladislav Prskavec - Teststack conference, 6. 6. 2019 38

Slide 39

Slide 39 text

Terratest Ladislav Prskavec - Teststack conference, 6. 6. 2019 39

Slide 40

Slide 40 text

terraformOptions := &terraform.Options { // The path to where your Terraform code is located TerraformDir: "../examples/terraform-basic-example", } // At the end of the test, run `terraform destroy` to clean up any resources that were created defer terraform.Destroy(t, terraformOptions) // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) // Validate your code works as expected validateServerIsWorking(t, terraformOptions) Ladislav Prskavec - Teststack conference, 6. 6. 2019 40

Slide 41

Slide 41 text

--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.15.7 ports: - containerPort: 80 --- kind: Service apiVersion: v1 metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP targetPort: 80 port: 80 type: NodePort Ladislav Prskavec - Teststack conference, 6. 6. 2019 41

Slide 42

Slide 42 text

package test import (...) // An example of how to test the Kubernetes resource config in examples/kubernetes-basic-example using Terratest. func TestKubernetesBasicExample(t *testing.T) { t.Parallel() // Path to the Kubernetes resource config we will test kubeResourcePath, err := filepath.Abs("../examples/kubernetes-basic-example/nginx-deployment.yml") require.NoError(t, err) options := k8s.NewKubectlOptions("", "") namespaceName := fmt.Sprintf("kubernetes-basic-example-%s", strings.ToLower(random.UniqueId())) k8s.CreateNamespace(t, options, namespaceName) // Make sure we set the namespace on the options options.Namespace = namespaceName defer k8s.DeleteNamespace(t, options, namespaceName) // At the end of the test, run `kubectl delete -f RESOURCE_CONFIG` to clean up any resources that were created. defer k8s.KubectlDelete(t, options, kubeResourcePath) // This will run `kubectl apply -f RESOURCE_CONFIG` and fail the test if there are any errors k8s.KubectlApply(t, options, kubeResourcePath) service := k8s.GetService(t, options, "nginx-service") require.Equal(t, service.Name, "nginx-service") } Ladislav Prskavec - Teststack conference, 6. 6. 2019 42

Slide 43

Slide 43 text

$ go test -v -tags kubernetes -run TestKubernetesBasicExample === RUN TestKubernetesBasicExampleServiceCheck === PAUSE TestKubernetesBasicExampleServiceCheck === RUN TestKubernetesBasicExample === PAUSE TestKubernetesBasicExample === CONT TestKubernetesBasicExampleServiceCheck === CONT TestKubernetesBasicExample --- PASS: TestKubernetesBasicExample (6.70s) PASS exit status 0 PASS github.com/gruntwork-io/terratest/test 7.820s Ladislav Prskavec - Teststack conference, 6. 6. 2019 43

Slide 44

Slide 44 text

Summary 4 Infrastructure as Code 4 Infrastructure as Software 4 Compliance as Code Ladislav Prskavec - Teststack conference, 6. 6. 2019 44

Slide 45

Slide 45 text

Q & A Or ask on twitter: @abtris Ladislav Prskavec - Teststack conference, 6. 6. 2019 45