The security module that you are going to implement has the following folder structure:
security/
│
├── certificate/
│   
├── gha-role/
│   
├── main.tf
│   
├── outputs.tf
│   
└── variables.tf
You then start building the submodules and configuration files required for the security module.
1. The security/certificate submodule is defined by the following structure:
security/
│
├── certificate/
│   │
│   ├── main.tf
│   │ 
│   ├── outputs.tf
│   │
│   └── variables.tf
└── ...
Fill the following lines of code to security/certificate/variables.tf:
variable "hosted_zone_id" {
  description = "The id of the Route53 hosted zone"
  type        = string
}
variable "domain_name" {
  description = "The domain name of the website"
  type        = string
}
Fill the following lines of code to security/certificate/main.tf:
resource "aws_acm_certificate" "main" {
  domain_name       = var.domain_name
  validation_method = "DNS"
}
resource "aws_route53_record" "main" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }
  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = var.hosted_zone_id
}
resource "aws_acm_certificate_validation" "main" {
  certificate_arn         = aws_acm_certificate.main.arn
  validation_record_fqdns = [for record in aws_route53_record.main : record.fqdn]
}
Fill the following lines of code to security/certificate/outputs.tf:
output "arn" {
  description = "The arn of the certificate"
  value       = aws_acm_certificate_validation.main.certificate_arn
}
2. The security/gha-role submodule is defined by the following structure:
security/
│
├── gha-role/
│   │
│   ├── gha-trust-policy.tpl
│   │
│   ├── main.tf
│   │ 
│   ├── outputs.tf
│   │
│   └── variables.tf
└── ...
Fill the following lines of code to security/gha-role/gha-trust-policy.tpl:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "${gh_oidc_provider_arn}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:${github_org}/${github_repo}:*"
        },
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
Fill the following lines of code to security/gha-role/variables.tf:
variable "gh_oidc_provider_arn" {
  description = "The arn of GitHub openid connect provider"
  type        = string
}
variable "role_name" {
  description = "The name of the role"
  type        = string
}
variable "policy_arn" {
  description = "The policy arn for the role"
  type        = string
}
variable "github_org" {
  description = "The GitHub organization that the Github Actions role trusts"
  type        = string
}
variable "github_repo" {
  description = "The GitHub repository that the Github Actions role trusts"
  type        = string
}
Fill the following lines of code to security/gha-role/main.tf:
resource "aws_iam_role" "github_actions" {
  name = var.role_name
  assume_role_policy = templatefile("${path.module}/gha-trust-policy.tpl", {
    gh_oidc_provider_arn = var.gh_oidc_provider_arn,
    github_org           = var.github_org,
    github_repo          = var.github_repo
  })
  managed_policy_arns = [var.policy_arn]
}
Fill the following lines of code to security/gha-role/outputs.tf:
output "arn" {
  description = "The role arn to use for GitHub Actions"
  value       = aws_iam_role.github_actions.arn
}
output "name" {
  description = "The role name to use for GitHub Actions"
  value       = aws_iam_role.github_actions.name
}
3. You now implement the Terraform configuration files for security module.
Fill the following lines of code to security/variables.tf:
variable "environment" {
  description = "The environment to which the security resources delploy"
  type        = string
}
variable "project_name" {
  description = "The name of the project"
  type        = string
}
Fill the following lines of code to security/main.tf:
resource "aws_iam_openid_connect_provider" "main" {
  url             = "https://token.actions.githubusercontent.com"
  thumbprint_list = ["1b511abead59c6ce207077c0bf0e0043b1382612"]
  client_id_list = [
    "sts.amazonaws.com",
  ]
}
Fill the following lines of code to security/outputs.tf:
output "gh_oidc_provider_arn" {
  value       = aws_iam_openid_connect_provider.main.arn
  description = "The arn of Github openid connect provider"
}
4. Commit and push the module to the GitHub repository.
git add . && \
git commit -m "add security module" && \
git push