Skip to content

Commit

Permalink
Merge pull request #188 from nikpivkin/go2rego-digitalocean-1
Browse files Browse the repository at this point in the history
refactor(checks): migrate DigitalOcean spaces to Rego
  • Loading branch information
simar7 authored Aug 22, 2024
2 parents f49bf32 + f9256c9 commit e5ffd71
Show file tree
Hide file tree
Showing 17 changed files with 326 additions and 231 deletions.
3 changes: 2 additions & 1 deletion avd_docs/digitalocean/spaces/AVD-DIG-0006/docs.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

Space bucket and bucket object permissions should be set to deny public access unless explicitly required.


### Impact
The contents of the space can be accessed publicly
<!-- Add Impact here -->

<!-- DO NOT CHANGE -->
{{ remediationActions }}
Expand Down
3 changes: 2 additions & 1 deletion avd_docs/digitalocean/spaces/AVD-DIG-0007/docs.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

Versioning is a means of keeping multiple variants of an object in the same bucket. You can use the Spaces (S3) Versioning feature to preserve, retrieve, and restore every version of every object stored in your buckets. With versioning you can recover more easily from both unintended user actions and application failures.


### Impact
Deleted or modified data would not be recoverable
<!-- Add Impact here -->

<!-- DO NOT CHANGE -->
{{ remediationActions }}
Expand Down
3 changes: 2 additions & 1 deletion avd_docs/digitalocean/spaces/AVD-DIG-0009/docs.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

Enabling force destroy on a Spaces bucket means that the bucket can be deleted without the additional check that it is empty. This risks important data being accidentally deleted by a bucket removal process.


### Impact
Accidental deletion of bucket objects
<!-- Add Impact here -->

<!-- DO NOT CHANGE -->
{{ remediationActions }}
Expand Down
3 changes: 2 additions & 1 deletion checks/cloud/digitalocean/spaces/acl_no_public_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ var CheckAclNoPublicRead = rules.Register(
Links: terraformAclNoPublicReadLinks,
RemediationMarkdown: terraformAclNoPublicReadRemediationMarkdown,
},
Severity: severity.Critical,
Severity: severity.Critical,
Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, bucket := range s.DigitalOcean.Spaces.Buckets {
Expand Down
45 changes: 45 additions & 0 deletions checks/cloud/digitalocean/spaces/acl_no_public_read.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# METADATA
# title: Spaces bucket or bucket object has public read acl set
# description: |
# Space bucket and bucket object permissions should be set to deny public access unless explicitly required.
# scope: package
# schemas:
# - input: schema["cloud"]
# related_resources:
# - https://docs.digitalocean.com/reference/api/spaces-api/#access-control-lists-acls
# custom:
# id: AVD-DIG-0006
# avd_id: AVD-DIG-0006
# provider: digitalocean
# service: spaces
# severity: CRITICAL
# short_code: acl-no-public-read
# recommended_action: Apply a more restrictive ACL
# input:
# selector:
# - type: cloud
# subtypes:
# - service: spaces
# provider: digitalocean
# terraform:
# links:
# - https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/spaces_bucket#acl
# - https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/spaces_bucket_object#acl
# good_examples: checks/cloud/digitalocean/spaces/acl_no_public_read.tf.go
# bad_examples: checks/cloud/digitalocean/spaces/acl_no_public_read.tf.go
package builtin.digitalocean.spaces.digitalocean0006

import rego.v1

deny contains res if {
some bucket in input.digitalocean.spaces.buckets
bucket.acl.value == "public-read"
res := result.new("Bucket is publicly exposed.", bucket.acl)
}

deny contains res if {
some bucket in input.digitalocean.spaces.buckets
some object in bucket.objects
object.acl.value == "public-read"
res := result.new("Object is publicly exposed.", object.acl)
}
89 changes: 0 additions & 89 deletions checks/cloud/digitalocean/spaces/acl_no_public_read_test.go

This file was deleted.

37 changes: 37 additions & 0 deletions checks/cloud/digitalocean/spaces/acl_no_public_read_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package builtin.digitalocean.spaces.digitalocean0006_test

import rego.v1

import data.builtin.digitalocean.spaces.digitalocean0006 as check
import data.lib.test

test_allow_acl_private_for_bucket if {
inp := {"digitalocean": {"spaces": {"buckets": [{"acl": {"value": "private"}}]}}}

res := check.deny with input as inp
res == set()
}

test_deny_acl_public_read_for_bucket if {
inp := {"digitalocean": {"spaces": {"buckets": [{"acl": {"value": "public-read"}}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_allow_private_acl_for_object if {
inp := {"digitalocean": {"spaces": {"buckets": [{"objects": [
{"acl": {"value": "private"}},
{"acl": {"value": "aws-exec-read"}},
]}]}}}

res := check.deny with input as inp
res == set()
}

test_deny_public_read_acl_for_object if {
inp := {"digitalocean": {"spaces": {"buckets": [{"objects": [{"acl": {"value": "public-read"}}]}]}}}

res := check.deny with input as inp
count(res) == 1
}
3 changes: 2 additions & 1 deletion checks/cloud/digitalocean/spaces/disable_force_destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ var CheckDisableForceDestroy = rules.Register(
Links: terraformDisableForceDestroyLinks,
RemediationMarkdown: terraformDisableForceDestroyRemediationMarkdown,
},
Severity: severity.Medium,
Severity: severity.Medium,
Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, bucket := range s.DigitalOcean.Spaces.Buckets {
Expand Down
35 changes: 35 additions & 0 deletions checks/cloud/digitalocean/spaces/disable_force_destroy.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# METADATA
# title: Force destroy is enabled on Spaces bucket which is dangerous
# description: |
# Enabling force destroy on a Spaces bucket means that the bucket can be deleted without the additional check that it is empty. This risks important data being accidentally deleted by a bucket removal process.
# scope: package
# schemas:
# - input: schema["cloud"]
# custom:
# id: AVD-DIG-0009
# avd_id: AVD-DIG-0009
# provider: digitalocean
# service: spaces
# severity: MEDIUM
# short_code: disable-force-destroy
# recommended_action: Don't use force destroy on bucket configuration
# input:
# selector:
# - type: cloud
# subtypes:
# - service: spaces
# provider: digitalocean
# terraform:
# links:
# - https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/spaces_bucket#force_destroy
# good_examples: checks/cloud/digitalocean/spaces/disable_force_destroy.tf.go
# bad_examples: checks/cloud/digitalocean/spaces/disable_force_destroy.tf.go
package builtin.digitalocean.spaces.digitalocean0009

import rego.v1

deny contains res if {
some bucket in input.digitalocean.spaces.buckets
bucket.forcedestroy.value == true
res := result.new("Bucket has force-destroy enabled.", bucket.forcedestroy)
}
65 changes: 0 additions & 65 deletions checks/cloud/digitalocean/spaces/disable_force_destroy_test.go

This file was deleted.

20 changes: 20 additions & 0 deletions checks/cloud/digitalocean/spaces/disable_force_destroy_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package builtin.digitalocean.spaces.digitalocean0009_test

import rego.v1

import data.builtin.digitalocean.spaces.digitalocean0009 as check
import data.lib.test

test_allow_force_destroy_disabled if {
inp := {"digitalocean": {"spaces": {"buckets": [{"forcedestroy": {"value": false}}]}}}

res := check.deny with input as inp
res == set()
}

test_deny_force_destroy_enabled if {
inp := {"digitalocean": {"spaces": {"buckets": [{"forcedestroy": {"value": true}}]}}}

res := check.deny with input as inp
count(res) == 1
}
3 changes: 2 additions & 1 deletion checks/cloud/digitalocean/spaces/versioning_enabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ var CheckVersioningEnabled = rules.Register(
Links: terraformVersioningEnabledLinks,
RemediationMarkdown: terraformVersioningEnabledRemediationMarkdown,
},
Severity: severity.Medium,
Severity: severity.Medium,
Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, bucket := range s.DigitalOcean.Spaces.Buckets {
Expand Down
37 changes: 37 additions & 0 deletions checks/cloud/digitalocean/spaces/versioning_enabled.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# METADATA
# title: Spaces buckets should have versioning enabled
# description: |
# Versioning is a means of keeping multiple variants of an object in the same bucket. You can use the Spaces (S3) Versioning feature to preserve, retrieve, and restore every version of every object stored in your buckets. With versioning you can recover more easily from both unintended user actions and application failures.
# scope: package
# schemas:
# - input: schema["cloud"]
# related_resources:
# - https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html
# custom:
# id: AVD-DIG-0007
# avd_id: AVD-DIG-0007
# provider: digitalocean
# service: spaces
# severity: MEDIUM
# short_code: versioning-enabled
# recommended_action: Enable versioning to protect against accidental or malicious removal or modification
# input:
# selector:
# - type: cloud
# subtypes:
# - service: spaces
# provider: digitalocean
# terraform:
# links:
# - https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/spaces_bucket#versioning
# good_examples: checks/cloud/digitalocean/spaces/versioning_enabled.tf.go
# bad_examples: checks/cloud/digitalocean/spaces/versioning_enabled.tf.go
package builtin.digitalocean.spaces.digitalocean0007

import rego.v1

deny contains res if {
some bucket in input.digitalocean.spaces.buckets
bucket.versioning.enabled.value == false
res := result.new("Bucket does not have versioning enabled.", bucket.versioning.enabled)
}
Loading

0 comments on commit e5ffd71

Please sign in to comment.