diff --git a/modules/mpc-party/variables.tf b/modules/mpc-party/variables.tf index 89cb3fa..339cd1f 100644 --- a/modules/mpc-party/variables.tf +++ b/modules/mpc-party/variables.tf @@ -353,22 +353,12 @@ variable "kms_cross_account_kms_key_id" { type = string description = "KMS key ID of KMS key created in a different AWS account" default = "" - - validation { - condition = !var.kms_use_cross_account_kms_key || (var.kms_use_cross_account_kms_key && var.kms_cross_account_kms_key_id != "") - error_message = "kms_cross_account_kms_key_id must be provided when kms_use_cross_account_kms_key is true." - } } variable "kms_cross_account_connector_txsender_key_id" { type = string description = "KMS key ID of Connector TxSender KMS key created in a different AWS account" default = "" - - validation { - condition = !var.kms_use_cross_account_kms_key || (var.kms_use_cross_account_kms_key && var.kms_cross_account_connector_txsender_key_id != "") - error_message = "kms_cross_account_connector_txsender_key_id must be provided when kms_use_cross_account_kms_key is true." - } } variable "kms_key_usage" { diff --git a/modules/zama-protocol-pauser-wallet/README.md b/modules/zama-protocol-pauser-wallet/README.md new file mode 100644 index 0000000..1112b71 --- /dev/null +++ b/modules/zama-protocol-pauser-wallet/README.md @@ -0,0 +1,63 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 6.0 | +| [kubernetes](#requirement\_kubernetes) | >= 2.23 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 6.0 | +| [kubernetes](#provider\_kubernetes) | >= 2.23 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [iam\_assumable\_role\_tx\_sender](#module\_iam\_assumable\_role\_tx\_sender) | terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc | 5.48.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.app_kms_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_kms_alias.tx_sender](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_external_key.tx_sender](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_external_key) | resource | +| [kubernetes_config_map.mpc_party_config](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | +| [kubernetes_namespace.zama_protocol_namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_service_account.tx_sender_irsa](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_eks_cluster.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster) | data source | +| [aws_iam_policy_document.tx_sender_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [app\_name](#input\_app\_name) | Name of the role | `string` | `"zama-protocol-pause"` | no | +| [cluster\_name](#input\_cluster\_name) | Name of the cluster | `string` | `null` | no | +| [k8s\_config\_map\_create](#input\_k8s\_config\_map\_create) | Whether to create the configmap for that holds AWS\_KMS\_KEY\_ID | `bool` | `true` | no | +| [k8s\_config\_map\_name](#input\_k8s\_config\_map\_name) | Name of the configmap | `string` | `"zama-protocol-pause"` | no | +| [k8s\_create\_namespace](#input\_k8s\_create\_namespace) | Whether to create the namespace if it doesn't exist | `bool` | `false` | no | +| [k8s\_namespace](#input\_k8s\_namespace) | Namespace of the application | `string` | `"zama-protocol"` | no | +| [k8s\_service\_account\_create](#input\_k8s\_service\_account\_create) | Whether to create the service account for the KMS key | `bool` | `true` | no | +| [k8s\_service\_account\_name](#input\_k8s\_service\_account\_name) | Name of the service account | `string` | `"zama-protocol-pause"` | no | +| [kms\_cross\_account\_iam\_role\_arn](#input\_kms\_cross\_account\_iam\_role\_arn) | ARN of cross-account IAM role allowed for usage of KMS key | `string` | `null` | no | +| [kms\_cross\_account\_kms\_key\_id](#input\_kms\_cross\_account\_kms\_key\_id) | KMS key ID of KMS key created in a different AWS account | `string` | `""` | no | +| [kms\_deletion\_window\_in\_days](#input\_kms\_deletion\_window\_in\_days) | Deletion window in days for KMS key | `number` | `30` | no | +| [kms\_key\_spec](#input\_kms\_key\_spec) | Specification for the txsender (e.g., ECC\_SECG\_P256K1 for Ethereum key signing) | `string` | `"ECC_SECG_P256K1"` | no | +| [kms\_key\_usage](#input\_kms\_key\_usage) | Key usage for txsender | `string` | `"SIGN_VERIFY"` | no | +| [kms\_use\_cross\_account\_kms\_key](#input\_kms\_use\_cross\_account\_kms\_key) | Whether a KMS key has been created in a different AWS account | `bool` | `false` | no | +| [tags](#input\_tags) | The tags for the KMS keys | `map(string)` | n/a | yes | +| [zama\_protocol\_pauser\_iam\_assumable\_role\_enabled](#input\_zama\_protocol\_pauser\_iam\_assumable\_role\_enabled) | Whether to enable the IAM assumable role for the application | `bool` | `false` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [aws\_kms\_key\_id](#output\_aws\_kms\_key\_id) | Summary of the KMS Key for the application | + diff --git a/modules/zama-protocol-pauser-wallet/main.tf b/modules/zama-protocol-pauser-wallet/main.tf new file mode 100644 index 0000000..7558ec0 --- /dev/null +++ b/modules/zama-protocol-pauser-wallet/main.tf @@ -0,0 +1,155 @@ +# ************ +# Data Sources +# ************ +data "aws_caller_identity" "current" {} + +data "aws_eks_cluster" "cluster" { + name = var.cluster_name +} + +# Create Kubernetes namespace (optional) +resource "kubernetes_namespace" "zama_protocol_namespace" { + count = var.k8s_create_namespace ? 1 : 0 + + metadata { + name = var.k8s_namespace + } +} + +# ************ +# Application Ethereum Key +# ************ +data "aws_iam_policy_document" "tx_sender_policy" { + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + actions = [ + "kms:Create*", + "kms:Describe*", + "kms:Enable*", + "kms:List*", + "kms:Put*", + "kms:Update*", + "kms:Revoke*", + "kms:Disable*", + "kms:Get*", + "kms:Delete*", + "kms:TagResource", + "kms:UntagResource", + "kms:ScheduleKeyDeletion", + "kms:CancelKeyDeletion", + "kms:ImportKeyMaterial", + "kms:DeleteImportedKeyMaterial" + ] + resources = ["*"] + } + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = [var.kms_cross_account_iam_role_arn != null ? var.kms_cross_account_iam_role_arn : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + actions = ["kms:DescribeKey", "kms:GetPublicKey", "kms:Sign", "kms:Verify"] + resources = ["*"] + } +} + +# ************ +# AWS External KMS Key for Ethereum TxSender +# ************ + +resource "aws_kms_external_key" "tx_sender" { + count = var.kms_use_cross_account_kms_key ? 0 : 1 + description = "Application ${var.app_name} tx sender key for ${var.cluster_name}" + key_usage = var.kms_key_usage + key_spec = var.kms_key_spec + deletion_window_in_days = var.kms_deletion_window_in_days + tags = var.tags + policy = data.aws_iam_policy_document.tx_sender_policy.json +} + +# ************ +# KMS Key Alias for Application Ethereum TxSender Key +# ************ +resource "aws_kms_alias" "tx_sender" { + count = var.kms_use_cross_account_kms_key ? 0 : 1 + + name = "alias/${var.app_name}-${var.cluster_name}" + target_key_id = aws_kms_external_key.tx_sender[0].id +} + +resource "aws_iam_policy" "app_kms_policy" { + count = var.kms_use_cross_account_kms_key ? 0 : 1 + + name = "${var.app_name}-${var.cluster_name}" + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AllowPauserJobToUseKeyForEthereumTxSender" + Effect = "Allow", + Action = [ + "kms:DescribeKey", + "kms:GetPublicKey", + "kms:Sign", + "kms:Verify" + ], + Resource = aws_kms_external_key.tx_sender[0].arn + }, + ] + }) +} + +module "iam_assumable_role_tx_sender" { + count = var.zama_protocol_pauser_iam_assumable_role_enabled ? 1 : 0 + source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc" + version = "5.48.0" + provider_url = data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer + create_role = true + role_name = "${var.app_name}-${var.cluster_name}" + oidc_fully_qualified_subjects = ["system:serviceaccount:${var.k8s_namespace}:${var.k8s_service_account_name}"] + role_policy_arns = [aws_iam_policy.app_kms_policy[0].arn] +} + +resource "kubernetes_service_account" "tx_sender_irsa" { + count = var.zama_protocol_pauser_iam_assumable_role_enabled && var.k8s_service_account_create ? 1 : 0 + metadata { + name = var.k8s_service_account_name + namespace = var.k8s_namespace + annotations = { + "eks.amazonaws.com/role-arn" = module.iam_assumable_role_tx_sender[0].iam_role_arn + } + } +} + +locals { + kms_key_id = var.kms_use_cross_account_kms_key ? var.kms_cross_account_kms_key_id : aws_kms_external_key.tx_sender[0].id +} + +resource "kubernetes_config_map" "mpc_party_config" { + count = var.k8s_config_map_create ? 1 : 0 + + metadata { + name = var.k8s_config_map_name + namespace = var.k8s_namespace + + labels = { + "app.kubernetes.io/name" = var.app_name + "app.kubernetes.io/component" = "config" + "app.kubernetes.io/managed-by" = "terraform" + } + + annotations = { + "terraform.io/module" = "zama-protocol-pauser-wallet" + } + } + + data = { + "AWS_KMS_KEY_ID" = local.kms_key_id + } + + depends_on = [kubernetes_namespace.zama_protocol_namespace] +} diff --git a/modules/zama-protocol-pauser-wallet/outputs.tf b/modules/zama-protocol-pauser-wallet/outputs.tf new file mode 100644 index 0000000..f9a6347 --- /dev/null +++ b/modules/zama-protocol-pauser-wallet/outputs.tf @@ -0,0 +1,4 @@ +output "aws_kms_key_id" { + description = "Summary of the KMS Key for the application" + value = local.kms_key_id +} diff --git a/modules/zama-protocol-pauser-wallet/variables.tf b/modules/zama-protocol-pauser-wallet/variables.tf new file mode 100644 index 0000000..7a24207 --- /dev/null +++ b/modules/zama-protocol-pauser-wallet/variables.tf @@ -0,0 +1,101 @@ +# ************ +# General variables +# ************ +variable "tags" { + type = map(string) + description = "The tags for the KMS keys" +} + +# ************ +# Variables for usage in kms-for-mpc-party.tf +# ************ + +variable "cluster_name" { + type = string + description = "Name of the cluster" + default = null +} + +variable "app_name" { + type = string + description = "Name of the role" + default = "zama-protocol-pause" +} + +variable "k8s_config_map_name" { + type = string + description = "Name of the configmap" + default = "zama-protocol-pause" +} + +variable "k8s_config_map_create" { + type = bool + description = "Whether to create the configmap for that holds AWS_KMS_KEY_ID" + default = true +} + +variable "k8s_service_account_name" { + type = string + description = "Name of the service account" + default = "zama-protocol-pause" +} + +variable "k8s_service_account_create" { + type = bool + description = "Whether to create the service account for the KMS key" + default = true +} + +variable "k8s_namespace" { + type = string + description = "Namespace of the application" + default = "zama-protocol" +} + +variable "k8s_create_namespace" { + description = "Whether to create the namespace if it doesn't exist" + type = bool + default = false +} + +variable "zama_protocol_pauser_iam_assumable_role_enabled" { + type = bool + description = "Whether to enable the IAM assumable role for the application" + default = false +} + +variable "kms_cross_account_iam_role_arn" { + type = string + description = "ARN of cross-account IAM role allowed for usage of KMS key" + default = null +} + +variable "kms_key_usage" { + type = string + description = "Key usage for txsender" + default = "SIGN_VERIFY" +} + +variable "kms_key_spec" { + description = "Specification for the txsender (e.g., ECC_SECG_P256K1 for Ethereum key signing)" + type = string + default = "ECC_SECG_P256K1" +} + +variable "kms_deletion_window_in_days" { + type = number + description = "Deletion window in days for KMS key" + default = 30 +} + +variable "kms_use_cross_account_kms_key" { + type = bool + description = "Whether a KMS key has been created in a different AWS account" + default = false +} + +variable "kms_cross_account_kms_key_id" { + type = string + description = "KMS key ID of KMS key created in a different AWS account" + default = "" +} diff --git a/modules/zama-protocol-pauser-wallet/versions.tf b/modules/zama-protocol-pauser-wallet/versions.tf new file mode 100644 index 0000000..7639655 --- /dev/null +++ b/modules/zama-protocol-pauser-wallet/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 6.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.23" + } + } +}