Slide 1

Slide 1 text

1

Slide 2

Slide 2 text

Catching Commits to Secure Infrastructure as Code May 23, 2023 2

Slide 3

Slide 3 text

OWASP Secure Coding Practices ● Input Validation ● Output Encoding ● Authentication and Password Management ● Session Management ● Access Control ● Cryptographic Practices ● Error Handling and Logging ● Data Protection ● Communication Security ● System Configuration ● Database Security ● File Management ● Memory Management ● General Coding Practices https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/ 3

Slide 4

Slide 4 text

What about infrastructure as code? 4

Slide 5

Slide 5 text

Rosemary Wang Developer Advocate, HashiCorp joatmon08.github.io @joatmon08 5

Slide 6

Slide 6 text

How do you write secure infrastructure as code? 6

Slide 7

Slide 7 text

Security Testing Static Analysis ● “Shift-left” security testing ● Policy as code ● Unit / contract testing for security Dynamic Analysis ● Vulnerability scanning ● Continuous validation ● Security monitoring 7

Slide 8

Slide 8 text

Infrastructure as Code Infrastructure Environment FIX Allow traffic from database to DR site. RECONCILE Add rule to allow traffic from database to DR site. A region has an outage. 8

Slide 9

Slide 9 text

Static Analysis Dynamic Analysis For you to fix quickly and maintain security requirements For someone else to know what security requirements exist 9

Slide 10

Slide 10 text

Capture security knowledge as tests. 10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

What commits to catch? Static Analysis Dynamic Analysis Input Validation Data Protection System Configuration 12

Slide 13

Slide 13 text

Input Validation 13

Slide 14

Slide 14 text

Input Validation Verify… ● Expected types ● Expected values ● Proper character sets ● Potentially insecure values Static analysis 14

Slide 15

Slide 15 text

Input Validation Examples: ● Password should have at least 1 symbol and 1 uppercase character. ● Region should be in United States. ● Private CA certificate key should be marked as sensitive. ● Names should include standard environment. 15

Slide 16

Slide 16 text

Input Validation Variable Validation Better for… ● Team ● Provider ● Modules Unit Test Better for… ● Multiple providers ● Organizational policy ● Dependencies 16

Slide 17

Slide 17 text

variable "region" { type = string description = "AWS Region" validation { condition = can(regex("^us-", var.region)) error_message = "AWS Region must be in United States" } } Variable Validation 17

Slide 18

Slide 18 text

resource "random_string" "boundary" { ## omitted lifecycle { precondition { condition = random_string.boundary.length > 3 error_message = "HCP Boundary requires username to be at least 3 characters in length" } } } Variable Validation, Inline with PreCondition 18

Slide 19

Slide 19 text

deny[msg] { r := tfplan.variables r.aws_secret_access_key msg := "do not define AWS secret access key as part of variables, use AWS_SECRET_ACCESS_KEY environment variable instead" } Unit Test with OPA 19

Slide 20

Slide 20 text

Data Protection 20

Slide 21

Slide 21 text

Data Protection ● Implement access controls to state ○ Data ○ State ● Encrypt in transit and at rest. ● Sanitize sensitive values in logs or outputs ● Ensure least privilege access to providers Static analysis Dynamic analysis 21

Slide 22

Slide 22 text

Data Protection Examples: ● Database should be encrypted. ● Password should not be printed in output. ● Virtual machine resource should have attached IAM role. ● Infrastructure state should be limited to owners of workspace. 22

Slide 23

Slide 23 text

Data Protection Static Analysis Better for… ● Enforcement of secure practices ● Testing valid dependencies Dynamic Analysis Better for… ● Least-privilege API access ● Continuous enforcement ● Auditing data access 23

Slide 24

Slide 24 text

deny[msg] { r := resource_changes[_] r.type == "aws_db_instance" r.change.after.storage_encrypted == "" msg := sprintf("%v should have encrypted storage", [r.address]) } Static Analysis of Attributes with OPA 24

Slide 25

Slide 25 text

deny[msg] { outputs := planned_values.outputs plaintext_password_outputs := [key | outputs[key] contains(key, "password") not outputs[key].sensitive ] count(plaintext_password_outputs) != 0 msg := sprintf("%v should be marked as sensitive outputs", [plaintext_password_outputs]) } Static Analysis of Practices with OPA25

Slide 26

Slide 26 text

resource "aws_db_instance" "products" { ## omitted storage_encrypted = true lifecycle { postcondition { condition = self.storage_encrypted error_message = "encrypt AWS RDS database storage" } } } Continuous Enforcement with PostCondition 26

Slide 27

Slide 27 text

System Configuration 27

Slide 28

Slide 28 text

System Configuration ● Check versions or images ● Ensure least privilege network access ● Separate development and production ● Analyze vulnerabilities and access ● Assess drift ● Remove idle / unused resources Need dynamic analysis 28

Slide 29

Slide 29 text

System Configuration Examples: ● Separate state for development and production. ● Verify network policies and secure versions. ● Tags should include environment. ● Image should include secure base. ● Scan running infrastructure for new vulnerabilities. 29

Slide 30

Slide 30 text

System Configuration Static Analysis Better for… ● Enforcement of secure practices ● Complex logic for validation ● Testing valid dependencies Dynamic Analysis Better for… ● Network auditing ● Continuous validation ● Drift detection 30

Slide 31

Slide 31 text

deny[msg] { ## omitted logic to parse VPC private_subnets := {r.values.id | r := vpc_modules[_].resources[_] r.type == "aws_subnet" not r.values.map_public_ip_on_launch } public_subnets := cluster_subnet_ids - private_subnets count(public_subnets) != 0 msg := sprintf("EKS cluster %v should be in private subnets (%v are public subnets)", [cluster_id, public_subnets]) } More Complex Static Analysis with OPA 31

Slide 32

Slide 32 text

32

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

There’s more! 34

Slide 35

Slide 35 text

How do I share tests? ● Store tests in central location. ● Tag / name / number tests for relevance. ● Document secure configurations in tests. 35

Slide 36

Slide 36 text

How to catch commits? Plan Unit Test Apply Integration Test Static Analysis Dynamic Analysis Plan Unit Test Apply Integration Test Static Analysis Staging Production 36

Slide 37

Slide 37 text

Do I write them all myself? Use pre-written test suites or industry benchmarks. Infrastructure modules Production configuration 1 Create custom policy tests. Divide by… ● Enforcement level ● Business unit ● Resource ● Type 2 37

Slide 38

Slide 38 text

38

Slide 39

Slide 39 text

What is important? ● Prefer secure defaults over tests. ● Choose a severity threshold. ○ Identify mandatory rules. ○ Use advisory as last resort. ○ Try to enforce development environments. ● Evaluate and make exceptions. 39

Slide 40

Slide 40 text

Conclusion 40

Slide 41

Slide 41 text

How do you write secure IaC? ● Capture practices into tests ● Share tests ● Catch commits using a pipeline ● Write what you must ● Choose what is important 41

Slide 42

Slide 42 text

Iterate Static Analysis Dynamic Analysis Break glass / drift Reconcile to infrastructure as code 42

Slide 43

Slide 43 text

More secure infrastructure as code over time. 43

Slide 44

Slide 44 text

Thank you! @joatmon08 ● github.com/joatmon08/hashicorp-stack-demoapp ● developer.hashicorp.com/terraform/tutorials/cloud-get-started/policy-quickstart ● openpolicyagent.org/docs/latest/terraform/ 44

Slide 45

Slide 45 text

45