diff --git a/layers/security_identity_compliance/security_services/.terraform.lock.hcl b/layers/security_identity_compliance/security_services/.terraform.lock.hcl new file mode 100644 index 0000000..eb93526 --- /dev/null +++ b/layers/security_identity_compliance/security_services/.terraform.lock.hcl @@ -0,0 +1,37 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "3.26.0" + constraints = ">= 3.25.0" + hashes = [ + "h1:0i78FItlPeiomd+4ThZrtm56P5K33k7/6dnEe4ZePI0=", + "zh:26043eed36d070ca032cf04bc980c654a25821a8abc0c85e1e570e3935bbfcbb", + "zh:2fe68f3f78d23830a04d7fac3eda550eef1f627dfc130486f70a65dc5c254300", + "zh:3d66484c608c64678e639db25d63872783ce60363a1246e30317f21c9c23b84b", + "zh:46ffd755cfd4cf94fe66342797b5afdcef010a24e126c67fee141b357d393535", + "zh:5e96f24357e945c9067cf5e032ad1d003609629c956c2f9f642fefe714e74587", + "zh:60c27aca36bb63bf3e865c2193be80ca83b376581d00f9c220af4b013e163c4d", + "zh:896f0f22d19d41e71b22f9240b261714c3915b165ddefeb771e7734d69dc47ea", + "zh:90de9966cb2fd3e2f326df291595e55d2dd2d90e7d6dd085c2c8691dce82bdb4", + "zh:ad05a91a88ceb1d6de5a568f7cc0b0e5bc0a79f3da70bc28c1e7f3750e362d58", + "zh:e8c63f59c6465329e1f3357498face3dd7ef10a033df3c366a33aa9e94b46c01", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.0.1" + hashes = [ + "h1:SzM8nt2wzLMI28A3CWAtW25g3ZCm1O4xD0h3Ps/rU1U=", + "zh:0d4f683868324af056a9eb2b06306feef7c202c88dbbe6a4ad7517146a22fb50", + "zh:4824b3c7914b77d41dfe90f6f333c7ac9860afb83e2a344d91fbe46e5dfbec26", + "zh:4b82e43712f3cf0d0cbc95b2cbcd409ba8f0dc7848fdfb7c13633c27468ed04a", + "zh:78b3a2b860c3ebc973a794000015f5946eb59b82705d701d487475406b2612f1", + "zh:88bc65197bd74ff408d147b32f0045372ae3a3f2a2fdd7f734f315d988c0e4a2", + "zh:91bd3c9f625f177f3a5d641a64e54d4b4540cb071070ecda060a8261fb6eb2ef", + "zh:a6818842b28d800f784e0c93284ff602b0c4022f407e4750da03f50b853a9a2c", + "zh:c4a1a2b52abd05687e6cfded4a789dcd7b43e7a746e4d02dd1055370cf9a994d", + "zh:cf65041bf12fc3bde709c1d267dbe94142bc05adcabc4feb17da3b12249132ac", + "zh:e385e00e7425dda9d30b74ab4ffa4636f4b8eb23918c0b763f0ffab84ece0c5c", + ] +} diff --git a/layers/security_identity_compliance/security_services/aws-config.tf b/layers/security_identity_compliance/security_services/aws-config.tf new file mode 100644 index 0000000..97c972d --- /dev/null +++ b/layers/security_identity_compliance/security_services/aws-config.tf @@ -0,0 +1,16 @@ +/* + Deploy aws config service. If it is already enabled in the account, import existing + config record with + ▶ terraform import module.aws-config-module.aws_config_configuration_recorder.config-recorder default + +*/ + +module aws-config-module { + source = "../../../modules/security_identity_compliance/aws_config" + application = var.application + environment = var.environment + customer-name = var.customer-name + project = var.project + aws-region-short = var.aws-region-short + default-tags = local.default-tags +} \ No newline at end of file diff --git a/layers/security_identity_compliance/security_services/main.tf b/layers/security_identity_compliance/security_services/main.tf new file mode 100644 index 0000000..8662c3d --- /dev/null +++ b/layers/security_identity_compliance/security_services/main.tf @@ -0,0 +1 @@ +data aws_caller_identity this {} diff --git a/layers/security_identity_compliance/security_services/provider.tf b/layers/security_identity_compliance/security_services/provider.tf new file mode 100644 index 0000000..4e906ad --- /dev/null +++ b/layers/security_identity_compliance/security_services/provider.tf @@ -0,0 +1,13 @@ +provider "aws" { + region = var.aws-region +} + +terraform { + required_version = ">= 0.14" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.25" + } + } +} \ No newline at end of file diff --git a/layers/security_identity_compliance/security_services/terraform.tfvars b/layers/security_identity_compliance/security_services/terraform.tfvars new file mode 100644 index 0000000..9f12b0d --- /dev/null +++ b/layers/security_identity_compliance/security_services/terraform.tfvars @@ -0,0 +1,6 @@ +aws-region = "ap-northeast-1" +aws-region-short = "apne1" +customer-name = "racken" +environment = "lab" +project = "cleanslate" +application = "infra" \ No newline at end of file diff --git a/layers/security_identity_compliance/security_services/variables.tf b/layers/security_identity_compliance/security_services/variables.tf new file mode 100644 index 0000000..b705e28 --- /dev/null +++ b/layers/security_identity_compliance/security_services/variables.tf @@ -0,0 +1,22 @@ +variable "aws-region" {} +variable "aws-region-short" {} +variable "customer-name" {} +variable "environment" {} +variable "project" {} +variable "application" {} + +locals { + default-tags = { + ServiceProvider = "RackspaceTechnology" + Environment = var.environment + Project = var.project + Application = var.application + TerraformMode = "managed" + TerraformDir = trimprefix(path.cwd, "/my/work/xpk-git/") + CreatedBy = data.aws_caller_identity.this.arn + BuildDate = formatdate("YYYYMMDD", timestamp()) + } + ct-bucket-name = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}-ctbucket-${data.aws_caller_identity.this.account_id}" + resource-prefix = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}" +} + diff --git a/modules/security_identity_compliance/aws_config/README.md b/modules/security_identity_compliance/aws_config/README.md new file mode 100644 index 0000000..b3ea62c --- /dev/null +++ b/modules/security_identity_compliance/aws_config/README.md @@ -0,0 +1,16 @@ +# Overview +This module performs the following tasks: + +- Enable AWS config +- Create s3 bucket for config use + +## Inputs: +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:-----:| +| application | name of application | string | none | yes | +| environment | capacity of environment (prd/dev/lab) | string | none | yes | +| customer-name | owner of aws resources | string | none | yes | +| project | name of project | string | none | yes | +| default-tags | tags to be added to resources | list | none | yes | +| aws-region-short | short name of aws region (e.g. apne1) | string | none | yes | + diff --git a/modules/security_identity_compliance/aws_config/main.tf b/modules/security_identity_compliance/aws_config/main.tf new file mode 100644 index 0000000..ff8ca73 --- /dev/null +++ b/modules/security_identity_compliance/aws_config/main.tf @@ -0,0 +1,115 @@ +/* + AWS Config Service + If config is already enabled, import it with + terraform import aws_config_configuration_recorder.config-recorder default +*/ + +data aws_caller_identity this {} + +resource "aws_iam_service_linked_role" "config" { + aws_service_name = "config.amazonaws.com" +} + +resource "aws_config_configuration_recorder" "config-recorder" { + name = "${local.resource-prefix}-awsconfig" + role_arn = aws_iam_service_linked_role.config.arn + + recording_group { + all_supported = true + include_global_resource_types = true + } +} + +resource "aws_config_delivery_channel" "config-delivery-channel" { + name = "${local.resource-prefix}-configdeliverychannel" + s3_bucket_name = module.config-bucket.bucket-name + + depends_on = [aws_config_configuration_recorder.config-recorder] +} + +resource "aws_config_configuration_recorder_status" "main" { + name = aws_config_configuration_recorder.config-recorder.name + is_enabled = true + depends_on = [aws_config_delivery_channel.config-delivery-channel] +} + +######## Config Bucket - Policy ######## + +module config-bucket { + source = "../../storage/infra-s3-bucket" + + application = var.application + aws-region-short = var.aws-region-short + bucket-name = "${local.resource-prefix}-configbucket-${data.aws_caller_identity.this.account_id}" + add-random-suffix = false + bucket-policy-json = data.aws_iam_policy_document.config_bucket_policy.json + customer-name = var.customer-name + default-tags = var.default-tags + environment = var.environment + project = var.project +} + +data "aws_iam_policy_document" "config_bucket_policy" { + + statement { + sid = "AWSConfigBucketPermissionsCheck" + + principals { + type = "Service" + identifiers = ["config.amazonaws.com"] + } + + actions = [ + "s3:GetBucketAcl", + ] + + resources = [ + "arn:aws:s3:::${local.resource-prefix}-configbucket-${data.aws_caller_identity.this.account_id}", + ] + } + + statement { + sid = "AWSConfigBucketExistenceCheck" + + principals { + type = "Service" + identifiers = ["config.amazonaws.com"] + } + + actions = [ + "s3:ListBucket", + ] + + resources = [ + "arn:aws:s3:::${local.resource-prefix}-configbucket-${data.aws_caller_identity.this.account_id}", + ] + } + + statement { + sid = "AWSConfigBucketDelivery" + + principals { + type = "Service" + identifiers = ["config.amazonaws.com"] + } + + actions = [ + "s3:PutObject", + ] + + resources = [ + "arn:aws:s3:::${local.resource-prefix}-configbucket-${data.aws_caller_identity.this.account_id}/*", + ] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + + values = [ + "bucket-owner-full-control", + ] + } + } +} + + diff --git a/modules/security_identity_compliance/aws_config/outputs.tf b/modules/security_identity_compliance/aws_config/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/security_identity_compliance/aws_config/variables.tf b/modules/security_identity_compliance/aws_config/variables.tf new file mode 100644 index 0000000..e1dcf7f --- /dev/null +++ b/modules/security_identity_compliance/aws_config/variables.tf @@ -0,0 +1,12 @@ +variable "customer-name" {} +variable "environment" {} +variable "project" {} +variable "application" {} +variable "aws-region-short" {} +variable "default-tags" {} + +locals { + ct-bucket-name = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}-ctbucket-${data.aws_caller_identity.this.account_id}" + resource-prefix = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}" +} + diff --git a/modules/storage/infra-s3-bucket/README.md b/modules/storage/infra-s3-bucket/README.md new file mode 100644 index 0000000..a4cfe02 --- /dev/null +++ b/modules/storage/infra-s3-bucket/README.md @@ -0,0 +1,20 @@ +# Overview +This module performs the following tasks: + +- Create s3 bucket using default settings and AWS AES256 encryption + +## Inputs: +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:-----:| +| application | name of application | string | none | yes | +| environment | capacity of environment (prd/dev/lab) | string | none | yes | +| customer-name | owner of aws resources | string | none | yes | +| project | name of project | string | none | yes | +| default-tags | tags to be added to resources | list | none | yes | +| aws-region-short | short name of aws region (e.g. apne1) | string | none | yes | +| bucket-name | name or prefix of s3 bucket | string | none | yes | +| add-random-suffix | Whether to append a random string to bucket name | bool | false | no | +| bucket-policy-json | bucket policy | json | none | yes | +| enable-bucket-versioning | Whether to enable bucket versioning | book | false | yes | +| bucket-retain-days | Days before s3 objects are expired on s3 | number | 90 | yes | + diff --git a/modules/storage/infra-s3-bucket/main.tf b/modules/storage/infra-s3-bucket/main.tf new file mode 100644 index 0000000..31b094a --- /dev/null +++ b/modules/storage/infra-s3-bucket/main.tf @@ -0,0 +1,54 @@ +module random-suffix { + source = "../../util/random" +} + +resource "aws_s3_bucket" "s3bucket" { + bucket = var.add-random-suffix ? "${var.bucket-name}-${module.random-suffix.number}" : var.bucket-name + policy = var.bucket-policy-json + + versioning { + enabled = var.enable-bucket-versioning + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + // kms_master_key_id = aws_kms_key.some-key.arn + sse_algorithm = "AES256" + } + } + } + tags = var.default-tags + + lifecycle_rule { + id = "${var.bucket-name}-ctbucket-lifecycle-rule" + enabled = true + + transition { + days = 30 + storage_class = "INTELLIGENT_TIERING" + } + + expiration { + days = var.bucket-retain-days + } + } +} + + +resource "aws_s3_bucket_public_access_block" "s3-public-access-settings" { + bucket = aws_s3_bucket.s3bucket.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_ownership_controls" "ctbucket-ownership-setting" { + bucket = aws_s3_bucket.s3bucket.id + + rule { + object_ownership = "BucketOwnerPreferred" + } +} \ No newline at end of file diff --git a/modules/storage/infra-s3-bucket/outputs.tf b/modules/storage/infra-s3-bucket/outputs.tf new file mode 100644 index 0000000..46af43c --- /dev/null +++ b/modules/storage/infra-s3-bucket/outputs.tf @@ -0,0 +1,3 @@ +output bucket-name { + value = aws_s3_bucket.s3bucket.id +} \ No newline at end of file diff --git a/modules/storage/infra-s3-bucket/variables.tf b/modules/storage/infra-s3-bucket/variables.tf new file mode 100644 index 0000000..f265abb --- /dev/null +++ b/modules/storage/infra-s3-bucket/variables.tf @@ -0,0 +1,25 @@ +variable "customer-name" {} +variable "environment" {} +variable "project" {} +variable "application" {} +variable "aws-region-short" {} +variable "default-tags" {} +variable "bucket-retain-days" { + type = number + default = 90 +} +variable "bucket-name" {} +variable "bucket-policy-json" {} +variable "enable-bucket-versioning" { + type = bool + default = false +} +variable "add-random-suffix" { + type = bool + default = false +} + +locals { + resource-prefix = "${var.environment}-${var.aws-region-short}-${var.customer-name}-${var.project}" +} + diff --git a/modules/util/random/main.tf b/modules/util/random/main.tf new file mode 100644 index 0000000..6a4d35d --- /dev/null +++ b/modules/util/random/main.tf @@ -0,0 +1,17 @@ +resource "random_string" "string" { + length = 4 + special = false +} + +resource "random_integer" "number" { + min = 1000 + max = 9999 +} + +output "string" { + value = random_string.string.result +} + +output "number" { + value = random_integer.number.result +}