diff --git a/modules/iam/README.md b/modules/iam/README.md index 48de31e..d931678 100644 --- a/modules/iam/README.md +++ b/modules/iam/README.md @@ -29,7 +29,8 @@ A basic module used to create IAM Roles, Policies for StreamNative Cloud Applica | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.64.2 | +| [aws.source](#provider\_aws.source) | 5.99.1 | +| [aws.target](#provider\_aws.target) | 5.99.1 | ## Modules @@ -45,7 +46,9 @@ No modules. | [aws_iam_role.csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.external_dns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.karpenter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.loki](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.irsa_s3_rw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.karpenter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy_attachment.aws_load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.cert_manager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -54,6 +57,7 @@ No modules. | [aws_iam_role_policy_attachment.csi_managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.external_dns](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_s3_bucket_policy.loki_bucket_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.aws_load_balancer_controller_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cert_manager_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -62,6 +66,7 @@ No modules. | [aws_iam_policy_document.external_dns_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.karpenter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.karpenter_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.loki_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.velero_sts](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 | @@ -69,19 +74,18 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [backup\_bucket](#input\_backup\_bucket) | The name of the s3 bucket to use for backups | `string` | n/a | yes | | [cluster\_name](#input\_cluster\_name) | The name of the cluster | `string` | n/a | yes | | [cluster\_node\_group\_iam\_role\_arn](#input\_cluster\_node\_group\_iam\_role\_arn) | n/a | `string` | n/a | yes | | [enable\_karpenter](#input\_enable\_karpenter) | Enable karpenter for autoscaling. If set to false, no karpenter resources will be created. | `bool` | `false` | no | +| [enable\_loki](#input\_enable\_loki) | Enable loki for logging. If set to false, no loki resources will be created. | `bool` | `true` | no | | [enable\_velero](#input\_enable\_velero) | Enable velero for backups. If set to false, no velero resources will be created. | `bool` | `true` | no | | [extra\_aws\_tags](#input\_extra\_aws\_tags) | extra aws tags to add to any resources | `map(string)` | `{}` | no | | [load\_balancer\_policy\_arn\_override](#input\_load\_balancer\_policy\_arn\_override) | Override the runtime policy arn, otherwise will construct an arn | `string` | `""` | no | +| [loki\_bucket](#input\_loki\_bucket) | The name of the AWS S3 bucket to use for Loki | `string` | n/a | yes | | [oidc\_issuer](#input\_oidc\_issuer) | The oidc issuer for the cluster | `string` | n/a | yes | | [permissions\_boundary\_arn\_override](#input\_permissions\_boundary\_arn\_override) | Override the permission boundary arn, otherwise will construct an arn | `string` | `""` | no | | [region](#input\_region) | AWS Region | `string` | n/a | yes | | [runtime\_policy\_arn\_override](#input\_runtime\_policy\_arn\_override) | Override the runtime policy arn, otherwise will construct an arn | `string` | `""` | no | -| [s3\_encryption\_kms\_key\_arn](#input\_s3\_encryption\_kms\_key\_arn) | KMS key ARN to use for S3 encryption. If not set, the default AWS S3 key will be used. | `string` | `""` | no | -| [velero\_backup\_schedule](#input\_velero\_backup\_schedule) | The scheduled time for Velero to perform backups. Written in cron expression, defaults to "0 5 * * *" or "at 5:00am every day" | `string` | `"0 5 * * *"` | no | ## Outputs @@ -93,5 +97,6 @@ No modules. | [csi\_arn](#output\_csi\_arn) | n/a | | [external\_dns\_arn](#output\_external\_dns\_arn) | n/a | | [karpenter\_arn](#output\_karpenter\_arn) | n/a | +| [loki\_arn](#output\_loki\_arn) | n/a | | [velero\_arn](#output\_velero\_arn) | n/a | \ No newline at end of file diff --git a/modules/iam/aws_load_balancer_controller.tf b/modules/iam/aws_load_balancer_controller.tf index 95b9f8b..0f362a2 100644 --- a/modules/iam/aws_load_balancer_controller.tf +++ b/modules/iam/aws_load_balancer_controller.tf @@ -1,4 +1,6 @@ data "aws_iam_policy_document" "aws_load_balancer_controller_sts" { + provider = aws.target + statement { actions = [ "sts:AssumeRoleWithWebIdentity" @@ -17,6 +19,8 @@ data "aws_iam_policy_document" "aws_load_balancer_controller_sts" { } resource "aws_iam_role" "aws_load_balancer_controller" { + provider = aws.target + name = format("%s-lbc-role", var.cluster_name) description = format("Role used by IRSA and the KSA aws-load-balancer-controller on StreamNative Cloud EKS cluster %s", var.cluster_name) assume_role_policy = data.aws_iam_policy_document.aws_load_balancer_controller_sts.json @@ -26,6 +30,8 @@ resource "aws_iam_role" "aws_load_balancer_controller" { } resource "aws_iam_role_policy_attachment" "aws_load_balancer_controller" { + provider = aws.target + role = aws_iam_role.aws_load_balancer_controller.name policy_arn = local.default_lb_policy_arn } diff --git a/modules/iam/cert_manager.tf b/modules/iam/cert_manager.tf index 28584c0..2a5dd93 100644 --- a/modules/iam/cert_manager.tf +++ b/modules/iam/cert_manager.tf @@ -1,4 +1,6 @@ data "aws_iam_policy_document" "cert_manager_sts" { + provider = aws.target + statement { actions = [ "sts:AssumeRoleWithWebIdentity" @@ -17,6 +19,8 @@ data "aws_iam_policy_document" "cert_manager_sts" { } resource "aws_iam_role" "cert_manager" { + provider = aws.target + name = format("%s-cm-role", var.cluster_name) description = format("Role assumed by IRSA and the KSA cert-manager on StreamNative Cloud EKS cluster %s", var.cluster_name) assume_role_policy = data.aws_iam_policy_document.cert_manager_sts.json @@ -26,6 +30,8 @@ resource "aws_iam_role" "cert_manager" { } resource "aws_iam_role_policy_attachment" "cert_manager" { + provider = aws.target + role = aws_iam_role.cert_manager.name policy_arn = local.default_service_policy_arn -} \ No newline at end of file +} diff --git a/modules/iam/cluster_autoscaler.tf b/modules/iam/cluster_autoscaler.tf index 61fb301..24db629 100644 --- a/modules/iam/cluster_autoscaler.tf +++ b/modules/iam/cluster_autoscaler.tf @@ -1,5 +1,6 @@ data "aws_iam_policy_document" "cluster_autoscaler_sts" { - count = var.enable_karpenter ? 0 : 1 + count = var.enable_karpenter ? 0 : 1 + provider = aws.target statement { actions = [ @@ -24,7 +25,8 @@ data "aws_iam_policy_document" "cluster_autoscaler_sts" { } resource "aws_iam_role" "cluster_autoscaler" { - count = var.enable_karpenter ? 0 : 1 + count = var.enable_karpenter ? 0 : 1 + provider = aws.target name = format("%s-ca-role", var.cluster_name) description = format("Role used by IRSA and the KSA cluster-autoscaler on StreamNative Cloud EKS cluster %s", var.cluster_name) @@ -35,7 +37,8 @@ resource "aws_iam_role" "cluster_autoscaler" { } resource "aws_iam_role_policy_attachment" "cluster_autoscaler" { - count = var.enable_karpenter ? 0 : 1 + count = var.enable_karpenter ? 0 : 1 + provider = aws.target policy_arn = local.default_service_policy_arn role = aws_iam_role.cluster_autoscaler.0.name diff --git a/modules/iam/csi.tf b/modules/iam/csi.tf index 962db39..df8535d 100644 --- a/modules/iam/csi.tf +++ b/modules/iam/csi.tf @@ -1,4 +1,6 @@ data "aws_iam_policy_document" "csi_sts" { + provider = aws.target + statement { actions = [ "sts:AssumeRoleWithWebIdentity" @@ -22,6 +24,8 @@ data "aws_iam_policy_document" "csi_sts" { } resource "aws_iam_role" "csi" { + provider = aws.target + name = format("%s-csi-role", var.cluster_name) description = format("Role used by IRSA and the KSA ebs-csi-controller-sa on StreamNative Cloud EKS cluster %s", var.cluster_name) assume_role_policy = data.aws_iam_policy_document.csi_sts.json @@ -31,11 +35,15 @@ resource "aws_iam_role" "csi" { } resource "aws_iam_role_policy_attachment" "csi" { + provider = aws.target + role = aws_iam_role.csi.name policy_arn = local.default_service_policy_arn } resource "aws_iam_role_policy_attachment" "csi_managed" { + provider = aws.target + role = aws_iam_role.csi.name policy_arn = "arn:${local.aws_partition}:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" } diff --git a/modules/iam/external_dns.tf b/modules/iam/external_dns.tf index 12c0cfd..f4d0f22 100644 --- a/modules/iam/external_dns.tf +++ b/modules/iam/external_dns.tf @@ -1,4 +1,6 @@ data "aws_iam_policy_document" "external_dns_sts" { + provider = aws.target + statement { actions = [ "sts:AssumeRoleWithWebIdentity" @@ -17,6 +19,8 @@ data "aws_iam_policy_document" "external_dns_sts" { } resource "aws_iam_role" "external_dns" { + provider = aws.target + name = format("%s-extdns-role", var.cluster_name) description = format("Role used by IRSA and the KSA external-dns on StreamNative Cloud EKS cluster %s", var.cluster_name) assume_role_policy = data.aws_iam_policy_document.external_dns_sts.json @@ -26,6 +30,8 @@ resource "aws_iam_role" "external_dns" { } resource "aws_iam_role_policy_attachment" "external_dns" { + provider = aws.target + role = aws_iam_role.external_dns.name policy_arn = local.default_service_policy_arn } diff --git a/modules/iam/karpenter.tf b/modules/iam/karpenter.tf index a12acc2..10e9844 100644 --- a/modules/iam/karpenter.tf +++ b/modules/iam/karpenter.tf @@ -1,5 +1,6 @@ data "aws_iam_policy_document" "karpenter_sts" { - count = var.enable_karpenter ? 1 : 0 + count = var.enable_karpenter ? 1 : 0 + provider = aws.target statement { effect = "Allow" @@ -27,7 +28,8 @@ data "aws_iam_policy_document" "karpenter_sts" { } resource "aws_iam_role" "karpenter" { - count = var.enable_karpenter ? 1 : 0 + count = var.enable_karpenter ? 1 : 0 + provider = aws.target name = format("%s-karpenter", var.cluster_name) path = "/StreamNative/" @@ -39,7 +41,8 @@ resource "aws_iam_role" "karpenter" { } data "aws_iam_policy_document" "karpenter" { - count = var.enable_karpenter ? 1 : 0 + count = var.enable_karpenter ? 1 : 0 + provider = aws.target statement { sid = "AllowScopedEC2InstanceAccessActions" @@ -391,7 +394,8 @@ data "aws_iam_policy_document" "karpenter" { } resource "aws_iam_role_policy" "karpenter" { - count = var.enable_karpenter ? 1 : 0 + count = var.enable_karpenter ? 1 : 0 + provider = aws.target name_prefix = "KarpenterController" role = aws_iam_role.karpenter[0].name diff --git a/modules/iam/locals.tf b/modules/iam/locals.tf index 21188d5..fcf8cee 100644 --- a/modules/iam/locals.tf +++ b/modules/iam/locals.tf @@ -1,6 +1,10 @@ -data "aws_caller_identity" "current" {} +data "aws_caller_identity" "current" { + provider = aws.target +} -data "aws_partition" "current" {} +data "aws_partition" "current" { + provider = aws.target +} locals { account_id = data.aws_caller_identity.current.account_id diff --git a/modules/iam/loki.tf b/modules/iam/loki.tf new file mode 100644 index 0000000..621183c --- /dev/null +++ b/modules/iam/loki.tf @@ -0,0 +1,90 @@ +data "aws_iam_policy_document" "loki_sts" { + count = var.enable_loki ? 1 : 0 + provider = aws.target + + statement { + actions = [ + "sts:AssumeRoleWithWebIdentity" + ] + effect = "Allow" + principals { + type = "Federated" + identifiers = [format("arn:%s:iam::%s:oidc-provider/%s", local.aws_partition, local.account_id, local.oidc_issuer)] + } + condition { + test = "StringLike" + values = [format("system:serviceaccount:%s:%s", "sn-system", "loki")] + variable = format("%s:sub", local.oidc_issuer) + } + } +} + +resource "aws_iam_role" "loki" { + count = var.enable_loki ? 1 : 0 + provider = aws.target + + name = format("%s-loki-s3-role", var.cluster_name) + description = format("Role used by IRSA for Loki on StreamNative Cloud EKS cluster %s", var.cluster_name) + tags = local.tags + path = "/StreamNative/" + permissions_boundary = local.permissions_boundary_arn + assume_role_policy = data.aws_iam_policy_document.loki_sts[0].json +} + +resource "aws_iam_role_policy" "irsa_s3_rw" { + count = var.enable_loki ? 1 : 0 + provider = aws.target + + name = "AllowS3ReadWriteAccess" + role = aws_iam_role.loki[0].id + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "AllowS3ReadWriteAccess", + Effect = "Allow", + Action = [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucket" + ], + Resource = [ + "arn:aws:s3:::${var.loki_bucket}", + "arn:aws:s3:::${var.loki_bucket}/*" + ] + } + ] + }) +} + +resource "aws_s3_bucket_policy" "loki_bucket_admin" { + count = var.enable_loki ? 1 : 0 + provider = aws.source + + bucket = var.loki_bucket + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "AllowCrossAccountIRSAAccessS3", + Effect = "Allow", + Principal = { + AWS = aws_iam_role.loki[0].arn + }, + Action = [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucket" + ], + Resource = [ + "arn:aws:s3:::${var.loki_bucket}", + "arn:aws:s3:::${var.loki_bucket}/*" + ] + } + ] + }) +} diff --git a/modules/iam/outputs.tf b/modules/iam/outputs.tf index 61a0ed6..6719918 100644 --- a/modules/iam/outputs.tf +++ b/modules/iam/outputs.tf @@ -24,4 +24,8 @@ output "karpenter_arn" { output "velero_arn" { value = try(aws_iam_role.velero[0].arn, null) -} \ No newline at end of file +} + +output "loki_arn" { + value = try(aws_iam_role.loki[0].arn, null) +} diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index ac54491..3ebc956 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -51,4 +51,15 @@ variable "extra_aws_tags" { default = {} description = "extra aws tags to add to any resources" type = map(string) +} + +variable "enable_loki" { + type = bool + default = true + description = "Enable loki for logging. If set to false, no loki resources will be created." +} + +variable "loki_bucket" { + description = "The name of the AWS S3 bucket to use for Loki" + type = string } \ No newline at end of file diff --git a/modules/iam/velero.tf b/modules/iam/velero.tf index a5f9fed..21c7786 100644 --- a/modules/iam/velero.tf +++ b/modules/iam/velero.tf @@ -1,5 +1,6 @@ data "aws_iam_policy_document" "velero_sts" { - count = var.enable_velero ? 1 : 0 + count = var.enable_velero ? 1 : 0 + provider = aws.target statement { actions = [ @@ -19,7 +20,8 @@ data "aws_iam_policy_document" "velero_sts" { } resource "aws_iam_role" "velero" { - count = var.enable_velero ? 1 : 0 + count = var.enable_velero ? 1 : 0 + provider = aws.target name = format("%s-velero-backup-role", var.cluster_name) description = format("Role used by IRSA and the KSA velero on StreamNative Cloud EKS cluster %s", var.cluster_name) @@ -30,7 +32,8 @@ resource "aws_iam_role" "velero" { } resource "aws_iam_role_policy_attachment" "velero" { - count = var.enable_velero ? 1 : 0 + count = var.enable_velero ? 1 : 0 + provider = aws.target role = aws_iam_role.velero.0.name policy_arn = local.default_service_policy_arn diff --git a/modules/iam/versions.tf b/modules/iam/versions.tf index 01a4315..b087b97 100644 --- a/modules/iam/versions.tf +++ b/modules/iam/versions.tf @@ -17,9 +17,17 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" - version = ">= 3.64.2" + source = "hashicorp/aws" + version = ">= 3.64.2" + configuration_aliases = [aws.source, aws.target] } } } +provider "aws" { + alias = "source" +} + +provider "aws" { + alias = "target" +}