Skip to content

Commit

Permalink
feat: add policy deny-snapshot-infinite-retention
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremychauvet committed Mar 28, 2024
0 parents commit 462d4b3
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.sentinel
.idea
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.PHONY: run-tests
.DEFAULT: run-tests

run-tests:
sentinel test ./policies/deny-snapshot-infinite-retention/deny-snapshot-infinite-retention.sentinel
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Sentinel policies for AWS Backup

This repository provide Sentinel policies for AWS Backup to be used on Terraform Cloud or Terraform Enterprise.

## Policies

| Scope | Rule | Description | Category | Enforcement level | Links |
|--------------|-----------------------------------|------------------------------------------------------------------------------------------------|----------|-------------------|----------------------------------------------------------|
| Backup rules | deny-snapshot-infinite-retention | Prevent creation or modification of a Backup Plan rule with an infinite retention of snapshots | FinOps | hard-mandatory | [doc](docs/policies/deny-snapshot-infinite-retention.md) |
47 changes: 47 additions & 0 deletions docs/policies/deny-snapshot-infinite-retention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Deny backup plans to keep snapshots forever

If a Backup Vault is locked in "compliance mode" and lifecycle not set to not expire snapshots (setting `delete_after`), the only option to delete it is to close the AWS account.

The following code will cause the test to fail:

```terraform
resource "aws_backup_vault" "main" {
name = "main"
}
resource "aws_backup_plan" "default" {
name = "sentinel-terraform-aws-backup"
rule {
rule_name = "keep-snapshots-forever"
target_vault_name = aws_backup_vault.main.name
schedule = "cron(0 12 * * ? *)"
lifecycle {
delete_after = 0 # Infinite.
}
}
}
```

To pass the test, the setting `delete_after` must be greater than 0:

```terraform
resource "aws_backup_vault" "main" {
name = "main"
}
resource "aws_backup_plan" "default" {
name = "sentinel-terraform-aws-backup"
rule {
rule_name = "keep-snapshots-forever"
target_vault_name = aws_backup_vault.main.name
schedule = "cron(0 12 * * ? *)"
lifecycle {
delete_after = 30 # days.
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import "tfplan/v2" as tfplan

backup_plans = filter tfplan.resource_changes as _, resource {
resource.mode == "managed" and
resource.type == "aws_backup_plan" and
(resource.change.actions contains "create" or resource.change.actions == ["update"])
}

main = rule {
all backup_plans as _, backup_plan {
all backup_plan.change.after.rule[0].lifecycle as _, lifecycle_settings {
lifecycle_settings.delete_after != 0
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mock "tfplan/v2" {
module {
source = "./mocks/mock-tfplan-snapshot-infinite-retention.sentinel"
}
}

test {
rules = {
main = false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
resource_changes = {
"aws_backup_plan.example": {
"address": "aws_backup_plan.example",
"change": {
"actions": [
"create",
],
"after": {
"advanced_backup_setting": [],
"name": "sentinel-terraform-aws-backup",
"rule": [
{
"completion_window": 180,
"copy_action": [],
"enable_continuous_backup": false,
"lifecycle": [
{
"cold_storage_after": null,
"delete_after": 30,
},
],
"recovery_point_tags": null,
"rule_name": "keep-snapshots-forever",
"schedule": "cron(0 12 * * ? *)",
"start_window": 60,
"target_vault_name": "main",
},
],
"tags": null,
},
"after_unknown": {
"advanced_backup_setting": [],
"arn": true,
"id": true,
"rule": [
{
"copy_action": [],
"lifecycle": [
{
"opt_in_to_archive_for_supported_resources": true,
},
],
},
],
"tags_all": true,
"version": true,
},
"before": null,
},
"deposed": "",
"index": null,
"mode": "managed",
"module_address": "",
"name": "example",
"provider_name": "registry.terraform.io/hashicorp/aws",
"type": "aws_backup_plan",
},
"aws_backup_vault.main": {
"address": "aws_backup_vault.main",
"change": {
"actions": [
"create",
],
"after": {
"force_destroy": false,
"name": "main",
"tags": null,
"timeouts": null,
},
"after_unknown": {
"arn": true,
"id": true,
"kms_key_arn": true,
"recovery_points": true,
"tags_all": true,
},
"before": null,
},
"deposed": "",
"index": null,
"mode": "managed",
"module_address": "",
"name": "main",
"provider_name": "registry.terraform.io/hashicorp/aws",
"type": "aws_backup_vault",
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
resource_changes = {
"aws_backup_plan.example": {
"address": "aws_backup_plan.example",
"change": {
"actions": [
"create",
],
"after": {
"advanced_backup_setting": [],
"name": "sentinel-terraform-aws-backup",
"rule": [
{
"completion_window": 180,
"copy_action": [],
"enable_continuous_backup": false,
"lifecycle": [
{
"cold_storage_after": null,
"delete_after": 0,
},
],
"recovery_point_tags": null,
"rule_name": "keep-snapshots-forever",
"schedule": "cron(0 12 * * ? *)",
"start_window": 60,
"target_vault_name": "main",
},
],
"tags": null,
},
"after_unknown": {
"advanced_backup_setting": [],
"arn": true,
"id": true,
"rule": [
{
"copy_action": [],
"lifecycle": [
{
"opt_in_to_archive_for_supported_resources": true,
},
],
},
],
"tags_all": true,
"version": true,
},
"before": null,
},
"deposed": "",
"index": null,
"mode": "managed",
"module_address": "",
"name": "example",
"provider_name": "registry.terraform.io/hashicorp/aws",
"type": "aws_backup_plan",
},
"aws_backup_vault.main": {
"address": "aws_backup_vault.main",
"change": {
"actions": [
"create",
],
"after": {
"force_destroy": false,
"name": "main",
"tags": null,
"timeouts": null,
},
"after_unknown": {
"arn": true,
"id": true,
"kms_key_arn": true,
"recovery_points": true,
"tags_all": true,
},
"before": null,
},
"deposed": "",
"index": null,
"mode": "managed",
"module_address": "",
"name": "main",
"provider_name": "registry.terraform.io/hashicorp/aws",
"type": "aws_backup_vault",
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mock "tfplan/v2" {
module {
source = "./mocks/mock-tfplan-snapshot-30-days-retention.sentinel"
}
}

test {
rules = {
main = true
}
}
4 changes: 4 additions & 0 deletions sentinel.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
policy "deny-snapshot-infinite-retention" {
source = "./policies/deny-snapshot-infinite-retention/deny-snapshot-infinite-retention.sentinel"
enforcement_level = "hard-mandatory"
}

0 comments on commit 462d4b3

Please sign in to comment.