Skip to content

Instantly share code, notes, and snippets.

@abiydv
Last active June 3, 2022 18:00
Show Gist options
  • Save abiydv/88f007f5c2555e5e8db8a7f0002bb730 to your computer and use it in GitHub Desktop.
Save abiydv/88f007f5c2555e5e8db8a7f0002bb730 to your computer and use it in GitHub Desktop.
{
"version": "",
"accountId": "",
"configurationItemCaptureTime": "",
"configurationItemStatus": "",
"configurationStateId": "",
"configurationItemMD5Hash": "",
"arn": "",
"resourceType": "",
"resourceId": "",
"awsRegion": "",
"availabilityZone": "",
"resourceCreationTime": "",
"tags": {
"department": "security",
"environment": "development",
"contact": "aperson@company.org"
},
"relatedEvents": [],
"relationships": [],
"configuration": {},
"supplementaryConfiguration": {}
}
{
"version": "",
"accountId": "",
"configurationItemCaptureTime": "",
"configurationItemStatus": "",
"configurationStateId": "",
"configurationItemMD5Hash": "",
"arn": "",
"resourceType": "",
"resourceId": "",
"awsRegion": "",
"availabilityZone": "",
"resourceCreationTime": "",
"tags": {
"department": "security",
"environment": "development",
"contact": "apersoncompany.org"
},
"relatedEvents": [],
"relationships": [],
"configuration": {},
"supplementaryConfiguration": {}
}

Valid event evaluation(s)

Full output of evaluation result

$ opa eval -d opa_tags.rego -i input.json  "data.tags"
{
  "result": [
    {
      "expressions": [
        {
          "value": {
            "compliant": true,
            "mandatory_tags": {
              "contact": "^[a-z]+@company.org$",
              "department": "^[a-z0-9_-]+$",
              "environment": "^(development|pre-production|production)$"
            },
            "violation": []
          },
          "text": "data.tags",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}

Invalid event evaluation(s)

Full output of evaluation result

$ opa eval -d opa_tags.rego -i invalid_input.json  "data.tags"
{
  "result": [
    {
      "expressions": [
        {
          "value": {
            "compliant": false,
            "mandatory_tags": {
              "contact": "^[a-z]+@company.org$",
              "department": "^[a-z0-9_-]+$",
              "environment": "^(development|pre-production|production)$"
            },
            "violation": [
              "tags in invalid format - contact"
            ]
          },
          "text": "data.tags",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}

Valid event evaluation(s)

Minimal output of evaluation result

$ opa eval -d opa_tags.rego -i input.json  "data.tags.compliant" --format pretty
true

Output violation desription as configured in the rule

$ opa eval -d opa_tags.rego -i input.json  "data.tags.violation" --format pretty
[]

Invalid event evaluation(s)

Minimal output of evaluation result

$ opa eval -d opa_tags.rego -i invalid_input.json  "data.tags.compliant" --format pretty
false

Output violation desription as configured in the rule

$ opa eval -d opa_tags.rego -i invalid_input.json  "data.tags.violation" --format pretty
[
  "tags in invalid format - contact"
]

Evaluate policy

Full output of evaluation result

$ opa eval -d opa_tags.rego -i input.json "data.tags"

Minimal output of evaluation result

$ opa eval -d opa_tags.rego -i input.json "data.tags.compliant" --format pretty

Output violation desription as configured in the rule

$ opa eval -d opa_tags.rego -i input.json "data.tags.violation" --format pretty

Test Policy

Run policy tests and output all debug/trace messages

$ opa test -d opa_tags.rego --explain full

Demo

OPA playground

References

# METADATA
# title: Tags
# description: Rules to check tag compliance for aws resources recorded in aws config.
# authors:
# - @abiydv
package tags
present(obj, k) { _ = obj[k] }
default compliant = false
compliant := true {
count(violation) == 0
}
mandatory_tags := {
"contact": "^[a-z]+@company.org$",
"department": "^[a-z0-9_-]+$",
"environment": "^(development|pre-production|production)$"
}
violation["tags key not found in input"] {
not present(input, "tags")
}
violation[msg] {
tags := input.tags
missing_tags := { tag | mandatory_tags[tag]; not tags[tag] }
count(missing_tags) > 0
msg := sprintf("tags not present - %s", [concat(", ", missing_tags)])
}
violation[msg] {
tags := input.tags
format_tags := { tag | not regex.match(mandatory_tags[tag], tags[tag]); mandatory_tags[tag]; tags[tag] }
count(format_tags) > 0
msg := sprintf("tags in invalid format - %s", [concat(", ", format_tags)])
}
package tags
test_compliant_all_tags {
compliant with input as {
"tags": {
"contact": "aperson@company.org",
"department": "security",
"environment": "development"
}
}
}
test_not_compliant_partial_tags {
not compliant with input as {
"tags": {
"contact": "aperson@company.org",
"department": "security"
}
}
}
test_not_compliant_no_tags {
not compliant with input as {
"tags": {}
}
}
test_not_compliant_missing_tags {
not compliant with input as {
"id": "test"
}
}
test_not_compliant_format_contact_tag {
not compliant with input as {
"tags": {
"contact": "aperson",
"department": "security",
"environment": "development"
}
}
}
test_not_compliant_invalid_contact_tag {
not compliant with input as {
"tags": {
"contact": "aperson@gmail.com",
"department": "security",
"environment": "development"
}
}
}
test_not_compliant_format_department_tag {
not compliant with input as {
"tags": {
"contact": "aperson@company.org",
"department": "Security Team",
"environment": "development"
}
}
}
test_not_compliant_format_environment_tag {
not compliant with input as {
"tags": {
"contact": "aperson@company.org",
"department": "security",
"environment": "All"
}
}
}

Run tests

$ opa test *.rego -v

opa_tags_test.rego:
data.tags.test_compliant_all_tags: PASS (1.080197ms)
data.tags.test_not_compliant_partial_tags: PASS (556.393µs)
data.tags.test_not_compliant_no_tags: PASS (399.769µs)
data.tags.test_not_compliant_missing_tags: PASS (186.828µs)
data.tags.test_not_compliant_format_contact_tag: PASS (464.022µs)
data.tags.test_not_compliant_invalid_contact_tag: PASS (486.996µs)
data.tags.test_not_compliant_format_department_tag: PASS (461.976µs)
data.tags.test_not_compliant_format_environment_tag: PASS (511.026µs)
--------------------------------------------------------------------------------
PASS: 8/8

Check coverage

$ opa test *.rego --coverage | jq -r '.files | to_entries[] | select(.key) | "\(.key): \(.value.coverage)"'

opa_tags.rego: 100
opa_tags_test.rego: 100
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment