diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 0000000..a878ec2 --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,34 @@ +name: Trivy Scan +on: + push: + branches-ignore: [master, main] + pull_request: + branches: [master, main] + +jobs: + build: + name: Security Scan + runs-on: ubuntu-20.04 + + permissions: + contents: read + packages: read + statuses: write + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + scan-type: 'config' + hide-progress: false + format: 'sarif' + output: 'trivy-results.sarif' + exit-code: '1' + ignore-unfixed: true +# - name: Upload Trivy scan results to GitHub Security tab +# uses: github/codeql-action/upload-sarif@v2 +# with: +# sarif_file: 'trivy-results.sarif' diff --git a/README.md b/README.md index 94d625e..bfb8ad2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ -# aws-terraform-modules +## Introduction AWS Terraform modules for WSO2 cloud deployments + +## Requirements +1. Terraform ( >= v1.3.8 ) +2. AWS Provider ( >= v5.0 ) diff --git a/modules/aws/Cloud-Watch-Log-Group/log_group.tf b/modules/aws/Cloud-Watch-Log-Group/log_group.tf index 5a46003..024dbff 100644 --- a/modules/aws/Cloud-Watch-Log-Group/log_group.tf +++ b/modules/aws/Cloud-Watch-Log-Group/log_group.tf @@ -12,5 +12,6 @@ resource "aws_cloudwatch_log_group" "log_group" { name = var.log_group_name retention_in_days = var.retention_in_days + kms_key_id = var.kms_key_id tags = var.tags } diff --git a/modules/aws/Cloud-Watch-Log-Group/variables.tf b/modules/aws/Cloud-Watch-Log-Group/variables.tf index bfd863b..a36168c 100644 --- a/modules/aws/Cloud-Watch-Log-Group/variables.tf +++ b/modules/aws/Cloud-Watch-Log-Group/variables.tf @@ -23,3 +23,8 @@ variable "retention_in_days" { type = number default = 30 } +variable "kms_key_id" { + description = "The ARN of the KMS Key to use when encrypting log data." + type = string + default = null +} diff --git a/modules/aws/CloudTrail-Logs/variables.tf b/modules/aws/CloudTrail-Logs/variables.tf index 6de35c1..154bcb1 100644 --- a/modules/aws/CloudTrail-Logs/variables.tf +++ b/modules/aws/CloudTrail-Logs/variables.tf @@ -68,7 +68,6 @@ variable "event_selector" { variable "kms_key_arn" { type = string description = "Specifies the KMS key ARN to use to encrypt the logs delivered by CloudTrail" - default = "" } variable "is_organization_trail" { type = bool diff --git a/modules/aws/ECR-IAM-User/iam_role.tf b/modules/aws/ECR-IAM-User/iam_role.tf index 7ef4cd5..6186bd7 100644 --- a/modules/aws/ECR-IAM-User/iam_role.tf +++ b/modules/aws/ECR-IAM-User/iam_role.tf @@ -14,6 +14,9 @@ resource "aws_iam_user" "ecr_access_user" { tags = var.tags } +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/) +# Reason: This if for an Admin user with access to all ECR resources. Hence, the wildcard is required. +# trivy:ignore:AVD-AWS-0057 resource "aws_iam_policy" "ecr_access_policy" { name = join("-", [var.project, var.application, var.environment, var.region, "ecr-access-iam-policy"]) tags = var.tags diff --git a/modules/aws/ECR/ecr.tf b/modules/aws/ECR/ecr.tf index 2056939..80da5ce 100644 --- a/modules/aws/ECR/ecr.tf +++ b/modules/aws/ECR/ecr.tf @@ -9,9 +9,27 @@ # # -------------------------------------------------------------------------------------- +# Ignore: AVD-AWS-0030 (https://avd.aquasec.com/misconfig/aws/ecr/avd-aws-0030/) +# Reason: Scanning on Image push should not be enabled by default and should be customizable per user requirement +# Ignore: AVD-AWS-0033 (https://avd.aquasec.com/misconfig/aws/ecr/avd-aws-0033/) +# Reason: While it has been enabled by default at the module level (check `encryption_type`) +# Further use of customer managed keys will be required per user requirement +# trivy:ignore:AVD-AWS-0030 +# trivy:ignore:AVD-AWS-0033 resource "aws_ecr_repository" "ecr_repository" { name = join("-", [var.project, var.application, var.environment, var.region, "ecr"]) tags = var.tags + + image_tag_mutability = var.image_tag_mutability + + image_scanning_configuration { + scan_on_push = var.scan_on_push # Custom parameter for AVD-AWS-0030 + } + + encryption_configuration { + encryption_type = var.encryption_type # Custom parameter for AVD-AWS-0033 + kms_key = var.encryption_type == "KMS" ? var.kms_key : null + } } resource "aws_iam_policy" "ecr_admin_iam_policy" { diff --git a/modules/aws/ECR/variables.tf b/modules/aws/ECR/variables.tf index 0673823..e60493c 100644 --- a/modules/aws/ECR/variables.tf +++ b/modules/aws/ECR/variables.tf @@ -30,3 +30,23 @@ variable "tags" { description = "Tags to be associated with the EKS" default = {} } +variable "encryption_type" { + type = string + description = "Encryption type for the ECR" + default = "AES256" +} +variable "kms_key" { + type = string + description = "KMS key ID for the ECR" + default = null +} +variable "scan_on_push" { + type = bool + description = "Whether to scan on push" + default = false +} +variable "image_tag_mutability" { + type = string + description = "Whether to allow image tag mutability" + default = "IMMUTABLE" +} diff --git a/modules/aws/EKS-Cluster/eks.tf b/modules/aws/EKS-Cluster/eks.tf index dbf9ce7..a552865 100644 --- a/modules/aws/EKS-Cluster/eks.tf +++ b/modules/aws/EKS-Cluster/eks.tf @@ -9,6 +9,10 @@ # # -------------------------------------------------------------------------------------- +# Ignore: AVD-AWS-0038 (https://avd.aquasec.com/misconfig/aws/eks/avd-aws-0038/) +# Reason: Requirement to enable logs for EKS cluster will vary based on cluster purpose and requirements +# Therefore has not been enforced as a requirement +# trivy:ignore:AVD-AWS-0038 resource "aws_eks_cluster" "eks_cluster" { name = join("-", [var.project, var.application, var.environment, var.region, "eks"]) role_arn = aws_iam_role.iam_role.arn diff --git a/modules/aws/EKS-Cluster/iam_role.tf b/modules/aws/EKS-Cluster/iam_role.tf index 027600f..08d21ca 100644 --- a/modules/aws/EKS-Cluster/iam_role.tf +++ b/modules/aws/EKS-Cluster/iam_role.tf @@ -71,7 +71,11 @@ resource "aws_iam_role" "cluster_autoscaler_role" { data.aws_iam_policy_document.cluster_autoscaler_sts_policy ] } -# IAM Policy for IAM Cluster Autoscaler role allowing ASG operations + +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/) +# Reason: This policy provides the necessary permissions for configuring the cluster autoscaler +# AWS Documentation: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#full-cluster-autoscaler-features-policy-recommended +# trivy:ignore:AVD-AWS-0057 resource "aws_iam_policy" "cluster_autoscaler_policy" { name = join("-", [var.project, var.application, var.environment, var.region, "eks-cluster-autoscaler-iam-policy"]) policy = jsonencode({ @@ -103,7 +107,10 @@ resource "aws_iam_role_policy_attachment" "eks_ca_iam_policy_attach" { ] } -# IAM Role for EFS +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/) +# Reason: This policy provides the necessary permissions for the EKS cluster to mount an EFS as a persistent volume +# Despite the wildcard, the tag definition only allows for accessing resources with a specific tag +# trivy:ignore:AVD-AWS-0057 resource "aws_iam_policy" "node_efs_policy" { name = join("-", [var.project, var.application, var.environment, var.region, "eks-cluster-efs-iam-policy"]) path = "/" @@ -122,6 +129,11 @@ resource "aws_iam_policy" "node_efs_policy" { ], "Effect" : "Allow", "Resource" : "*", + "Condition" : { + "StringEquals" : { + "aws:RequestTag/eks-cluster-usage" : aws_eks_cluster.eks_cluster.name # Special Tag definition for AVD-AWS-0057 + } + } "Sid" : "" } ], @@ -130,7 +142,7 @@ resource "aws_iam_policy" "node_efs_policy" { ) } -resource "aws_iam_role_policy_attachment" "test-attach" { +resource "aws_iam_role_policy_attachment" "efs_policy_attachment" { role = aws_iam_role.iam_role.name policy_arn = aws_iam_policy.node_efs_policy.arn } @@ -144,7 +156,10 @@ resource "aws_iam_role" "cluster_loadbalancer_role" { data.aws_iam_policy_document.cluster_lb_sts_policy ] } -# IAM Policy for IAM Cluster Autoscaler role allowing ASG operations +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/)# This however is an AWS Recommended Policy as per https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json +# Reason: This policy provides the necessary permissions for the EKS cluster to create AWS Load Balancers +# AWS Documentation: https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html +# trivy:ignore:AVD-AWS-0057 resource "aws_iam_policy" "cluster_loadbalancer_policy" { name = join("-", [var.project, var.application, var.environment, var.region, "eks-cluster-lb-iam-policy"]) policy = jsonencode({ @@ -400,7 +415,7 @@ resource "aws_iam_role_policy_attachment" "cluster_loadbalancer_policy_attach" { ] } -# IAM Role for IAM Cluster Autoscaler +# IAM Role for CloudWatch Agents resource "aws_iam_role" "cluster_container_cloudwatch_streamer_role" { assume_role_policy = data.aws_iam_policy_document.cluster_container_cloudwatch_streamer_sts_policy.json name = join("-", [var.project, var.application, var.environment, var.region, "eks-cluster-ccw-iam-role"]) diff --git a/modules/aws/EKS-Node-Group/iam_role.tf b/modules/aws/EKS-Node-Group/iam_role.tf index b587aeb..4ee305f 100644 --- a/modules/aws/EKS-Node-Group/iam_role.tf +++ b/modules/aws/EKS-Node-Group/iam_role.tf @@ -61,6 +61,10 @@ resource "aws_iam_role_policy_attachment" "amazon_cloud_watch_agent_policy" { ] } +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/) +# Reason: This policy provides the necessary permissions for configuring the cluster autoscaler +# AWS Documentation: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#full-cluster-autoscaler-features-policy-recommended +# trivy:ignore:AVD-AWS-0057 resource "aws_iam_policy" "node_group_autoscaler_policy" { name = join("-", [var.eks_cluster_name, var.node_group_name, "eks-cluster-auto-scaler-policy"]) policy = jsonencode({ diff --git a/modules/aws/Elastic-LoadBalancer/elastic_loadbalancer.tf b/modules/aws/Elastic-LoadBalancer/elastic_loadbalancer.tf index 26cb575..e11ee12 100644 --- a/modules/aws/Elastic-LoadBalancer/elastic_loadbalancer.tf +++ b/modules/aws/Elastic-LoadBalancer/elastic_loadbalancer.tf @@ -9,9 +9,12 @@ # # -------------------------------------------------------------------------------------- +# Ignore: AVD-AWS-0053 (https://avd.aquasec.com/misconfig/aws/elb/avd-aws-0053/) +# Reason: We may need public load balancers. As such this has been configured as a parameter. +# trivy:ignore:AVD-AWS-0053 resource "aws_lb" "lb" { name = join("-", [var.project, var.application, var.environment, var.region, "elb"]) - internal = var.internal_usage_flag + internal = var.internal_usage_flag # Defines the Load balancer network connectivity required by AVD-AWS-0053 load_balancer_type = var.load_balancer_type security_groups = var.security_group_ids subnets = var.subnet_ids diff --git a/modules/aws/Elasticache-Cluster/elasticache_cluster.tf b/modules/aws/Elasticache-Cluster/elasticache_cluster.tf index 94c2e0c..0e8d311 100644 --- a/modules/aws/Elasticache-Cluster/elasticache_cluster.tf +++ b/modules/aws/Elasticache-Cluster/elasticache_cluster.tf @@ -17,7 +17,6 @@ resource "aws_elasticache_replication_group" "elasticache_replication_group" { at_rest_encryption_enabled = var.at_rest_encryption_enabled num_cache_clusters = var.num_cache_clusters automatic_failover_enabled = var.automatic_failover_enabled - availability_zones = var.availability_zones replication_group_id = join("-", [var.project, var.application, var.environment, var.region, "ec-rds-rg"]) node_type = var.node_type @@ -26,6 +25,8 @@ resource "aws_elasticache_replication_group" "elasticache_replication_group" { subnet_group_name = var.subnet_group_name security_group_ids = var.security_group_ids + preferred_cache_cluster_azs = var.availability_zones + snapshot_window = var.snapshot_window maintenance_window = var.maintenance_window snapshot_retention_limit = var.snapshot_retention_limit diff --git a/modules/aws/SNS-Topic/sns_topic.tf b/modules/aws/SNS-Topic/sns_topic.tf index 011ad92..50e1995 100644 --- a/modules/aws/SNS-Topic/sns_topic.tf +++ b/modules/aws/SNS-Topic/sns_topic.tf @@ -10,8 +10,9 @@ # -------------------------------------------------------------------------------------- resource "aws_sns_topic" "sns_topic" { - name = join("-", [var.project, var.application, var.environment, var.region, var.topic_name]) - tags = var.tags + name = join("-", [var.project, var.application, var.environment, var.region, var.topic_name]) + kms_master_key_id = var.kms_master_key_id + tags = var.tags } resource "aws_sns_topic_subscription" "subscription" { diff --git a/modules/aws/SNS-Topic/variables.tf b/modules/aws/SNS-Topic/variables.tf index 9b22190..bbe6e40 100644 --- a/modules/aws/SNS-Topic/variables.tf +++ b/modules/aws/SNS-Topic/variables.tf @@ -45,3 +45,8 @@ variable "tags" { description = "Tags to be added to the security group" default = {} } +variable "kms_master_key_id" { + type = string + description = "The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK" + default = null +} diff --git a/modules/aws/VPC-Flow-Log/iam.tf b/modules/aws/VPC-Flow-Log/iam.tf index 8de0d28..f5e0e39 100644 --- a/modules/aws/VPC-Flow-Log/iam.tf +++ b/modules/aws/VPC-Flow-Log/iam.tf @@ -28,6 +28,10 @@ resource "aws_iam_role" "iam_role" { assume_role_policy = data.aws_iam_policy_document.assume_role.json } +# Ignore: AVD-AWS-0057 (https://avd.aquasec.com/misconfig/aws/iam/avd-aws-0057/) +# Reason: This permission is required to publish flow logs to Cloud watch +# AWS documentation: https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-cwl.html +# trivy:ignore:AVD-AWS-0057 data "aws_iam_policy_document" "iam_policy_document" { statement { effect = "Allow" diff --git a/modules/aws/VPC/vpc.tf b/modules/aws/VPC/vpc.tf index 4ee552c..8b1eaec 100644 --- a/modules/aws/VPC/vpc.tf +++ b/modules/aws/VPC/vpc.tf @@ -9,6 +9,9 @@ # # -------------------------------------------------------------------------------------- +# Ignore: AVD-AWS-0178 (https://avd.aquasec.com/misconfig/aws/ec2/avd-aws-0178) +# Reason: For more granular control Flow logs are enabled at the subnet level via a separate module at the subnet level (Refer VPC-Flow-Log Module), instead of the VPC level. +# trivy:ignore:AVD-AWS-0178 resource "aws_vpc" "vpc" { cidr_block = var.vpc_cidr_block enable_dns_support = var.enable_dns_support