From 096b190c695c0ab260632e54acdd954990e5d68b Mon Sep 17 00:00:00 2001 From: Abderrahmane DKOUR Date: Thu, 12 Dec 2024 17:43:09 +0100 Subject: [PATCH] Added AWS service account and SQS module to ArmoniK.Infra --- service-account/aws/main.tf | 51 ++++++++++++++++++++++++++++++++ service-account/aws/outputs.tf | 4 +++ service-account/aws/variables.tf | 43 +++++++++++++++++++++++++++ service-account/aws/versions.tf | 13 ++++++++ storage/aws/s3/README.md | 4 +++ storage/aws/s3/main.tf | 51 ++++++++++++++++++++++++++++++++ storage/aws/s3/variables.tf | 6 ++++ storage/aws/sqs/main.tf | 36 ++++++++++++++++++++++ storage/aws/sqs/outputs.tf | 9 ++++++ storage/aws/sqs/variables.tf | 20 +++++++++++++ storage/aws/sqs/versions.tf | 9 ++++++ 11 files changed, 246 insertions(+) create mode 100644 service-account/aws/main.tf create mode 100644 service-account/aws/outputs.tf create mode 100644 service-account/aws/variables.tf create mode 100644 service-account/aws/versions.tf create mode 100644 storage/aws/sqs/main.tf create mode 100644 storage/aws/sqs/outputs.tf create mode 100644 storage/aws/sqs/variables.tf create mode 100644 storage/aws/sqs/versions.tf diff --git a/service-account/aws/main.tf b/service-account/aws/main.tf new file mode 100644 index 000000000..3ae420cd9 --- /dev/null +++ b/service-account/aws/main.tf @@ -0,0 +1,51 @@ + + +locals { + prefix = var.prefix + tags = merge(var.tags, { module = "aws-service-account" }) + oidc_arn = var.oidc_provider_arn + oidc_url = trimprefix(var.oidc_issuer_url, "https://") +} + +resource "aws_iam_role" "armonik" { + name = "${local.prefix}-eks-pod-identity-armonik" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Federated = local.oidc_arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${local.oidc_url}:aud" = "sts.amazonaws.com" + "${local.oidc_url}:sub" = [ + "system:serviceaccount:${var.namespace}:${var.service_account_name}", + ] + } + } + } + ] + }) + tags = local.tags +} + +resource "aws_iam_policy_attachment" "armonik_decrypt_object" { + name = "${local.prefix}-s3-encrypt-decrypt-armonik" + roles = [aws_iam_role.armonik.name] + policy_arn = var.decrypt_policy_arn +} + +resource "kubernetes_service_account" "armonik" { + metadata { + name = var.service_account_name + namespace = var.namespace + + annotations = { + "eks.amazonaws.com/role-arn" = aws_iam_role.armonik.arn + } + } + automount_service_account_token = var.automount_service_account_token +} diff --git a/service-account/aws/outputs.tf b/service-account/aws/outputs.tf new file mode 100644 index 000000000..5c1caa6a4 --- /dev/null +++ b/service-account/aws/outputs.tf @@ -0,0 +1,4 @@ +output "service_account_iam_role_name" { + description = "name of the IAM role associated to the created Kubernetes service account" + value = aws_iam_role.armonik.name +} diff --git a/service-account/aws/variables.tf b/service-account/aws/variables.tf new file mode 100644 index 000000000..a6ec4542e --- /dev/null +++ b/service-account/aws/variables.tf @@ -0,0 +1,43 @@ +variable "prefix" { + description = "Prefix to use for service account related resources" + type = string +} + +# Tags +variable "tags" { + description = "Tags for resource" + type = map(string) + default = {} +} + +variable "namespace" { + description = "Namespace of ArmoniK service account related resources" + type = string + default = "armonik" +} + +variable "service_account_name" { + description = "Name of the service account to create" + type = string +} + +variable "automount_service_account_token" { + description = "To enable automatic mounting of the Kubernetes service account token." + type = bool + default = true +} + +variable "oidc_provider_arn" { + description = "ARN of the OIDC provider" + type = string +} + +variable "decrypt_policy_arn" { + description = "ARN of the S3 encrypt/decrypt IAM policy" + type = string +} + +variable "oidc_issuer_url" { + description = "URL of the OIDC issuer" + type = string +} diff --git a/service-account/aws/versions.tf b/service-account/aws/versions.tf new file mode 100644 index 000000000..2082d6d72 --- /dev/null +++ b/service-account/aws/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.61" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.7.1" + } + } +} diff --git a/storage/aws/s3/README.md b/storage/aws/s3/README.md index e3e6b1829..ed741d173 100644 --- a/storage/aws/s3/README.md +++ b/storage/aws/s3/README.md @@ -29,6 +29,8 @@ No modules. | Name | Type | |------|------| +| [aws_iam_policy.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy_attachment.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_s3_bucket.s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_acl.acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | | [aws_s3_bucket_ownership_controls.ownership](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | @@ -39,6 +41,7 @@ No modules. | [aws_iam_policy_document.combined](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.deny_insecure_transport](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.require_latest_tls](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs @@ -57,6 +60,7 @@ No modules. | [ownership](#input\_ownership) | Object ownership | `string` | `"BucketOwnerPreferred"` | no | | [policy](#input\_policy) | Text of the policy | `string` | `null` | no | | [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Whether Amazon S3 should restrict public bucket policies for this bucket | `bool` | `true` | no | +| [service\_account\_role\_name](#input\_service\_account\_role\_name) | Name of the IAM role to give the SQS permissions to | `optional(string)` | n/a | yes | | [sse\_algorithm](#input\_sse\_algorithm) | SSE algorithm to encrypt S3 object data | `string` | `"aws:kms"` | no | | [tags](#input\_tags) | Tags for resource | `any` | `{}` | no | | [versioning](#input\_versioning) | Enable or disable versioning | `string` | `"Disabled"` | no | diff --git a/storage/aws/s3/main.tf b/storage/aws/s3/main.tf index eabf92d97..5ab3db8b3 100644 --- a/storage/aws/s3/main.tf +++ b/storage/aws/s3/main.tf @@ -121,3 +121,54 @@ resource "aws_s3_bucket_public_access_block" "s3_bucket" { ignore_public_acls = var.ignore_public_acls restrict_public_buckets = var.restrict_public_buckets } + +data "aws_iam_policy_document" "s3" { + + statement { + sid = "AllowBucketAdminActions" + actions = [ + "s3:ListBucket", + "s3:ListBucketMultipartUploads", + ] + effect = "Allow" + resources = [aws_s3_bucket.s3_bucket.arn] + } + + statement { + sid = "AllowObjectAdminActions" + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:DeleteObject", + "s3:PutObjectAcl", + "s3:GetObjectAcl", + ] + effect = "Allow" + resources = ["${aws_s3_bucket.s3_bucket.arn}/*"] + } + + statement { + sid = "AllowBucketLifecycleActions" + actions = [ + "s3:PutLifecycleConfiguration", + "s3:GetLifecycleConfiguration", + ] + effect = "Allow" + resources = [aws_s3_bucket.s3_bucket.arn] + } +} + +resource "aws_iam_policy" "s3" { + count = can(coalesce(var.service_account_role_name)) ? 1 : 0 + name_prefix = "${var.name}-s3-admin" + description = "Policy for allowing S3 admin access" + policy = data.aws_iam_policy_document.s3.json + tags = local.tags +} + +resource "aws_iam_policy_attachment" "s3" { + count = can(coalesce(var.service_account_role_name)) ? 1 : 0 + name = "${var.name}-s3" + roles = [var.service_account_role_name] + policy_arn = aws_iam_policy.s3[0].arn +} diff --git a/storage/aws/s3/variables.tf b/storage/aws/s3/variables.tf index b45945061..33809e69b 100644 --- a/storage/aws/s3/variables.tf +++ b/storage/aws/s3/variables.tf @@ -103,3 +103,9 @@ variable "object_storage_adapter" { type = string default = "ArmoniK.Adapters.S3.ObjectStorage" } + +variable "service_account_role_name" { + description = "Name of the IAM role to give the SQS permissions to" + type = string + default = "" +} diff --git a/storage/aws/sqs/main.tf b/storage/aws/sqs/main.tf new file mode 100644 index 000000000..10dc7f41e --- /dev/null +++ b/storage/aws/sqs/main.tf @@ -0,0 +1,36 @@ +locals { + prefix = var.prefix + region = var.region + tags = merge(var.tags, { module = "amazon-sqs" }) +} + + +data "aws_iam_policy_document" "sqs" { + statement { + sid = "SqsAdmin" + actions = [ + "sqs:CreateQueue", + "sqs:DeleteQueue", + "sqs:PurgeQueue", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage", + "sqs:SendMessage", + "sqs:ChangeMessageVisibility" + ] + effect = "Allow" + resources = ["*"] + } +} + +resource "aws_iam_policy" "sqs" { + name_prefix = "${local.prefix}-sqs-admin" + description = "Policy for allowing SQS admin access" + policy = data.aws_iam_policy_document.sqs.json + tags = local.tags +} + +resource "aws_iam_policy_attachment" "sqs" { + name = "${local.prefix}-sqs" + roles = [var.service_account_role_name] + policy_arn = aws_iam_policy.sqs.arn +} diff --git a/storage/aws/sqs/outputs.tf b/storage/aws/sqs/outputs.tf new file mode 100644 index 000000000..d1e9489e4 --- /dev/null +++ b/storage/aws/sqs/outputs.tf @@ -0,0 +1,9 @@ +output "env" { + description = "Environment variables to pass to ArmoniK.Core" + value = { + "Components__QueueAdaptorSettings__ClassName" = "ArmoniK.Core.Adapters.SQS.QueueBuilder" + "Components__QueueAdaptorSettings__AdapterAbsolutePath" = "/adapters/queue/sqs/ArmoniK.Core.Adapters.SQS.dll" + "SQS__ServiceURL" = "https://sqs.${local.region}.amazonaws.com" + "SQS__Prefix" = local.prefix + } +} diff --git a/storage/aws/sqs/variables.tf b/storage/aws/sqs/variables.tf new file mode 100644 index 000000000..fff3f4188 --- /dev/null +++ b/storage/aws/sqs/variables.tf @@ -0,0 +1,20 @@ +variable "region" { + description = "Region" + type = string +} + +variable "prefix" { + description = "Prefix to use for SQS queues" + type = string +} + +variable "tags" { + description = "Tags for resource" + type = map(string) + default = {} +} + +variable "service_account_role_name" { + description = "Name of the IAM role to give the SQS permissions to" + type = string +} diff --git a/storage/aws/sqs/versions.tf b/storage/aws/sqs/versions.tf new file mode 100644 index 000000000..5cb7783be --- /dev/null +++ b/storage/aws/sqs/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.61" + } + } +}