Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backup plan role #45

Merged
merged 11 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/tests/output/
/tests/integration/integration_config.yml
/tests/integration/inventory
/changelogs/.plugin-cache.yaml
tests/integration/cloud-config-*
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Name | Description
[cloud.aws_ops.aws_setup_credentials](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/aws_setup_credentials/README.md)|A role to define credentials for aws modules.
[cloud.aws_ops.awsconfig_detach_and_delete_internet_gateway](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/awsconfig_detach_and_delete_internet_gateway/README.md)|A role to detach and delete the internet gateway you specify from virtual private cloud.
[cloud.aws_ops.awsconfig_multiregion_cloudtrail](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/awsconfig_multiregion_cloudtrail/README.md)|A role to create/delete a Trail for multiple regions.
[cloud.backup_create_plan](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/backup_create_plan/README.md)|A role to create an AWS backup plan.
[cloud.backup_select_resources](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/backup_create_plan/README.md)|A role to select resources to back up with an existing backup plan.
[cloud.aws_ops.customized_ami](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/customized_ami/README.md)|A role to manage custom AMIs on AWS.
[cloud.aws_ops.ec2_instance_terminate_by_tag](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/ec2_instance_terminate_by_tag/README.md)|A role to terminate the EC2 instances based on a specific tag you specify.
[cloud.aws_ops.enable_cloudtrail_encryption_with_kms](https://github.com/ansible-collections/cloud.aws_ops/blob/main/roles/enable_cloudtrail_encryption_with_kms/README.md)|A role to encrypt an AWS CloudTrail trail using the AWS Key Management Service (AWS KMS) customer managed key you specify.
Expand Down
67 changes: 67 additions & 0 deletions roles/backup_create_plan/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
backup_create_plan
==================

A role to create a backup plan and optionally a vault. A set of variables for plan rules is included for use as-is or as examples for modification. This role can be combined with the backup_select_resources role to back up a selection of resources.

Requirements
------------

AWS User Account with the following permission:

* backup:CreateBackupVault
* backup:CreateBackupPlan
* backup:DescribeBackupVault
* backup:ListBackupPlans
* backup:ListTags
* backup-storage:MountCapsule
* kms:CreateGrant
* kms:GenerateDataKey
* kms:Decrypt
* kms:RetireGrant
* kms:DescribeKey

Role Variables
--------------

* **plan_name**: (Required) The name of the backup plan you want to create
* **plan_rules**: (Required) A set of rules for the backup, as a list of dicts
alinabuzachis marked this conversation as resolved.
Show resolved Hide resolved
* **plan_windows_vss_settings**: Optional settings for Windows VSS backup, see [AdvancedBackupSetting object in the AWS Backup API documentation](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_AdvancedBackupSetting.html) for details
* **plan_tags**: Optional tags to apply to all backups created with the plan
* **vault_name**: The name of the vault you want to use or create. If not provided, the role will use (and create if needed) the AWS default vault for the account, named Default.
* **vault_encryption_key_arn**: Optional ARN of key to use for vault encryption
* **vault_tags**: Optional tags to apply to the vault

### Included sample plan rules variables
These are included in vars/main.yaml for use as-is or as examples for modification.

* **hourly_backup**: Rules specifying hourly continous backup at :15 UTC with 7-day retention
* **daily_backup**: Rules specifying daily backup at 5am UTC with Amazon defaults for all other settings
* **weekly_backup**: Rules specifying weekly backup on Mondays at 5am UTC with 90 day retention after quick transition to cold storage
* **monthly_backup**: Rules specifying monthly backup at 5am UTC on 1st of month with copy to additional vault (requires an additional variable **copy_vault_name** be set with the name of the vault to copy to)


Dependencies
------------

* role: [aws_setup_credentials](../aws_setup_credentials/README.md)

Example Playbook
----------------

- hosts: localhost
roles:
- role: cloud.aws_ops.backup_create_plan
plan_name: my-backup-plan
plan_rules: "{{ daily_backup }}"

License
-------

GNU General Public License v3.0 or later

See [LICENCE](https://github.com/ansible-collections/cloud.aws_ops/blob/main/LICENSE) to see the full text.

Author Information
------------------

* Ansible Cloud Content Team
2 changes: 2 additions & 0 deletions roles/backup_create_plan/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
vault_name: Default
3 changes: 3 additions & 0 deletions roles/backup_create_plan/meta/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- role: cloud.aws_ops.aws_setup_credentials
53 changes: 53 additions & 0 deletions roles/backup_create_plan/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
- name: Verify required variables
block:
- name: Fail when plan variables are not defined
ansible.builtin.fail:
msg: "Required variable {{ item }} has not been defined"
when: vars[item] is undefined
loop:
- plan_name
- plan_rules

- name: Run backup_create_plan_role
module_defaults:
group/aws: "{{ aws_setup_credentials__output }}"
block:
- name: Create or update backup vault
block:
- name: Create or update backup vault
amazon.aws.backup_vault:
state: present
backup_vault_name: "{{ vault_name }}"
encryption_key_arn: "{{ vault_encryption_key_arn | default(omit) }}"
tags: "{{ vault_tags | default(omit) }}"
register: backup_create_plan_backup_vault_result

- name: Verify that vault has been created/updated
ansible.builtin.debug:
msg: Vault '{{ vault_name }}' successfully created/updated.
when: backup_create_plan_backup_vault_result is changed

- name: Verify that vault already exists
ansible.builtin.debug:
msg: Vault '{{ vault_name }}' exists, no updates needed.
when: backup_create_plan_backup_vault_result is not changed

- name: Create or update backup plan
amazon.aws.backup_plan:
state: present
backup_plan_name: "{{ plan_name }}"
rules: "{{ plan_rules }}"
advanced_backup_settings: "{{ plan_windows_vss_settings | default(omit) }}"
tags: "{{ plan_tags | default(omit) }}"
register: backup_create_plan_backup_plan_result

- name: Verify that plan has been created/updated
ansible.builtin.debug:
msg: Plan '{{ plan_name }}' successfully created/updated.
when: backup_create_plan_backup_plan_result is changed

- name: Verify that plan already exists
ansible.builtin.debug:
msg: Plan '{{ plan_name }}' exists, no updates needed.
when: backup_create_plan_backup_plan_result is not changed
30 changes: 30 additions & 0 deletions roles/backup_create_plan/vars/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
abikouo marked this conversation as resolved.
Show resolved Hide resolved
hourly_backup: # Hourly continous backup at :15 with 7-day retention
rule_name: hourly
target_backup_vault_name: "{{ vault_name }}"
schedule_expression: "cron(15 * ? * * *)"
start_window_minutes: 60
completion_window_minutes: 120
enable_continuous_backup: true
lifecycle:
delete_after_days: 7

daily_backup: # Daily backup at 5am UTC with Amazon defaults for all other settings
rule_name: daily
target_backup_vault_name: "{{ vault_name }}"
schedule_expression: "cron(0 5 ? * * *)"

weekly_backup: # Weekly backup on Mondays at 5am UTC with 90 day retention after quick transition to cold storage
rule_name: weekly
target_backup_vault_name: "{{ vault_name }}"
schedule_expression: "cron(0 5 ? * MON *)"
lifecycle:
delete_after_days: 91
move_to_cold_storage_after_days: 1

monthly_backup: # Monthly backup at 5am UTC on 1st of month with copy to additional vault
rule_name: monthly
target_backup_vault_name: "{{ vault_name }}"
schedule_expression: "cron(0 5 1 * ? *)"
copy_actions:
- destination_backup_vault_name: "{{ copy_vault_name }}"
83 changes: 83 additions & 0 deletions roles/backup_select_resources/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
backup_select_resources
==================

A role to configure backups for selected resources. The role requires an existing backup vault and plan, and adds selected resources to the provided plan. A set of variables for resource selections is included for use as-is or as examples for modification. This role can be combined with the `backup_create_plan` role to create or update a backup plan if one does not already exist. (see [example playbook](#create-backup-plan-and-select-resources)).

hakbailey marked this conversation as resolved.
Show resolved Hide resolved
Requirements
------------

AWS User Account with the following permission:

* backup:CreateBackupSelection
* backup:DeleteBackupSelection
* backup:GetBackupPlan
* backup:GetBackupSelection
* backup:ListBackupSelections
* iam:GetRole

Role Variables
--------------

* **plan_name**: (Required) The name of the backup plan you want to use for the selected resources.
* **selection_name**: (Required) The display name of the resource selection you want to back up.
* **selection_resources**: (Required) List of resources selected for backup. Can use wild cards and/or combine with selection options below to precisely restrict resources based on various conditions. See included vars for examples.
* **selection_excluded_resources**: List of resources to exclude from backup
* **selection_tags**: List of resource tags selected for backup
alinabuzachis marked this conversation as resolved.
Show resolved Hide resolved
* **selection_conditions**: Conditions for resources to back up
* **backup_role_name**: (Required) The name of an IAM role with permissions to perform all needed backup actions for the selected resources. Alternatively, provide a new for a new IAM role which will be created with the same permissions as the AWSBackupDefaultServiceRole (note: these permissions allow backups and restores for all resources).

### Included sample resource selection variables
These are included in vars/main.yaml for use as-is or as examples for modification.

* **all_resources**: All AWS resources
* **all_s3_buckets** All S3 buckets
* **all_rds_db_instances**: All RDS database instances
* **tag_list_backup_or_prod**: Resources tagged {"backup": "true"} OR {"env": "prod"}, for use with the **selection_tags** role variable
* **conditions_tagged_backup_and_prod**: Resources tagged {"backup": "true"} AND {"env": "prod"}, for use with the **selection_conditions** role variable

Dependencies
------------

* role: [aws_setup_credentials](../aws_setup_credentials/README.md)

Example Playbooks
----------------

### Select resources
- hosts: localhost
roles:
- role: cloud.aws_ops.backup_select_resources
vars:
plan_name: my-backup-plan
selection_name: s3_buckets
selection_resources:
- "{{ all_s3_buckets }}"

### Create backup plan and select resources

- hosts: localhost
roles:
- role: cloud.aws_ops.backup_create_plan
plan_name: my-backup-plan
plan_rules: "{{ daily_backup }}"

- hosts: localhost
roles:
- role: cloud.aws_ops.backup_select_resources
vars:
plan_name: my-backup-plan
selection_name: s3_buckets
selection_resources:
- "{{ all_s3_buckets }}"

License
-------

GNU General Public License v3.0 or later

See [LICENCE](https://github.com/ansible-collections/cloud.aws_ops/blob/main/LICENSE) to see the full text.

Author Information
------------------

* Ansible Cloud Content Team
12 changes: 12 additions & 0 deletions roles/backup_select_resources/files/backup-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Version": "2012-10-17",
"Statement":[
{
"Effect": "Allow",
"Principal": {
"Service": "backup.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
3 changes: 3 additions & 0 deletions roles/backup_select_resources/meta/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- role: cloud.aws_ops.aws_setup_credentials
75 changes: 75 additions & 0 deletions roles/backup_select_resources/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
- name: Fail when name, role, and resource variables are not defined
ansible.builtin.fail:
msg: "Required variable {{ item }} has not been defined"
when: vars[item] is undefined
loop:
- backup_role_name
- plan_name
- selection_name
- selection_resources

- name: Run backup_select_resources role
module_defaults:
group/aws: "{{ aws_setup_credentials__output }}"
block:
- name: Get plan info
amazon.aws.backup_plan_info:
backup_plan_names:
- "{{ plan_name }}"
register: backup_select_resources_backup_plan_info

- name: Fail when backup plan does not exist
ansible.builtin.fail:
msg: Backup plan {{ plan_name }} does not exist, please create or confirm plan name is correct.
when: backup_select_resources_backup_plan_info.backup_plans | length == 0

- name: Get provided IAM role info
community.aws.iam_role_info:
name: "{{ backup_role_name }}"
register: backup_select_resources_role_info

- name: Create new role when IAM role does not exist
block:
- name: Create role
when: backup_select_resources_role_info.iam_roles | length == 0
community.aws.iam_role:
name: "{{ backup_role_name }}"
state: present
assume_role_policy_document: '{{ lookup("file", "backup-policy.json") }}'
create_instance_profile: false
description: "AWS Backup Role"
managed_policy:
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
wait: true
register: backup_select_resources_new_role_info

- name: Wait for role to be created
ansible.builtin.pause:
seconds: 8

- name: Set backup role ARN
ansible.builtin.set_fact:
backup_select_resources_backup_role_arn: "{{ backup_select_resources_role_info.iam_roles[0].arn if backup_select_resources_new_role_info is skipped else backup_select_resources_new_role_info.arn }}"

- name: Create or update backup selection
amazon.aws.backup_selection:
state: present
backup_plan_name: "{{ plan_name }}"
selection_name: "{{ selection_name }}"
iam_role_arn: "{{ backup_select_resources_backup_role_arn }}"
resources: "{{ selection_resources }}"
list_of_tags: "{{ selection_tags | default(omit) }}"
not_resources: "{{ selection_excluded_resources | default(omit) }}"
conditions: "{{ selection_conditions | default(omit) }}"
register: backup_select_resources_selection_result

- name: Verify that selection has been created/updated
ansible.builtin.debug:
msg: Backup selection '{{ selection_name }}' successfully created/updated.
when: backup_select_resources_selection_result is changed

- name: Verify that selection already exists
ansible.builtin.debug:
msg: Backup selection '{{ selection_name }}' exists, no updates needed.
when: backup_select_resources_selection_result is not changed
19 changes: 19 additions & 0 deletions roles/backup_select_resources/vars/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
hakbailey marked this conversation as resolved.
Show resolved Hide resolved
all_resources: "*"
all_s3_buckets: "arn:aws:s3:::*"
all_rds_db_instances: "arn:aws:rds:*:*:db:*"

tag_list_backup_or_prod: # Resources tagged {"backup": "true"} OR {"env": "prod"}
- condition_type: "STRINGEQUALS"
condition_key: "backup"
condition_value: "true"
- condition_type: "StringEquals"
condition_key: "env"
condition_value: "prod"

conditions_tagged_backup_and_prod: # Resources tagged {"backup": "true"} AND {"env": "prod"}
string_equals:
- condition_key: "aws:ResourceTag/backup"
condition_value: "true"
- condition_key: "aws:ResourceTag/env"
condition_value: "prod"
7 changes: 7 additions & 0 deletions tests/integration/constraints.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Specifically run tests against the oldest versions that we support
boto3==1.22.0
botocore==1.25.0

# AWS CLI has `botocore==` dependencies, provide the one that matches botocore
# to avoid needing to download over a years worth of awscli wheels.
awscli==1.23.0
3 changes: 3 additions & 0 deletions tests/integration/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Our code is based on the AWS SDKs
boto3
botocore
3 changes: 3 additions & 0 deletions tests/integration/targets/test_backup_create_plan/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cloud/aws
role/backup_create_plan
time=3m
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
hakbailey marked this conversation as resolved.
Show resolved Hide resolved
aws_security_token: '{{ security_token | default(omit) }}'
Loading