himari-aws 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +127 -14
  4. data/Rakefile +2 -0
  5. data/lambda/Dockerfile +40 -0
  6. data/lambda/Gemfile +35 -0
  7. data/lambda/Gemfile.lock +374 -0
  8. data/lambda/README.md +42 -0
  9. data/lambda/entrypoint.rb +5 -0
  10. data/lambda/terraform/README.md +92 -0
  11. data/lambda/terraform/functions/aws.tf +2 -0
  12. data/lambda/terraform/functions/dynamodb.tf +18 -0
  13. data/lambda/terraform/functions/lambda_rack.tf +66 -0
  14. data/lambda/terraform/functions/lambda_secrets_rotation.tf +33 -0
  15. data/lambda/terraform/functions/outputs.tf +19 -0
  16. data/lambda/terraform/functions/variables.tf +65 -0
  17. data/lambda/terraform/functions/versions.tf +7 -0
  18. data/lambda/terraform/iam/aws.tf +2 -0
  19. data/lambda/terraform/iam/outputs.tf +7 -0
  20. data/lambda/terraform/iam/role.tf +77 -0
  21. data/lambda/terraform/iam/variables.tf +44 -0
  22. data/lambda/terraform/iam/versions.tf +8 -0
  23. data/lambda/terraform/image/aws.tf +1 -0
  24. data/lambda/terraform/image/copy.tf +45 -0
  25. data/lambda/terraform/image/ecr.tf +42 -0
  26. data/lambda/terraform/image/outputs.tf +9 -0
  27. data/lambda/terraform/image/variables.tf +20 -0
  28. data/lambda/terraform/image/versions.tf +9 -0
  29. data/lambda/terraform/signing_key/aws.tf +1 -0
  30. data/lambda/terraform/signing_key/outputs.tf +3 -0
  31. data/lambda/terraform/signing_key/secret.tf +18 -0
  32. data/lambda/terraform/signing_key/variables.tf +24 -0
  33. data/lambda/terraform/signing_key/versions.tf +7 -0
  34. data/lib/himari/aws/dynamodb_storage.rb +41 -16
  35. data/lib/himari/aws/lambda_handler.rb +76 -0
  36. data/lib/himari/aws/secretsmanager_signing_key_provider.rb +8 -5
  37. data/lib/himari/aws/secretsmanager_signing_key_rotation_handler.rb +36 -9
  38. data/lib/himari/aws/version.rb +1 -1
  39. data/lib/himari-aws.rb +2 -0
  40. metadata +49 -10
  41. data/Gemfile +0 -12
  42. data/Gemfile.lock +0 -171
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # BUNDLE_GEMFILE is defined at Dockerfile
4
+ require 'bundler/setup'
5
+ require 'himari/aws/lambda_handler'
@@ -0,0 +1,92 @@
1
+ # Himari Terraform modules for AWS Lambda
2
+
3
+ himari-aws/lambda/terraform provides the following modules:
4
+
5
+ - **iam:** to establish IAM role
6
+ - **image:** to copy prebuilt container image for Lambda from ECR Public
7
+ - **functions:** to deploy Lambda function
8
+ - **signing_key:** to create a secret with auto rotation enabled on Secrets Manager
9
+
10
+ ## iam
11
+
12
+ Provisions IAM role for Lambda functions.
13
+
14
+ ```terraform
15
+ module "himari_iam" {
16
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/iam"
17
+
18
+ role_name = "HimariRole"
19
+
20
+ # for policy hardening
21
+ secrets_rotation_function_arn = module.himari_functions.secrets_rotation_function_arn
22
+
23
+ # Add grants
24
+ dynamodb_table_arn = module.himari_functions.dynamodb_table_arn
25
+ secret_arns = toset([module.himari_signing_key.secret_arn])
26
+ }
27
+ ```
28
+
29
+ ## image
30
+
31
+ Create ECR private repository then mirror specified image tag from https://gallery.ecr.aws/sorah/himari-lambda
32
+
33
+ ```terraform
34
+ module "himari_image" {
35
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/image"
36
+
37
+ repository_name = "himari-lambda"
38
+ source_image_tag = "" # Replace with image tag
39
+ architecture = "x86_64" # or arm64; must match the Lambda architecture
40
+ }
41
+ ```
42
+
43
+ - Uses null_resource with `skopeo` command to copy the image to ECR private locally (requires `skopeo` on the machine running Terraform)
44
+ - `architecture` selects which platform to copy out of the multi-arch source image (defaults to `x86_64`); set it to match the `architecture` you pass to the functions module
45
+ - Requires Terraform >= 1.10 and AWS provider >= 5.83 (ephemeral resource for ECR credentials)
46
+ - Prebuilt image tag is based on git commit SHA: https://github.com/sorah/himari/commits/main
47
+
48
+ ## functions
49
+
50
+ Deploy lambda functions and DynamoDB table
51
+
52
+ ```terraform
53
+ module "himari_functions" {
54
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/functions"
55
+
56
+ iam_role_arn = module.himari_iam.role_arn
57
+ image_url = module.himari_image.image.url
58
+
59
+ dynamodb_table_name = "himari"
60
+ function_name_prefix = "himari"
61
+
62
+ config_ru = file("${path.module}/config.ru")
63
+
64
+ environment = {
65
+ HIMARI_SIGNING_KEY_ARN = module.himari_signing_key.secret_arn
66
+ HIMARI_SECRET_PARAMS_ARN = aws_secretsmanager_secret.params.arn
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## signing_key
72
+
73
+ ```terraform
74
+ module "himari_signing_key" {
75
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/signing_key"
76
+
77
+ secret_name = "himari-prd-signing-key"
78
+
79
+ rotation_function_arn = module.himari_functions.secrets_rotation_function_arn
80
+ rotate_automatically_after_days = 20
81
+ }
82
+ ```
83
+
84
+ ## misc (not modules)
85
+
86
+ Use secrets manager to store additional secrets like upstream client secrets and SECRET_KEY_BASE...
87
+
88
+ ```terraform
89
+ resource "aws_secretsmanager_secret" "params" {
90
+ name = "himari-secret-params"
91
+ }
92
+ ```
@@ -0,0 +1,2 @@
1
+ data "aws_region" "current" {}
2
+ data "aws_caller_identity" "current" {}
@@ -0,0 +1,18 @@
1
+ resource "aws_dynamodb_table" "table" {
2
+ count = var.create_dynamodb_table ? 1 : 0
3
+
4
+ name = var.dynamodb_table_name
5
+ billing_mode = "PAY_PER_REQUEST"
6
+ hash_key = "pk"
7
+ range_key = "sk"
8
+
9
+ attribute {
10
+ name = "pk"
11
+ type = "S"
12
+ }
13
+
14
+ attribute {
15
+ name = "sk"
16
+ type = "S"
17
+ }
18
+ }
@@ -0,0 +1,66 @@
1
+ resource "aws_lambda_function" "rack" {
2
+ count = var.deploy_rack ? 1 : 0
3
+
4
+ function_name = "${var.function_name_prefix}-rack"
5
+
6
+ package_type = "Image"
7
+ image_uri = var.image_url
8
+ architectures = var.architectures
9
+
10
+ image_config {
11
+ command = ["himari_lambda_entrypoint.Himari::Aws::LambdaHandler.rack_handler"]
12
+ }
13
+
14
+ role = var.iam_role_arn
15
+
16
+ memory_size = var.rack_memory_size
17
+ timeout = 20
18
+
19
+ environment {
20
+ variables = merge({
21
+ HIMARI_RACK_DYNAMODB_TABLE = var.dynamodb_table_name
22
+ HIMARI_DYNAMODB_TABLE = var.dynamodb_table_name
23
+
24
+ # dependency trick. see below
25
+ HIMARI_RACK_DIGEST = nonsensitive(jsondecode(aws_dynamodb_table_item.config_ru[local.config_ru_dgst].item)["dgst"]["S"])
26
+
27
+ RACK_ENV = "production"
28
+ }, var.environment)
29
+ }
30
+
31
+ depends_on = [aws_dynamodb_table_item.config_ru]
32
+ }
33
+
34
+ resource "aws_lambda_function_url" "rack" {
35
+ count = (var.deploy_rack && var.enable_function_url) ? 1 : 0
36
+ function_name = aws_lambda_function.rack[0].function_name
37
+ authorization_type = "NONE"
38
+ }
39
+
40
+ resource "aws_dynamodb_table_item" "config_ru" {
41
+ # Employing dependency trick to make sure a previous config_ru item removed after the function environment value update.
42
+ # By using for_each every updates will be a new resource and is referred by aws_lambda_function as a dependency, old item will be removed after updating the function completes.
43
+ for_each = { "${local.config_ru_dgst}" = var.config_ru }
44
+
45
+ table_name = var.dynamodb_table_name
46
+ hash_key = "pk"
47
+ range_key = "sk"
48
+
49
+ # using sensitive to supress unwanted diff, and diff is useful as we use for_each here
50
+ item = sensitive(jsonencode({
51
+ "pk" = { "S" = "rack" },
52
+ "sk" = { "S" = "rack:${each.key}" },
53
+ "dgst" = { "S" = each.key },
54
+ "file" = { "S" = each.value },
55
+ }))
56
+
57
+ lifecycle {
58
+ create_before_destroy = true
59
+ }
60
+
61
+ depends_on = [aws_dynamodb_table.table]
62
+ }
63
+
64
+ locals {
65
+ config_ru_dgst = base64sha256(var.config_ru)
66
+ }
@@ -0,0 +1,33 @@
1
+ resource "aws_lambda_function" "secrets_rotation" {
2
+ count = var.deploy_secrets_rotation ? 1 : 0
3
+
4
+ function_name = "${var.function_name_prefix}-secrets-rotation"
5
+
6
+ package_type = "Image"
7
+ image_uri = var.image_url
8
+ architectures = var.architectures
9
+
10
+ image_config {
11
+ command = ["himari_lambda_entrypoint.Himari::Aws::LambdaHandler.secrets_rotation_handler"]
12
+ }
13
+
14
+ role = var.iam_role_arn
15
+
16
+ memory_size = 128
17
+ timeout = 20
18
+
19
+ environment {
20
+ variables = merge({
21
+ }, var.environment)
22
+ }
23
+ }
24
+
25
+ resource "aws_lambda_permission" "secrets_rotation_secretsmanager" {
26
+ count = var.deploy_secrets_rotation ? 1 : 0
27
+
28
+ statement_id = "secretsmanager"
29
+ action = "lambda:InvokeFunction"
30
+ function_name = aws_lambda_function.secrets_rotation[0].function_name
31
+ principal = "secretsmanager.amazonaws.com"
32
+ source_account = data.aws_caller_identity.current.account_id
33
+ }
@@ -0,0 +1,19 @@
1
+ output "dynamodb_table_name" {
2
+ value = var.dynamodb_table_name
3
+ }
4
+
5
+ output "dynamodb_table_arn" {
6
+ value = var.create_dynamodb_table ? aws_dynamodb_table.table[0].arn : null
7
+ }
8
+
9
+ output "function_url" {
10
+ value = (var.deploy_rack && var.enable_function_url) ? aws_lambda_function_url.rack[0].function_url : null
11
+ }
12
+
13
+ output "rack_function_arn" {
14
+ value = var.deploy_rack ? aws_lambda_function.rack[0].arn : null
15
+ }
16
+
17
+ output "secrets_rotation_function_arn" {
18
+ value = var.deploy_secrets_rotation ? aws_lambda_function.secrets_rotation[0].arn : null
19
+ }
@@ -0,0 +1,65 @@
1
+ variable "iam_role_arn" {
2
+ type = string
3
+ description = "IAM role arn for functions"
4
+ }
5
+
6
+ variable "image_url" {
7
+ type = string
8
+ description = "Image url for deploy"
9
+ }
10
+
11
+ variable "dynamodb_table_name" {
12
+ type = string
13
+ description = "dynamodb table name to use"
14
+ }
15
+
16
+ variable "create_dynamodb_table" {
17
+ type = bool
18
+ description = "Create dynamodb table"
19
+ default = true
20
+ }
21
+
22
+ variable "function_name_prefix" {
23
+ type = string
24
+ description = "function name prefix"
25
+ }
26
+
27
+ variable "deploy_rack" {
28
+ type = bool
29
+ description = "Deploy rack function"
30
+ default = true
31
+ }
32
+
33
+ variable "rack_memory_size" {
34
+ type = number
35
+ default = 256
36
+ }
37
+
38
+ variable "deploy_secrets_rotation" {
39
+ type = bool
40
+ description = "Deploy secrets rotation function"
41
+ default = true
42
+ }
43
+
44
+ variable "enable_function_url" {
45
+ type = bool
46
+ description = "Enable function URL"
47
+ default = true
48
+ }
49
+
50
+ variable "config_ru" {
51
+ type = string
52
+ description = "File content of config.ru"
53
+ default = "raise 'empty config_ru'\n"
54
+ }
55
+
56
+ variable "environment" {
57
+ type = map(any)
58
+ description = "Additional environment variables"
59
+ default = {}
60
+ }
61
+
62
+ variable "architectures" {
63
+ type = list(string)
64
+ default = ["x86_64"]
65
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,2 @@
1
+ data "aws_region" "current" {}
2
+ data "aws_caller_identity" "current" {}
@@ -0,0 +1,7 @@
1
+ output "role_arn" {
2
+ value = aws_iam_role.role.arn
3
+ }
4
+
5
+ output "role_name" {
6
+ value = aws_iam_role.role.name
7
+ }
@@ -0,0 +1,77 @@
1
+ resource "aws_iam_role" "role" {
2
+ name = var.role_name
3
+ description = var.role_description
4
+ assume_role_policy = data.aws_iam_policy_document.role-trust.json
5
+ permissions_boundary = var.role_permissions_boundary
6
+ }
7
+
8
+ data "aws_iam_policy_document" "role-trust" {
9
+ statement {
10
+ effect = "Allow"
11
+ actions = ["sts:AssumeRole"]
12
+ principals {
13
+ type = "Service"
14
+ identifiers = [
15
+ "lambda.amazonaws.com"
16
+ ]
17
+ }
18
+ }
19
+ }
20
+
21
+ resource "aws_iam_role_policy_attachment" "role-AWSLambdaBasicExecutionRole" {
22
+ role = aws_iam_role.role.name
23
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
24
+ }
25
+
26
+ resource "aws_iam_role_policy" "role-dynamodb" {
27
+ count = local.dynamodb_table_arn != null ? 1 : 0
28
+ role = aws_iam_role.role.name
29
+ policy = data.aws_iam_policy_document.role-dynamodb.json
30
+ }
31
+
32
+ data "aws_iam_policy_document" "role-dynamodb" {
33
+ statement {
34
+ effect = "Allow"
35
+ actions = [
36
+ "dynamodb:DeleteItem",
37
+ "dynamodb:Query",
38
+ "dynamodb:UpdateItem",
39
+ ]
40
+ resources = [local.dynamodb_table_arn]
41
+ }
42
+ }
43
+
44
+ resource "aws_iam_role_policy" "role-secretsmanager" {
45
+ count = length(var.secret_arns) > 0 ? 1 : 0
46
+ role = aws_iam_role.role.name
47
+ policy = data.aws_iam_policy_document.role-secretsmanager.json
48
+ }
49
+
50
+ data "aws_iam_policy_document" "role-secretsmanager" {
51
+ statement {
52
+ effect = "Allow"
53
+ actions = [
54
+ "secretsmanager:DescribeSecret",
55
+ "secretsmanager:GetSecretValue",
56
+
57
+ ]
58
+ resources = toset(var.secret_arns)
59
+ }
60
+ statement {
61
+ effect = "Allow"
62
+ actions = [
63
+ "secretsmanager:PutSecretValue",
64
+ "secretsmanager:UpdateSecretVersionStage",
65
+ ]
66
+ dynamic "condition" {
67
+ for_each = var.secrets_rotation_function_arn != null ? { hardening = true } : {}
68
+ content {
69
+ test = "StringEquals"
70
+ variable = "lambda:SourceFunctionArn"
71
+ values = [var.secrets_rotation_function_arn]
72
+ }
73
+ }
74
+ resources = toset(var.secret_arns)
75
+ }
76
+
77
+ }
@@ -0,0 +1,44 @@
1
+ variable "role_name" {
2
+ type = string
3
+ description = "IAM Role name to create"
4
+ }
5
+
6
+ variable "role_description" {
7
+ type = string
8
+ description = "IAM Role description to specify"
9
+ default = "sorah/himari lambda function role"
10
+ }
11
+
12
+ variable "role_permissions_boundary" {
13
+ type = string
14
+ description = "IAM Role permissions boundary to specify"
15
+ default = null
16
+ }
17
+
18
+ variable "dynamodb_table_arn" {
19
+ type = string
20
+ description = "DynamoDB Table ARN"
21
+ default = null
22
+ }
23
+
24
+ variable "dynamodb_table_name" {
25
+ type = string
26
+ description = "DynamoDB Table name"
27
+ default = null
28
+ }
29
+
30
+ variable "secret_arns" {
31
+ type = set(string)
32
+ description = "Secrets Manager secret ARNs"
33
+ default = null
34
+ }
35
+
36
+ variable "secrets_rotation_function_arn" {
37
+ type = string
38
+ description = "ARN of rotation function. If set, it will be used to harden the write action policy"
39
+ default = null
40
+ }
41
+
42
+ locals {
43
+ dynamodb_table_arn = coalesce(var.dynamodb_table_arn, var.dynamodb_table_name != null ? "arn:aws:dynamodb:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:table/${var.dynamodb_table_name}" : null)
44
+ }
@@ -0,0 +1,8 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ version = ">= 6.0"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1 @@
1
+ data "aws_region" "current" {}
@@ -0,0 +1,45 @@
1
+ ephemeral "aws_ecr_authorization_token" "repo" {}
2
+
3
+ locals {
4
+ # Map Lambda's architecture notation to the source image's OS/arch so skopeo
5
+ # picks the matching image out of the multi-arch index deterministically,
6
+ # regardless of the host running Terraform.
7
+ skopeo_platform = {
8
+ x86_64 = { os = "linux", arch = "amd64" }
9
+ arm64 = { os = "linux", arch = "arm64" }
10
+ }[var.architecture]
11
+ }
12
+
13
+ resource "null_resource" "copy-image" {
14
+ triggers = {
15
+ region = data.aws_region.current.region
16
+ repository_url = aws_ecr_repository.repo.repository_url
17
+ source_image_tag = var.source_image_tag
18
+ architecture = var.architecture
19
+ }
20
+
21
+ provisioner "local-exec" {
22
+ interpreter = ["/bin/bash", "-c"]
23
+ # public.ecr.aws is pulled anonymously; only the destination ECR needs credentials.
24
+ # The password is fed over stdin into a temporary authfile rather than passed as a
25
+ # command-line argument, so it never appears in the process argument list.
26
+ command = <<-EOT
27
+ set -euo pipefail
28
+ authfile="$(mktemp)"
29
+ trap 'rm -f "$authfile"' EXIT
30
+ # skopeo login reads the authfile before merging the new credential into it,
31
+ # so seed it with an empty JSON object; mktemp's 0-byte file is invalid JSON.
32
+ printf '{}' > "$authfile"
33
+ printf '%s' "$DEST_PASSWORD" | skopeo login --username AWS --password-stdin --authfile "$authfile" "$${REPOSITORY_URL%%/*}"
34
+ skopeo copy --authfile "$authfile" --override-os "$OVERRIDE_OS" --override-arch "$OVERRIDE_ARCH" "docker://public.ecr.aws/sorah/himari-lambda:$SOURCE_IMAGE_TAG" "docker://$REPOSITORY_URL:$SOURCE_IMAGE_TAG"
35
+ EOT
36
+
37
+ environment = {
38
+ DEST_PASSWORD = ephemeral.aws_ecr_authorization_token.repo.password
39
+ REPOSITORY_URL = aws_ecr_repository.repo.repository_url
40
+ SOURCE_IMAGE_TAG = var.source_image_tag
41
+ OVERRIDE_OS = local.skopeo_platform.os
42
+ OVERRIDE_ARCH = local.skopeo_platform.arch
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,42 @@
1
+ resource "aws_ecr_repository" "repo" {
2
+ name = var.repository_name
3
+ }
4
+
5
+ resource "aws_ecr_repository_policy" "repo-lambda" {
6
+ repository = aws_ecr_repository.repo.name
7
+ policy = data.aws_iam_policy_document.repo-lambda.json
8
+ }
9
+
10
+ data "aws_iam_policy_document" "repo-lambda" {
11
+ statement {
12
+ effect = "Allow"
13
+ principals {
14
+ type = "Service"
15
+ identifiers = ["lambda.amazonaws.com"]
16
+ }
17
+ actions = [
18
+ "ecr:BatchGetImage",
19
+ "ecr:GetDownloadUrlForLayer"
20
+ ]
21
+ }
22
+ }
23
+
24
+ resource "aws_ecr_lifecycle_policy" "repo" {
25
+ repository = aws_ecr_repository.repo.name
26
+ policy = jsonencode({
27
+ rules = [
28
+ {
29
+ rulePriority = 10
30
+ description = "expire old images"
31
+ selection = {
32
+ tagStatus = "any"
33
+ countType = "imageCountMoreThan"
34
+ countNumber = 10
35
+ }
36
+ action = {
37
+ type = "expire"
38
+ }
39
+ }
40
+ ]
41
+ })
42
+ }
@@ -0,0 +1,9 @@
1
+ output "image" {
2
+ value = {
3
+ url = "${aws_ecr_repository.repo.repository_url}:${var.source_image_tag}"
4
+
5
+ repository_url = aws_ecr_repository.repo.repository_url
6
+ repository_arn = aws_ecr_repository.repo.arn
7
+ }
8
+ depends_on = [null_resource.copy-image]
9
+ }
@@ -0,0 +1,20 @@
1
+ variable "repository_name" {
2
+ type = string
3
+ description = "Repository name to create on your AWS account"
4
+ }
5
+
6
+ variable "source_image_tag" {
7
+ type = string
8
+ description = "Image tag for public.ecr.aws/sorah/himari-lambda. You can use Git commit hash on https://github.com/sorah/himari"
9
+ }
10
+
11
+ variable "architecture" {
12
+ type = string
13
+ default = "x86_64"
14
+ description = "Lambda CPU architecture to copy from the multi-arch source image (x86_64 or arm64)"
15
+
16
+ validation {
17
+ condition = contains(["x86_64", "arm64"], var.architecture)
18
+ error_message = "architecture must be one of: x86_64, arm64."
19
+ }
20
+ }
@@ -0,0 +1,9 @@
1
+ terraform {
2
+ required_version = ">= 1.10"
3
+ required_providers {
4
+ aws = {
5
+ source = "hashicorp/aws"
6
+ version = ">= 6.0"
7
+ }
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ data "aws_region" "current" {}
@@ -0,0 +1,3 @@
1
+ output "secret_arn" {
2
+ value = aws_secretsmanager_secret.signing_key.arn
3
+ }
@@ -0,0 +1,18 @@
1
+ resource "aws_secretsmanager_secret" "signing_key" {
2
+ name = var.secret_name
3
+
4
+ tags = {
5
+ HimariKey = base64encode(jsonencode(var.keygen_params))
6
+ }
7
+ }
8
+
9
+ resource "aws_secretsmanager_secret_rotation" "signing_key" {
10
+ secret_id = aws_secretsmanager_secret.signing_key.id
11
+ rotation_lambda_arn = var.rotation_function_arn
12
+
13
+ # XXX: https://github.com/hashicorp/terraform-provider-aws/issues/22969
14
+ rotation_rules {
15
+ automatically_after_days = 16
16
+ }
17
+
18
+ }
@@ -0,0 +1,24 @@
1
+ variable "secret_name" {
2
+ type = string
3
+ description = "Secret name to create"
4
+ }
5
+
6
+ variable "rotation_function_arn" {
7
+ type = string
8
+ description = "Lambda function ARN to handle secret rotation"
9
+ }
10
+
11
+ variable "rotate_automatically_after_days" {
12
+ type = number
13
+ description = "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation#automatically_after_days"
14
+ default = 16
15
+ }
16
+
17
+ variable "keygen_params" {
18
+ type = object({ kty = string, len = string })
19
+ description = "keygen params"
20
+ default = {
21
+ "kty" = "rsa"
22
+ "len" = 2048
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }