diff --git a/modules/aws-backup/README.md b/modules/aws-backup/README.md
index b8e0b292c..4da76b8ae 100644
--- a/modules/aws-backup/README.md
+++ b/modules/aws-backup/README.md
@@ -37,6 +37,13 @@ components:
iam_role_enabled: true # this will be reused
vault_enabled: true # this will be reused
plan_enabled: false
+
+## Please be careful when enabling backup_vault_lock_configuration,
+# backup_vault_lock_configuration:
+## `changeable_for_days` enables compliance mode and once the lock is set, the retention policy cannot be changed unless through account deletion!
+# changeable_for_days: 36500
+# max_retention_days: 365
+# min_retention_days: 1
```
Then if we would like to deploy the component into a given stacks we can import the following to deploy our backup plans.
@@ -85,7 +92,12 @@ components:
vars:
plan_name_suffix: aws-backup-daily
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
- schedule: cron(0 0 ? * * *) # Daily at midnight (UTC)
+ rules:
+ - name: "plan-daily"
+ schedule: "cron(0 5 ? * * *)"
+ start_window: 320 # 60 * 8 # minutes
+ completion_window: 10080 # 60 * 24 * 7 # minutes
+ delete_after: 35 # 7 * 5 # days
selection_tags:
- type: STRINGEQUALS
key: aws-backup/efs
@@ -102,7 +114,12 @@ components:
vars:
plan_name_suffix: aws-backup-weekly
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
- schedule: cron(0 0 ? * 1 *) # Weekly on first day of week at midnight (UTC)
+ rules:
+ - name: "plan-weekly"
+ schedule: "cron(0 5 ? * SAT *)"
+ start_window: 320 # 60 * 8 # minutes
+ completion_window: 10080 # 60 * 24 * 7 # minutes
+ delete_after: 90 # 30 * 3 # days
selection_tags:
- type: STRINGEQUALS
key: aws-backup/efs
@@ -118,10 +135,15 @@ components:
- aws-backup/plan-defaults
vars:
plan_name_suffix: aws-backup-monthly
- # delete monthly snapshots after 60 days
- delete_after: 60
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
- schedule: cron(0 0 1 * ? *) # Monthly on 1st day of the month (doesn't matter which) at midnight UTC
+ rules:
+ - name: "plan-monthly"
+ schedule: "cron(0 5 1 * ? *)"
+ start_window: 320 # 60 * 8 # minutes
+ completion_window: 10080 # 60 * 24 * 7 # minutes
+ delete_after: 2555 # 365 * 7 # days
+ cold_storage_after: 90 # 30 * 3 # days
+
selection_tags:
- type: STRINGEQUALS
key: aws-backup/efs
@@ -182,13 +204,41 @@ components:
copy_action_delete_after: 14
```
+### Backup Lock Configuration
+
+To enable backup lock configuration, you can use the following snippet:
+
+* [AWS Backup Vault Lock](https://docs.aws.amazon.com/aws-backup/latest/devguide/vault-lock.html)
+
+#### Compliance Mode
+Vaults locked in compliance mode cannot be deleted once the cooling-off period ("grace time") expires. During grace time, you can still remove the vault lock and change the lock configuration.
+
+To enable **Compliance Mode**, set `changeable_for_days` to a value greater than 0. Once the lock is set, the retention policy cannot be changed unless through account deletion!
+```yaml
+# Please be careful when enabling backup_vault_lock_configuration,
+ backup_vault_lock_configuration:
+# `changeable_for_days` enables compliance mode and once the lock is set, the retention policy cannot be changed unless through account deletion!
+ changeable_for_days: 36500
+ max_retention_days: 365
+ min_retention_days: 1
+```
+
+#### Governance Mode
+Vaults locked in governance mode can have the lock removed by users with sufficient IAM permissions.
+
+To enable **governance mode**
+```yaml
+ backup_vault_lock_configuration:
+ max_retention_days: 365
+ min_retention_days: 1
+```
## Requirements
| Name | Version |
|------|---------|
-| [terraform](#requirement\_terraform) | >= 1.0.0 |
+| [terraform](#requirement\_terraform) | >= 1.3.0 |
| [aws](#requirement\_aws) | >= 4.9.0 |
## Providers
@@ -199,7 +249,7 @@ No providers.
| Name | Source | Version |
|------|--------|---------|
-| [backup](#module\_backup) | cloudposse/backup/aws | 0.14.0 |
+| [backup](#module\_backup) | cloudposse/backup/aws | 1.0.0 |
| [copy\_destination\_vault](#module\_copy\_destination\_vault) | cloudposse/stack-config/yaml//modules/remote-state | 1.5.0 |
| [iam\_roles](#module\_iam\_roles) | ../account-map/modules/iam-roles | n/a |
| [this](#module\_this) | cloudposse/label/null | 0.25.0 |
@@ -213,8 +263,10 @@ No resources.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no |
+| [advanced\_backup\_setting](#input\_advanced\_backup\_setting) | An object that specifies backup options for each resource type. |
object({| `null` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
backup_options = string
resource_type = string
})
object({| `null` | no | | [cold\_storage\_after](#input\_cold\_storage\_after) | Specifies the number of days after creation that a recovery point is moved to cold storage | `number` | `null` | no | | [completion\_window](#input\_completion\_window) | The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window` | `number` | `null` | no | | [context](#input\_context) | Single object for setting entire context at once.
changeable_for_days = optional(number)
max_retention_days = optional(number)
min_retention_days = optional(number)
})
{| no | @@ -241,6 +293,7 @@ No resources. | [plan\_name\_suffix](#input\_plan\_name\_suffix) | The string appended to the plan name | `string` | `null` | no | | [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
list(object({| `[]` | no | | [schedule](#input\_schedule) | A CRON expression specifying when AWS Backup initiates a backup job | `string` | `null` | no | | [selection\_tags](#input\_selection\_tags) | An array of tag condition objects used to filter resources based on tags for assigning to a backup plan | `list(map(string))` | `[]` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | diff --git a/modules/aws-backup/main.tf b/modules/aws-backup/main.tf index bb371da65..f93e4717d 100644 --- a/modules/aws-backup/main.tf +++ b/modules/aws-backup/main.tf @@ -6,7 +6,7 @@ locals { module "backup" { source = "cloudposse/backup/aws" - version = "0.14.0" + version = "1.0.0" plan_name_suffix = var.plan_name_suffix vault_enabled = var.vault_enabled @@ -16,17 +16,11 @@ module "backup" { backup_resources = var.backup_resources selection_tags = var.selection_tags - schedule = var.schedule - start_window = var.start_window - completion_window = var.completion_window - cold_storage_after = var.cold_storage_after - delete_after = var.delete_after - kms_key_arn = var.kms_key_arn + kms_key_arn = var.kms_key_arn - # Copy config to new region - destination_vault_arn = local.copy_destination_arn - copy_action_cold_storage_after = var.copy_action_cold_storage_after - copy_action_delete_after = var.copy_action_delete_after + rules = var.rules + advanced_backup_setting = var.advanced_backup_setting + backup_vault_lock_configuration = var.backup_vault_lock_configuration context = module.this.context } diff --git a/modules/aws-backup/variables.tf b/modules/aws-backup/variables.tf index c43515f5a..4b8de574e 100644 --- a/modules/aws-backup/variables.tf +++ b/modules/aws-backup/variables.tf @@ -21,6 +21,19 @@ variable "start_window" { default = null } +variable "backup_vault_lock_configuration" { + type = object({ + changeable_for_days = optional(number) + max_retention_days = optional(number) + min_retention_days = optional(number) + }) + description = <<-EOT + The backup vault lock configuration, each vault can have one vault lock in place. This will enable Backup Vault Lock on an AWS Backup vault it prevents the deletion of backup data for the specified retention period. During this time, the backup data remains immutable and cannot be deleted or modified." + `changeable_for_days` - The number of days before the lock date. If omitted creates a vault lock in `governance` mode, otherwise it will create a vault lock in `compliance` mode. + EOT + default = null +} + variable "completion_window" { type = number description = "The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window`" @@ -104,3 +117,38 @@ variable "iam_role_enabled" { description = "Whether or not to create a new IAM Role and Policy Attachment" default = true } + + +variable "rules" { + type = list(object({ + name = string + schedule = optional(string) + enable_continuous_backup = optional(bool) + start_window = optional(number) + completion_window = optional(number) + lifecycle = optional(object({ + cold_storage_after = optional(number) + delete_after = optional(number) + opt_in_to_archive_for_supported_resources = optional(bool) + })) + copy_action = optional(object({ + destination_vault_arn = optional(string) + lifecycle = optional(object({ + cold_storage_after = optional(number) + delete_after = optional(number) + opt_in_to_archive_for_supported_resources = optional(bool) + })) + })) + })) + description = "An array of rule maps used to define schedules in a backup plan" + default = [] +} + +variable "advanced_backup_setting" { + type = object({ + backup_options = string + resource_type = string + }) + description = "An object that specifies backup options for each resource type." + default = null +} diff --git a/modules/aws-backup/versions.tf b/modules/aws-backup/versions.tf index cc73ffd35..b5920b7b1 100644 --- a/modules/aws-backup/versions.tf +++ b/modules/aws-backup/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.0.0" + required_version = ">= 1.3.0" required_providers { aws = { diff --git a/modules/philips-labs-github-runners/templates/userdata_post_install.sh b/modules/philips-labs-github-runners/templates/userdata_post_install.sh index b511a316b..3f810387b 100644 --- a/modules/philips-labs-github-runners/templates/userdata_post_install.sh +++ b/modules/philips-labs-github-runners/templates/userdata_post_install.sh @@ -1,3 +1,16 @@ echo "Installing Custom Packages..." yum install -y make + +# Install AWS CLI +curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +unzip awscliv2.zip +sudo ./aws/install + +# Install `gh` CLI +type -p yum-config-manager >/dev/null || sudo yum install -y yum-utils +sudo yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo +sudo yum install -y gh + +# Install nodejs +sudo yum install -y nodejs-1:18.18.2-1.amzn2023.0.1
name = string
schedule = optional(string)
enable_continuous_backup = optional(bool)
start_window = optional(number)
completion_window = optional(number)
lifecycle = optional(object({
cold_storage_after = optional(number)
delete_after = optional(number)
opt_in_to_archive_for_supported_resources = optional(bool)
}))
copy_action = optional(object({
destination_vault_arn = optional(string)
lifecycle = optional(object({
cold_storage_after = optional(number)
delete_after = optional(number)
opt_in_to_archive_for_supported_resources = optional(bool)
}))
}))
}))