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 unit tests #470

Closed
wants to merge 7 commits into from
Closed
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
36 changes: 36 additions & 0 deletions .github/workflows/go-terratest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
on:
pull_request:
types: [opened, edited, reopened, synchronize]
push:
branches:
- feature/add-unit-tests

permissions: {}

env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
TF_IN_AUTOMATION: true

jobs:
go-tests:
permissions:
contents: read
actions: write
name: Run Go Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
with:
go-version: 1.18
- uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
with:
terraform_version: ~1.3
terraform_wrapper: false
- name: Download Go Modules
working-directory: test
run: go mod download
- name: Run Go Tests
working-directory: test
run: go test -v
15 changes: 7 additions & 8 deletions modules/backup/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ locals {
resource "aws_backup_vault" "default" {
#checkov:skip=CKV_AWS_166: "Ensure Backup Vault is encrypted at rest using KMS CMK - Tricky to implement, hence using AWS managed KMS key"

name = "everything"
name = var.aws_backup_vault_name
tags = var.tags
}

# Production backups
resource "aws_backup_plan" "default" {
#checkov:skip=CKV_AWS_166: "Ensure Backup Vault is encrypted at rest using KMS CMK - Tricky to implement, hence using AWS managed KMS key"

name = "backup-daily-retain-30-days"

name = var.production_backup_plan_name
rule {
rule_name = "backup-daily-retain-30-days"
target_vault_name = aws_backup_vault.default.name
Expand Down Expand Up @@ -47,7 +46,7 @@ resource "aws_backup_plan" "default" {
}

resource "aws_backup_selection" "production" {
name = "is-production-true"
name = var.production_backup_selection_name
iam_role_arn = var.iam_role_arn
plan_id = aws_backup_plan.default.id
resources = ["*"]
Expand All @@ -66,7 +65,7 @@ resource "aws_backup_selection" "production" {

# Non production backups
resource "aws_backup_plan" "non_production" {
name = "backup-daily-cold-storage-monthly-retain-30-days"
name = var.non_production_backup_plan_name

rule {
rule_name = "backup-daily-cold-storage-monthly-retain-30-days"
Expand Down Expand Up @@ -97,7 +96,7 @@ resource "aws_backup_plan" "non_production" {
}

resource "aws_backup_selection" "non_production" {
name = "non-production-backup"
name = var.non_production_backup_selection_name
iam_role_arn = var.iam_role_arn
plan_id = aws_backup_plan.non_production.id
resources = ["*"]
Expand All @@ -115,10 +114,10 @@ resource "aws_backup_selection" "non_production" {
}

# SNS topic
#trivy:ignore:avd-aws-0136
# trivy:ignore:avd-aws-0136
resource "aws_sns_topic" "backup_failure_topic" {
kms_master_key_id = var.sns_backup_topic_key
name = "backup_failure_topic"
name = var.backup_aws_sns_topic_name
tags = merge(var.tags, {
Description = "This backup topic is so the MP team can subscribe to backup notifications from selected accounts and teams using member-unrestricted accounts can create their own subscriptions"
})
Expand Down
23 changes: 23 additions & 0 deletions modules/backup/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
output "aws_backup_vault_arn" {
value = aws_backup_vault.default.arn
}

output "aws_backup_plan_production" {
value = aws_backup_plan.default.arn
}

output "aws_backup_plan_non_production" {
value = aws_backup_plan.non_production.arn
}

output "aws_backup_selection_production" {
value = aws_backup_selection.production.id
}

output "aws_backup_selection_non_production" {
value = aws_backup_selection.non_production.id
}
output "backup_aws_sns_topic_arn" {
value = aws_sns_topic.backup_failure_topic.arn
}

30 changes: 30 additions & 0 deletions modules/backup/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,33 @@ variable "tags" {
description = "Tags to apply to resources, where applicable"
type = map(any)
}

variable "aws_backup_vault_name" {
default = "everything"
type = string
}

variable "production_backup_plan_name" {
default = "backup-daily-retain-30-days"
type = string
}

variable "production_backup_selection_name" {
default = "is-production-true"
type = string
}

variable "non_production_backup_plan_name" {
default = "backup-daily-cold-storage-monthly-retain-30-days"
type = string
}

variable "non_production_backup_selection_name" {
default = "non-production-backup"
type = string
}

variable "backup_aws_sns_topic_name" {
default = "backup_failure_topic"
type = string
}
3 changes: 3 additions & 0 deletions test/backup-test/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
environment_management = jsondecode(data.aws_secretsmanager_secret_version.environment_management.secret_string)
}
42 changes: 42 additions & 0 deletions test/backup-test/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module "backup-test" {
source = "../../modules/backup"
iam_role_arn = aws_iam_role.backup.arn
aws_backup_vault_name = var.aws_backup_vault_name
production_backup_plan_name = var.production_backup_plan_name
production_backup_selection_name = var.production_backup_selection_name
non_production_backup_plan_name = var.non_production_backup_plan_name
non_production_backup_selection_name = var.non_production_backup_selection_name
backup_aws_sns_topic_name = var.backup_aws_sns_topic_name

}

/*
IAM role for AWS Backup
*/
resource "aws_iam_role" "backup" {
name = var.aws_iam_role_backup_name
assume_role_policy = data.aws_iam_policy_document.backup-assume-role-policy.json
}

data "aws_iam_policy_document" "backup-assume-role-policy" {
version = "2012-10-17"
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["backup.amazonaws.com"]
}
}
}

resource "aws_iam_role_policy_attachment" "backup" {
role = aws_iam_role.backup.id
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
}

resource "aws_iam_role_policy_attachment" "backupS3" {
role = aws_iam_role.backup.id
policy_arn = "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup"
}
23 changes: 23 additions & 0 deletions test/backup-test/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
output "aws_backup_vault_arn" {
value = module.backup-test.aws_backup_vault_arn
}

output "aws_backup_plan_production" {
value = module.backup-test.aws_backup_plan_production
}

output "aws_backup_plan_non_production" {
value = module.backup-test.aws_backup_plan_non_production
}

output "aws_backup_selection_production" {
value = module.backup-test.aws_backup_selection_production
}

output "aws_backup_selection_non_production" {
value = module.backup-test.aws_backup_selection_non_production
}

output "backup_aws_sns_topic_arn" {
value = module.backup-test.backup_aws_sns_topic_arn
}
13 changes: 13 additions & 0 deletions test/backup-test/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# AWS provider for the workspace you're working in (every resource will default to using this, unless otherwise specified)
provider "aws" {
region = "eu-west-2"
assume_role {
role_arn = "arn:aws:iam::${local.environment_management.account_ids["testing-test"]}:role/MemberInfrastructureAccess"
}
}

# AWS provider for the testing-ci user (testing-test account), to get things from there if required
provider "aws" {
alias = "testing-ci-user"
region = "eu-west-2"
}
16 changes: 16 additions & 0 deletions test/backup-test/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Get secret by arn for environment management
data "aws_ssm_parameter" "environment_management_arn" {
provider = aws.testing-ci-user
name = "environment_management_arn"
}

data "aws_secretsmanager_secret" "environment_management" {
provider = aws.testing-ci-user
arn = data.aws_ssm_parameter.environment_management_arn.value
}

# Get latest secret value with ID from above. This secret stores account IDs for the Modernisation Platform sub-accounts
data "aws_secretsmanager_secret_version" "environment_management" {
provider = aws.testing-ci-user
secret_id = data.aws_secretsmanager_secret.environment_management.id
}
34 changes: 34 additions & 0 deletions test/backup-test/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
variable "aws_iam_role_backup_name" {
default = "AWSBackup"
type = string
}

variable "aws_backup_vault_name" {
default = "everything"
type = string
}

variable "production_backup_plan_name" {
default = "backup-daily-retain-30-days"
type = string
}

variable "production_backup_selection_name" {
default = "is-production-true"
type = string
}

variable "non_production_backup_plan_name" {
default = "backup-daily-cold-storage-monthly-retain-30-days"
type = string
}

variable "non_production_backup_selection_name" {
default = "non-production-backup"
type = string
}

variable "backup_aws_sns_topic_name" {
default = "backup_failure_topic"
type = string
}
13 changes: 13 additions & 0 deletions test/backup-test/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_providers {
aws = {
version = "~> 5.0"
source = "hashicorp/aws"
}
http = {
version = "~> 3.0"
source = "hashicorp/http"
}
}
required_version = "~> 1.0"
}
64 changes: 64 additions & 0 deletions test/baselines_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"fmt"
"regexp"
"testing"

"github.com/gruntwork-io/terratest/modules/random"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)

// Backup Module Unit Testing
func TestTerraformBackup(t *testing.T) {
t.Parallel()

terraformDir := "./backup-test"
uniqueId := random.UniqueId()

// Unique names for Backup resources
BackupIamRoleName := fmt.Sprintf("AWSBackup-%s", uniqueId)
BackupVaultName := fmt.Sprintf("everything-%s", uniqueId)
ProdBackupVaultName := fmt.Sprintf("backup-daily-retain-30-days-%s", uniqueId)
ProdBackupSelectionName := fmt.Sprintf("is-production-true-%s", uniqueId)
NonProdBackupPlanName := fmt.Sprintf("backup-daily-cold-storage-monthly-retain-30-days-%s", uniqueId)
NonProdBackupSelectionName := fmt.Sprintf("non-production-backup-%s", uniqueId)
BackupSNSTopicName := fmt.Sprintf("backup_failure_topic-%s", uniqueId)

terraformOptions := &terraform.Options{
TerraformDir: terraformDir,
Vars: map[string]interface{}{
"aws_iam_role_backup_name": BackupIamRoleName,
"aws_backup_vault_name": BackupVaultName,
"production_backup_plan_name": ProdBackupVaultName,
"production_backup_selection_name": ProdBackupSelectionName,
"non_production_backup_plan_name": NonProdBackupPlanName,
"non_production_backup_selection_name": NonProdBackupSelectionName,
"backup_aws_sns_topic_name": BackupSNSTopicName,
},
}
// Clean up resources with "terraform destroy" at the end of the test
defer terraform.Destroy(t, terraformOptions)

// Run "terraform init" and "terraform plan"
// terraform.InitAndPlan(t, terraformOptions)

// Run "terraform init" and "terraform apply"
terraform.InitAndApply(t, terraformOptions)

// Test backup module
AwsBackupVaultArn := terraform.Output(t, terraformOptions, "aws_backup_vault_arn")
AwsBackupPlanProd := terraform.Output(t, terraformOptions, "aws_backup_plan_production")
AwsBackupPlanNonProd := terraform.Output(t, terraformOptions, "aws_backup_plan_non_production")
AwsBackupSelectionProd := terraform.Output(t, terraformOptions, "aws_backup_selection_production")
AwsBackupSelectionNonProd := terraform.Output(t, terraformOptions, "aws_backup_selection_non_production")
AWSBackupSNSTopicArn := terraform.Output(t, terraformOptions, "backup_aws_sns_topic_arn")

assert.Regexp(t, regexp.MustCompile(`^arn:aws:backup:eu-west-2:[0-9]{12}:backup-vault:everything-`+uniqueId), AwsBackupVaultArn)
assert.Regexp(t, regexp.MustCompile(`^arn:aws:backup:eu-west-2:[0-9]{12}:backup-plan:*`), AwsBackupPlanProd)
assert.Regexp(t, regexp.MustCompile(`^arn:aws:backup:eu-west-2:[0-9]{12}:backup-plan:*`), AwsBackupPlanNonProd)
assert.Regexp(t, regexp.MustCompile(`^*`), AwsBackupSelectionProd)
assert.Regexp(t, regexp.MustCompile(`^*`), AwsBackupSelectionNonProd)
assert.Regexp(t, regexp.MustCompile(`^arn:aws:sns:eu-west-2:[0-9]{12}:backup_failure_topic-`+uniqueId), AWSBackupSNSTopicArn)
}
Loading
Loading