Skip to content
This repository was archived by the owner on Mar 26, 2025. It is now read-only.

Commit 004483e

Browse files
committed
Local account backup module
1 parent 55b455a commit 004483e

File tree

7 files changed

+287
-0
lines changed

7 files changed

+287
-0
lines changed

modules/backup/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Terraform module: backup schedules
2+
3+
## Description
4+
5+
This is a simple module to create a AWS Backup vault, KMS keys, Plans and automatic off-account site backup.
6+
7+
The vault module should be ran first in the remote AWS account.
8+
9+
**WARNING** Once a snaphshot has been placed intothe remote locked vault it can not be removed until the
10+
lifecycle duration has been exceeded.
11+
12+
## Module parameters
13+
14+
| Name | Description | Type | Default |
15+
|:-----------------|:---------------------------------------------------------|:------:|:-------------------:|
16+
| instance_name | The name of the service being served | string | - |
17+
| remote_account | The AWS Account ID number of the remote account | string | - |
18+
| remote_vault_arn | The vault ARN in the remote account | string | false |
19+
| local_lifecycle | Lifecycle for local copies, in days | number | - |
20+
| remote_lifecycle | Lifecycle for remote copies, in days | number | - |
21+
| backup_schedule | The schedule to run backups, in AWS CRON format | string | cron(15 11 ? * * *) |
22+
| use_env | Wether to backup by environmrnt ot ALL assets in account | bool | false |
23+
| environment | The environment name to select assets from | string | - |
24+
25+
26+
## Sample usage
27+
28+
This snippet creates a backup vault and plan for RSS prod. The AWS account number "123456789012" and ARN
29+
is the locked vault created by the vault module in a seperate AWS account.
30+
31+
Local copies of the snapshots are held for 7 days and remote "tamper-proof" copies for 90 days. The backup
32+
runs at 11:15 every day and backs up all assets in the prod environment (as defined by the Environment tag)
33+
with the BackupRemote Tag set to true
34+
35+
```
36+
module "rss_prod_backup_vault" {
37+
source = "../modules/backup"
38+
39+
instance_name = "rss-prod"
40+
remote_accountount = "123456789012"
41+
remote_vault_arn = "arn:aws:backup:eu-west-2:123456789012:backup-vault:rss_prod_backup"
42+
local_lifecycle = 7
43+
remote_lifecycle = 90
44+
backup_schedule = "cron(15 11 ? * * *)"
45+
use_env = true
46+
environment = "prod"
47+
}
48+
```

modules/backup/data.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Data sources require dby module
2+
3+
data "aws_caller_identity" "current" {}

modules/backup/iam.tf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Backup IAM role to use for backups
2+
3+
resource "aws_iam_role" "remote_backup" {
4+
name = "${var.instance_name}-remote_backup"
5+
assume_role_policy = <<POLICY
6+
{
7+
"Version": "2012-10-17",
8+
"Statement": [
9+
{
10+
"Action": ["sts:AssumeRole"],
11+
"Effect": "allow",
12+
"Principal": {
13+
"Service": ["backup.amazonaws.com"]
14+
}
15+
}
16+
]
17+
}
18+
POLICY
19+
}
20+
21+
resource "aws_iam_role_policy_attachment" "remote_backup" {
22+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
23+
role = aws_iam_role.remote_backup.name
24+
}
25+
26+
resource "aws_iam_role_policy_attachment" "remote_backup_s3" {
27+
policy_arn = "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup"
28+
role = aws_iam_role.remote_backup.name
29+
}

modules/backup/kms.tf

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Create a specific KMS key for the local backup vault and allow the remote
2+
// AWS account access to that key.
3+
4+
resource "aws_kms_alias" "remote_backup_vault_key" {
5+
name = "alias/${var.instance_name}-remote-backup-vault-key"
6+
target_key_id = aws_kms_key.remote_backup_vault.key_id
7+
}
8+
9+
resource "aws_kms_key" "remote_backup_vault" {
10+
description = "${var.instance_name} Remote Backup vault Key"
11+
12+
policy = <<POLICY
13+
{
14+
"Version": "2012-10-17",
15+
"Id": "key-default-plus",
16+
"Statement": [
17+
{
18+
"Sid": "Enable IAM User Permissions",
19+
"Effect": "Allow",
20+
"Principal": {
21+
"AWS": "arn:aws:iam::${data.aws_caller_identity.current.id}:root"
22+
},
23+
"Action": "kms:*",
24+
"Resource": "*"
25+
},
26+
{
27+
"Sid": "Allow access from remote backup account",
28+
"Effect": "Allow",
29+
"Principal": {
30+
"AWS": "arn:aws:iam::${var.remote_account}:root"
31+
},
32+
"Action": [
33+
"kms:Encrypt",
34+
"kms:Decrypt",
35+
"kms:ReEncrypt*",
36+
"kms:GenerateDataKey*",
37+
"kms:DescribeKey"
38+
],
39+
"Resource": "*"
40+
},
41+
{
42+
"Sid": "Allow attachment of persistant resources",
43+
"Effect": "Allow",
44+
"Principal": {
45+
"AWS": "arn:aws:iam::${var.remote_account}:root"
46+
},
47+
"Action": [
48+
"kms:CreateGrant",
49+
"kms:ListGrants",
50+
"kms:RevokeGrant"
51+
],
52+
"Resource": "*",
53+
"Condition": {
54+
"Bool": {
55+
"kms:GrantIsForAWSResource": "true"
56+
}
57+
}
58+
}
59+
]
60+
}
61+
POLICY
62+
}

modules/backup/outputs.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Output variable definitions
2+
3+
output "vault_arn" {
4+
description = "The Local backup vault ARN"
5+
value = aws_backup_vault.remote_backup_vault.arn
6+
}

modules/backup/variables.tf

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Input variable definitions
2+
3+
variable "instance_name" {
4+
description = "The name of the service being served"
5+
type = string
6+
}
7+
8+
variable "remote_account" {
9+
description = "The AWS accound ID number holding the remote locked vault"
10+
type = string
11+
}
12+
13+
variable "remote_vault_arn" {
14+
description = "The ARN of the locked vault to copy snaphsots too in the remote AWS account"
15+
type = string
16+
}
17+
18+
variable "local_lifecycle" {
19+
description = "The lifecycle used for local backup snaphots, in days"
20+
type = string
21+
}
22+
23+
variable "remote_lifecycle" {
24+
description = "The lifecycle used for remote backup snaphots, in days"
25+
type = string
26+
}
27+
28+
variable "backup_schedule" {
29+
description = "The schedule to run backups in, in AWS's CRON format"
30+
type = string
31+
default = "cron(15 11 ? * * *)"
32+
}
33+
34+
variable "use_env" {
35+
description = ""
36+
type = bool
37+
default = false
38+
}
39+
40+
variable "environment" {
41+
description = "The environment name to back up, if omitted then ALL assets in the AWS account will be backed up if requested."
42+
type = string
43+
}

modules/backup/vault.tf

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Create the AWS Backup Vault and plans
2+
3+
// The vault
4+
5+
resource "aws_backup_vault" "remote_backup_vault" {
6+
name = "${var.instance_name}-remote_backup"
7+
kms_key_arn = aws_kms_key.remote_backup_vault.arn
8+
}
9+
10+
// The policy to use for the vault allowing the remote AWS account to copy snapshots
11+
// back in case of incidents
12+
13+
resource "aws_backup_vault_policy" "remote_backup" {
14+
backup_vault_name = aws_backup_vault.remote_backup_vault.name
15+
16+
policy = <<POLICY
17+
{
18+
"Version": "2012-10-17",
19+
"Statement": [
20+
{
21+
"Effect": "Allow",
22+
"Action": "backup:CopyIntoBackupVault",
23+
"Resource": "*",
24+
"Principal": {
25+
"AWS": [
26+
"arn:aws:iam::${var.remote_account}:root"
27+
]
28+
}
29+
}
30+
]
31+
}
32+
POLICY
33+
}
34+
35+
// The backup plan which automatically copies snapshots off-account
36+
37+
resource "aws_backup_plan" "remote_backup" {
38+
name = "${var.instance_name}-remote_backup"
39+
40+
rule {
41+
rule_name = "${var.instance_name}-remote_backup"
42+
target_vault_name = aws_backup_vault.remote_backup_vault.name
43+
schedule = var.backup_schedule
44+
45+
lifecycle {
46+
delete_after = var.local_lifecycle
47+
}
48+
copy_action {
49+
destination_vault_arn = var.remote_vault_arn
50+
51+
lifecycle {
52+
delete_after = var.remote_lifecycle
53+
}
54+
}
55+
}
56+
}
57+
58+
// A selection which backs up ALL assets in the AWS account which have
59+
// the tag BackupRemote=True
60+
61+
resource "aws_backup_selection" "remote_backup_account" {
62+
count = var.use_env ? 0 : 1
63+
iam_role_arn = aws_iam_role.remote_backup.arn
64+
name = "${var.instance_name}-remote-backup-account"
65+
plan_id = aws_backup_plan.remote_backup.id
66+
resources = ["*"]
67+
68+
condition {
69+
string_equals {
70+
key = "aws:ResourceTag/BackupRemote"
71+
value = "true"
72+
}
73+
}
74+
}
75+
76+
// A selection which backs up assets in the AWS account which have
77+
// the tag BackupRemote=True AND the requested Environment tag.
78+
79+
resource "aws_backup_selection" "remote_backup_env" {
80+
count = var.use_env ? 1 : 0
81+
iam_role_arn = aws_iam_role.remote_backup.arn
82+
name = "${var.instance_name}-remote-backup-env"
83+
plan_id = aws_backup_plan.remote_backup.id
84+
resources = ["*"]
85+
86+
condition {
87+
string_equals {
88+
key = "aws:ResourceTag/BackupRemote"
89+
value = "true"
90+
}
91+
string_equals {
92+
key = "aws:ResourceTag/Environment"
93+
value = var.environment
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)