diff --git a/README.md b/README.md index 190ad92..1694b2e 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,14 @@ module "custom_pod_identity" { additional = aws_iam_policy.additional.arn } + associations = { + custom-association = { + cluster_name = "custom-cluster" + namespace = "custom-namespace" + service_account = "custom-service-account" + } + } + tags = { Environment = "dev" } @@ -67,6 +75,14 @@ module "aws_gateway_controller_pod_identity" { attach_aws_gateway_controller_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "aws-application-networking-system" + service_account = "gateway-api-controller" + } + } + tags = { Environment = "dev" } @@ -84,6 +100,14 @@ module "cert_manager_pod_identity" { attach_cert_manager_policy = true cert_manager_hosted_zone_arns = ["arn:aws:route53:::hostedzone/IClearlyMadeThisUp"] + associations = { + this = { + cluster_name = "example" + namespace = "cert-manager" + service_account = "cert-manager" + } + } + tags = { Environment = "dev" } @@ -100,13 +124,20 @@ module "aws_cloudwatch_observability_pod_identity" { attach_aws_cloudwatch_observability_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "amazon-cloudwatch" + service_account = "cloudwatch-agent" + } + } + tags = { Environment = "dev" } } ``` - ### [Cluster Autoscaler](https://github.com/kubernetes/autoscaler) ```hcl @@ -118,6 +149,14 @@ module "cluster_autoscaler_pod_identity" { attach_cluster_autoscaler_policy = true cluster_autoscaler_cluster_names = ["foo"] + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "cluster-autoscaler-sa" + } + } + tags = { Environment = "dev" } @@ -135,6 +174,14 @@ module "aws_ebs_csi_pod_identity" { attach_aws_ebs_csi_policy = true aws_ebs_csi_kms_arns = ["arn:aws:kms:*:*:key/1234abcd-12ab-34cd-56ef-1234567890ab"] + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "ebs-csi-controller-sa" + } + } + tags = { Environment = "dev" } @@ -151,6 +198,14 @@ module "aws_efs_csi_pod_identity" { attach_aws_efs_csi_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "efs-csi-controller-sa" + } + } + tags = { Environment = "dev" } @@ -168,6 +223,14 @@ module "external_dns_pod_identity" { attach_external_dns_policy = true external_dns_hosted_zone_arns = ["arn:aws:route53:::hostedzone/IClearlyMadeThisUp"] + associations = { + this = { + cluster_name = "example" + namespace = "external-dns" + service_account = "external-dns-sa" + } + } + tags = { Environment = "dev" } @@ -188,6 +251,14 @@ module "external_secrets_pod_identity" { external_secrets_kms_key_arns = ["arn:aws:kms:*:*:key/1234abcd-12ab-34cd-56ef-1234567890ab"] external_secrets_create_permission = true + associations = { + this = { + cluster_name = "example" + namespace = "external-secrets" + service_account = "external-secrets-sa" + } + } + tags = { Environment = "dev" } @@ -205,6 +276,14 @@ module "aws_fsx_lustre_csi_pod_identity" { attach_aws_fsx_lustre_csi_policy = true aws_fsx_lustre_csi_service_role_arns = ["arn:aws:iam::*:role/aws-service-role/s3.data-source.lustre.fsx.amazonaws.com/*"] + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "fsx-csi-controller-sa" + } + } + tags = { Environment = "dev" } @@ -221,6 +300,14 @@ module "aws_lb_controller_pod_identity" { attach_aws_lb_controller_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "aws-load-balancer-controller-sa" + } + } + tags = { Environment = "dev" } @@ -238,6 +325,14 @@ module "aws_lb_controller_targetgroup_binding_only_pod_identity" { attach_aws_lb_controller_targetgroup_binding_only_policy = true aws_lb_controller_targetgroup_arns = ["arn:aws:elasticloadbalancing:*:*:targetgroup/foo/bar"] + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "aws-load-balancer-controller-tgb-sa" + } + } + tags = { Environment = "dev" } @@ -254,6 +349,14 @@ module "aws_appmesh_controller_pod_identity" { attach_aws_appmesh_controller_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "appmesh-system" + service_account = "appmesh-controller" + } + } + tags = { Environment = "dev" } @@ -270,6 +373,14 @@ module "aws_appmesh_envoy_proxy_pod_identity" { attach_aws_appmesh_envoy_proxy_policy = true + associations = { + this = { + cluster_name = "example" + namespace = "appmesh-system" + service_account = "envoy-proxy" + } + } + tags = { Environment = "dev" } @@ -287,6 +398,14 @@ module "amazon_managed_service_prometheus_pod_identity" { attach_amazon_managed_service_prometheus_policy = true amazon_managed_service_prometheus_workspace_arns = ["arn:aws:prometheus:*:*:workspace/foo"] + associations = { + this = { + cluster_name = "example" + namespace = "prometheus" + service_account = "prometheus" + } + } + tags = { Environment = "dev" } @@ -305,6 +424,14 @@ module "mountpoint_s3_csi_pod_identity" { mountpoint_s3_csi_bucket_arns = ["arn:aws:s3:::mountpoint-s3"] mountpoint_s3_csi_bucket_path_arns = ["arn:aws:s3:::mountpoint-s3/example/*"] + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "s3-csi-driver-sa" + } + } + tags = { Environment = "dev" } @@ -322,11 +449,20 @@ module "aws_node_termination_handler_pod_identity" { attach_aws_node_termination_handler_policy = true aws_node_termination_handler_sqs_queue_arns = ["arn:aws:sqs:*:*:eks-node-termination-handler"] + associations = { + this = { + cluster_name = "example" + namespace = "aws-node-termination-handler" + service_account = "aws-node-termination-handler-sa" + } + } + tags = { Environment = "dev" } } ``` + ### [AWS Private CA Issuer](https://github.com/cert-manager/aws-privateca-issuer) ```hcl @@ -338,6 +474,38 @@ module "aws_privateca_issuer_pod_identity" { attach_aws_privateca_issuer_policy = true aws_privateca_issuer_acmca_arns = ["arn:aws:acm-pca:*:*:certificate-authority/foo"] + associations = { + this = { + cluster_name = "example" + namespace = "cert-manager" + service_account = "aws-privateca-issuer-sa" + } + } + + tags = { + Environment = "dev" + } +} +``` + +### [PGAnalyze](https://pganalyze.com/) + +```hcl +module "pganalyze_pod_identity" { + source = "terraform-aws-modules/eks-pod-identity/aws" + + name = "pganalyze" + + attach_pganalyze_pod_identity_policy = true + + associations = { + this = { + cluster_name = "example" + namespace = "default" + service_account = "pganalyze-service-account" + } + } + tags = { Environment = "dev" } @@ -356,6 +524,14 @@ module "velero_pod_identity" { velero_s3_bucket_arns = ["arn:aws:s3:::velero-backups"] velero_s3_bucket_path_arns = ["arn:aws:s3:::velero-backups/example/*"] + associations = { + this = { + cluster_name = "example" + namespace = "velero" + service_account = "velero-server" + } + } + tags = { Environment = "dev" } @@ -373,6 +549,14 @@ module "aws_vpc_cni_ipv4_pod_identity" { attach_aws_vpc_cni_policy = true aws_vpc_cni_enable_ipv4 = true + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "aws-node" + } + } + tags = { Environment = "dev" } @@ -390,6 +574,14 @@ module "aws_vpc_cni_ipv6_pod_identity" { attach_aws_vpc_cni_policy = true aws_vpc_cni_enable_ipv6 = true + associations = { + this = { + cluster_name = "example" + namespace = "kube-system" + service_account = "aws-node" + } + } + tags = { Environment = "dev" } @@ -442,6 +634,7 @@ No modules. | [aws_iam_policy.lb_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.pganalyze](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.vpc_cni](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | @@ -463,9 +656,11 @@ No modules. | [aws_iam_role_policy_attachment.lb_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.pganalyze](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.vpc_cni](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.amazon_managed_service_prometheus](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.appmesh_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.appmesh_envoy_proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -484,9 +679,11 @@ No modules. | [aws_iam_policy_document.lb_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.pganalyze](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.vpc_cni](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -518,6 +715,7 @@ No modules. | [attach\_external\_dns\_policy](#input\_attach\_external\_dns\_policy) | Determines whether to attach the External DNS IAM policy to the role | `bool` | `false` | no | | [attach\_external\_secrets\_policy](#input\_attach\_external\_secrets\_policy) | Determines whether to attach the External Secrets policy to the role | `bool` | `false` | no | | [attach\_mountpoint\_s3\_csi\_policy](#input\_attach\_mountpoint\_s3\_csi\_policy) | Determines whether to attach the Mountpoint S3 CSI IAM policy to the role | `bool` | `false` | no | +| [attach\_pganalyze\_policy](#input\_attach\_pganalyze\_policy) | Determines whether to attach the PGAnalyze IAM policy to the role | `bool` | `false` | no | | [attach\_velero\_policy](#input\_attach\_velero\_policy) | Determines whether to attach the Velero IAM policy to the role | `bool` | `false` | no | | [aws\_ebs\_csi\_kms\_arns](#input\_aws\_ebs\_csi\_kms\_arns) | KMS key ARNs to allow EBS CSI to manage encrypted volumes | `list(string)` | `[]` | no | | [aws\_ebs\_csi\_policy\_name](#input\_aws\_ebs\_csi\_policy\_name) | Custom name of the EBS CSI IAM policy | `string` | `null` | no | @@ -558,6 +756,7 @@ No modules. | [override\_policy\_documents](#input\_override\_policy\_documents) | List of IAM policy documents that are merged together into the exported document | `list(string)` | `[]` | no | | [path](#input\_path) | Path of IAM role | `string` | `"/"` | no | | [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | Permissions boundary ARN to use for IAM role | `string` | `null` | no | +| [pganalyze\_policy\_name](#input\_pganalyze\_policy\_name) | Custom name of the PGAnalyze IAM policy | `string` | `null` | no | | [policy\_name\_prefix](#input\_policy\_name\_prefix) | IAM policy name prefix | `string` | `"AmazonEKS_"` | no | | [policy\_statements](#input\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | diff --git a/examples/complete/README.md b/examples/complete/README.md index d4393e3..381174e 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -55,6 +55,7 @@ Note that this example may create resources which will incur monetary charges on | [external\_dns\_pod\_identity](#module\_external\_dns\_pod\_identity) | ../../ | n/a | | [external\_secrets\_pod\_identity](#module\_external\_secrets\_pod\_identity) | ../../ | n/a | | [mountpoint\_s3\_csi\_pod\_identity](#module\_mountpoint\_s3\_csi\_pod\_identity) | ../../ | n/a | +| [pganalyze\_pod\_identity](#module\_pganalyze\_pod\_identity) | ../../ | n/a | | [velero\_pod\_identity](#module\_velero\_pod\_identity) | ../../ | n/a | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 6eaff47..a125151 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -501,6 +501,31 @@ module "aws_privateca_issuer_pod_identity" { tags = local.tags } +module "pganalyze_pod_identity" { + source = "../../" + + name = "pganalyze" + + attach_pganalyze_policy = true + + # Pod Identity Associations + association_defaults = { + namespace = "default" + service_account = "pganalyze-service-account" + } + + associations = { + ex-one = { + cluster_name = module.eks_one.cluster_name + } + ex-two = { + cluster_name = module.eks_two.cluster_name + } + } + + tags = local.tags +} + module "velero_pod_identity" { source = "../../" diff --git a/main.tf b/main.tf index 06a3649..aeacdef 100644 --- a/main.tf +++ b/main.tf @@ -1,7 +1,21 @@ -data "aws_partition" "current" {} +data "aws_partition" "current" { + count = var.create ? 1 : 0 +} + +data "aws_caller_identity" "current" { + count = var.create ? 1 : 0 +} + +data "aws_region" "current" { + count = var.create ? 1 : 0 + + region = var.region +} locals { - partition = data.aws_partition.current.partition + partition = try(data.aws_partition.current[0].partition, null) + account_id = try(data.aws_caller_identity.current[0].account_id, null) + region = try(data.aws_region.current[0].name, null) } ################################################################################ diff --git a/pganalyze.tf b/pganalyze.tf new file mode 100644 index 0000000..d4c2667 --- /dev/null +++ b/pganalyze.tf @@ -0,0 +1,69 @@ +################################################################################ +# PGAnalyze Policy +################################################################################ + +# https://pganalyze.com/docs/install/amazon_rds/03_install_collector_eks#set-up-iam-policy + +data "aws_iam_policy_document" "pganalyze" { + count = var.create && var.attach_pganalyze_policy ? 1 : 0 + + source_policy_documents = [data.aws_iam_policy_document.base[0].json] + override_policy_documents = var.override_policy_documents + + statement { + sid = "CloudwatchGetMetrics" + actions = ["cloudwatch:GetMetricStatistics"] + resources = ["*"] + } + + statement { + sid = "CloudwatchLogEvents" + actions = ["logs:GetLogEvents"] + resources = ["arn:${local.partition}:logs:${local.region}:${local.account_id}:log-group:RDSOSMetrics:log-stream:*"] + } + + statement { + sid = "RDSDescribeParameters" + actions = ["rds:DescribeDBParameters"] + resources = ["arn:${local.partition}:rds:${local.region}:${local.account_id}:pg:*"] + } + + statement { + sid = "RDSInstanceDescribe" + actions = [ + "rds:DescribeDBInstances", + "rds:DownloadDBLogFilePortion", + "rds:DescribeDBLogFiles", + ] + resources = ["arn:${local.partition}:rds:${local.region}:${local.account_id}:db:*"] + } + + statement { + sid = "RDSClusterDescribe" + actions = ["rds:DescribeDBClusters"] + resources = ["arn:${local.partition}:rds:${local.region}:${local.account_id}:cluster:*"] + } +} + +locals { + pganalyze_policy_name = coalesce(var.pganalyze_policy_name, "${var.policy_name_prefix}PGAnalyze") +} + +resource "aws_iam_policy" "pganalyze" { + count = var.create && var.attach_pganalyze_policy ? 1 : 0 + + name = var.use_name_prefix ? null : local.pganalyze_policy_name + name_prefix = var.use_name_prefix ? "${local.pganalyze_policy_name}-" : null + path = var.path + description = "Permissions for PGAnalyze" + policy = data.aws_iam_policy_document.pganalyze[0].json + + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "pganalyze" { + count = var.create && var.attach_pganalyze_policy ? 1 : 0 + + role = aws_iam_role.this[0].name + policy_arn = aws_iam_policy.pganalyze[0].arn +} diff --git a/variables.tf b/variables.tf index b0944fc..f99573f 100644 --- a/variables.tf +++ b/variables.tf @@ -531,6 +531,20 @@ variable "mountpoint_s3_csi_bucket_path_arns" { default = [] } +# PGAnalyze + +variable "attach_pganalyze_policy" { + description = "Determines whether to attach the PGAnalyze IAM policy to the role" + type = bool + default = false +} + +variable "pganalyze_policy_name" { + description = "Custom name of the PGAnalyze IAM policy" + type = string + default = null +} + # Velero variable "attach_velero_policy" { description = "Determines whether to attach the Velero IAM policy to the role" diff --git a/wrappers/main.tf b/wrappers/main.tf index bde3e1b..12c2763 100644 --- a/wrappers/main.tf +++ b/wrappers/main.tf @@ -29,6 +29,7 @@ module "wrapper" { attach_external_dns_policy = try(each.value.attach_external_dns_policy, var.defaults.attach_external_dns_policy, false) attach_external_secrets_policy = try(each.value.attach_external_secrets_policy, var.defaults.attach_external_secrets_policy, false) attach_mountpoint_s3_csi_policy = try(each.value.attach_mountpoint_s3_csi_policy, var.defaults.attach_mountpoint_s3_csi_policy, false) + attach_pganalyze_policy = try(each.value.attach_pganalyze_policy, var.defaults.attach_pganalyze_policy, false) attach_velero_policy = try(each.value.attach_velero_policy, var.defaults.attach_velero_policy, false) aws_ebs_csi_kms_arns = try(each.value.aws_ebs_csi_kms_arns, var.defaults.aws_ebs_csi_kms_arns, []) aws_ebs_csi_policy_name = try(each.value.aws_ebs_csi_policy_name, var.defaults.aws_ebs_csi_policy_name, null) @@ -69,6 +70,7 @@ module "wrapper" { override_policy_documents = try(each.value.override_policy_documents, var.defaults.override_policy_documents, []) path = try(each.value.path, var.defaults.path, "/") permissions_boundary_arn = try(each.value.permissions_boundary_arn, var.defaults.permissions_boundary_arn, null) + pganalyze_policy_name = try(each.value.pganalyze_policy_name, var.defaults.pganalyze_policy_name, null) policy_name_prefix = try(each.value.policy_name_prefix, var.defaults.policy_name_prefix, "AmazonEKS_") policy_statements = try(each.value.policy_statements, var.defaults.policy_statements, null) region = try(each.value.region, var.defaults.region, null)