diff --git a/modules/mpc-backup-key/README.md b/modules/mpc-backup-key/README.md new file mode 100644 index 0000000..8077dca --- /dev/null +++ b/modules/mpc-backup-key/README.md @@ -0,0 +1,44 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.10 | +| [aws](#requirement\_aws) | >= 6.0 | +| [random](#requirement\_random) | >= 3.1 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 6.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.this_backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.this_backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [mpc\_party\_cross\_account\_iam\_role\_arn](#input\_mpc\_party\_cross\_account\_iam\_role\_arn) | ARN of cross-account IAM role allowed for usage of KMS key | `string` | `null` | no | +| [mpc\_party\_kms\_alias](#input\_mpc\_party\_kms\_alias) | Alias for the KMS key | `string` | `null` | no | +| [mpc\_party\_kms\_backup\_description](#input\_mpc\_party\_kms\_backup\_description) | Description of KMS Key | `string` | `"Asymmetric KMS key backup for MPC Party"` | no | +| [mpc\_party\_kms\_backup\_vault\_customer\_master\_key\_spec](#input\_mpc\_party\_kms\_backup\_vault\_customer\_master\_key\_spec) | Key spec for the backup vault | `string` | `"ASYMMETRIC_DEFAULT"` | no | +| [mpc\_party\_kms\_backup\_vault\_key\_usage](#input\_mpc\_party\_kms\_backup\_vault\_key\_usage) | Key usage for the backup vault | `string` | `"ENCRYPT_DECRYPT"` | no | +| [mpc\_party\_kms\_deletion\_window\_in\_days](#input\_mpc\_party\_kms\_deletion\_window\_in\_days) | Deletion window in days for KMS key | `number` | `30` | no | +| [mpc\_party\_kms\_image\_attestation\_sha](#input\_mpc\_party\_kms\_image\_attestation\_sha) | Attestation SHA for KMS image | `string` | `null` | no | +| [tags](#input\_tags) | A map of tags to assign to the resource | `map(string)` |
{
"module": "mpc-party-backup",
"terraform": "true"
} | no |
+
+## Outputs
+
+No outputs.
+
diff --git a/modules/mpc-backup-key/main.tf b/modules/mpc-backup-key/main.tf
new file mode 100644
index 0000000..ce2f09e
--- /dev/null
+++ b/modules/mpc-backup-key/main.tf
@@ -0,0 +1,77 @@
+# ************
+# Data Sources
+# ************
+data "aws_caller_identity" "current" {}
+
+# ************
+# ASYMMETRIC KMS Key Backup for MPC Party
+# ************
+resource "aws_kms_key" "this_backup" {
+ description = var.mpc_party_kms_backup_description
+ key_usage = var.mpc_party_kms_backup_vault_key_usage
+ customer_master_key_spec = var.mpc_party_kms_backup_vault_customer_master_key_spec
+ enable_key_rotation = false
+ deletion_window_in_days = var.mpc_party_kms_deletion_window_in_days
+ tags = var.tags
+
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Sid = "Allow access for Key Administrators", # https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators
+ Effect = "Allow",
+ Principal = {
+ AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
+ },
+ Action = [
+ "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"
+ ],
+ Resource = "*"
+ },
+ {
+ Effect = "Allow",
+ Principal = {
+ AWS = var.mpc_party_cross_account_iam_role_arn
+ },
+ Action = [
+ "kms:GetPublicKey",
+ ],
+ Resource = "*"
+ },
+ {
+ Effect = "Allow",
+ Principal = {
+ AWS = var.mpc_party_cross_account_iam_role_arn
+ },
+ Action = [
+ "kms:Decrypt",
+ "kms:GenerateDataKey",
+ ],
+ Resource = "*",
+ Condition = {
+ StringEqualsIgnoreCase = {
+ "kms:RecipientAttestation:ImageSha384" : var.mpc_party_kms_image_attestation_sha
+ }
+ }
+ },
+ ]
+ })
+}
+
+resource "aws_kms_alias" "this_backup" {
+ name = "${var.mpc_party_kms_alias}-backup"
+ target_key_id = aws_kms_key.this_backup.key_id
+}
diff --git a/modules/mpc-backup-key/outputs.tf b/modules/mpc-backup-key/outputs.tf
new file mode 100644
index 0000000..e69de29
diff --git a/modules/mpc-backup-key/variables.tf b/modules/mpc-backup-key/variables.tf
new file mode 100644
index 0000000..f4cac4b
--- /dev/null
+++ b/modules/mpc-backup-key/variables.tf
@@ -0,0 +1,58 @@
+# ************
+# General variables
+# ************
+# Tagging
+variable "tags" {
+ type = map(string)
+ description = "A map of tags to assign to the resource"
+ default = {
+ "terraform" = "true"
+ "module" = "mpc-party-backup"
+ }
+}
+
+# ************
+# Variables for usage in main.tf
+# ************
+
+variable "mpc_party_cross_account_iam_role_arn" {
+ type = string
+ description = "ARN of cross-account IAM role allowed for usage of KMS key"
+ default = null
+}
+
+variable "mpc_party_kms_image_attestation_sha" {
+ type = string
+ description = "Attestation SHA for KMS image"
+ default = null
+}
+
+variable "mpc_party_kms_alias" {
+ type = string
+ description = "Alias for the KMS key"
+ default = null
+}
+
+variable "mpc_party_kms_deletion_window_in_days" {
+ type = number
+ description = "Deletion window in days for KMS key"
+ default = 30
+}
+
+variable "mpc_party_kms_backup_description" {
+ type = string
+ description = "Description of KMS Key"
+ default = "Asymmetric KMS key backup for MPC Party"
+}
+
+variable "mpc_party_kms_backup_vault_key_usage" {
+ type = string
+ description = "Key usage for the backup vault"
+ default = "ENCRYPT_DECRYPT"
+}
+
+variable "mpc_party_kms_backup_vault_customer_master_key_spec" {
+ type = string
+ description = "Key spec for the backup vault"
+ default = "ASYMMETRIC_DEFAULT"
+}
diff --git a/modules/mpc-backup-key/versions.tf b/modules/mpc-backup-key/versions.tf
new file mode 100644
index 0000000..03df166
--- /dev/null
+++ b/modules/mpc-backup-key/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.10"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 6.0"
+ }
+ random = {
+ source = "hashicorp/random"
+ version = ">= 3.1"
+ }
+ }
+}
diff --git a/modules/mpc-backup-vault/README.md b/modules/mpc-backup-vault/README.md
new file mode 100644
index 0000000..fe9b1fc
--- /dev/null
+++ b/modules/mpc-backup-vault/README.md
@@ -0,0 +1,61 @@
+# MPC Key backup modules\
+
+This module is aim to create :
+- bucket for backup vault
+
+The kms keys is handled by kms-stack terraform module in infra repo.
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.10 |
+| [aws](#requirement\_aws) | >= 6.0 |
+| [random](#requirement\_random) | >= 3.1 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | >= 6.0 |
+| [random](#provider\_random) | >= 3.1 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_iam_policy.mpc_aws](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_role.mpc_backup_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_iam_role_policy_attachment.mpc_backup_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_s3_bucket.backup_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
+| [aws_s3_bucket_ownership_controls.backup_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource |
+| [aws_s3_bucket_policy.backup_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
+| [aws_s3_bucket_public_access_block.backup_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
+| [aws_s3_bucket_versioning.backup_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
+| [random_id.mpc_party_suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
+| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [bucket\_cross\_account\_id](#input\_bucket\_cross\_account\_id) | ID of the AWS account that can access the backup bucket. | `string` | n/a | yes |
+| [bucket\_prefix](#input\_bucket\_prefix) | The prefix for the S3 bucket names | `string` | `"mpc-backup-vault"` | no |
+| [party\_name](#input\_party\_name) | The name of the MPC party (used for resource naming and tagging) | `string` | n/a | yes |
+| [tags](#input\_tags) | A map of tags to assign to the resource | `map(string)` | {
"module": "mpc-party",
"terraform": "true"
} | no |
+| [trusted\_principal\_arns](#input\_trusted\_principal\_arns) | List of ARNs (users, roles, or root accounts) that can assume the backup role. | `list(string)` | `[]` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [bucket\_arn](#output\_bucket\_arn) | The ARN of the created S3 bucket |
+| [bucket\_name](#output\_bucket\_name) | The name of the created S3 bucket |
+| [role\_arn](#output\_role\_arn) | The ARN of the IAM role created for accessing the bucket |
+| [role\_name](#output\_role\_name) | The name of the IAM role created for accessing the bucket |
+
diff --git a/modules/mpc-backup-vault/main.tf b/modules/mpc-backup-vault/main.tf
new file mode 100644
index 0000000..c30469c
--- /dev/null
+++ b/modules/mpc-backup-vault/main.tf
@@ -0,0 +1,120 @@
+# ***************************************
+# Local variables
+# ***************************************
+resource "random_id" "mpc_party_suffix" {
+ byte_length = 4
+}
+locals {
+ backup_bucket_name = "${var.bucket_prefix}-${var.party_name}-${random_id.mpc_party_suffix.hex}"
+}
+
+# ***************************************
+# S3 Buckets for Vault Private Storage
+# ***************************************
+resource "aws_s3_bucket" "backup_bucket" {
+ force_destroy = true
+ bucket = local.backup_bucket_name
+ tags = merge(var.tags, {
+ "Name" = local.backup_bucket_name
+ "Type" = "backup-vault"
+ "Party" = var.party_name
+ "Purpose" = "mpc-backup-storage"
+ })
+}
+
+resource "aws_s3_bucket_ownership_controls" "backup_bucket" {
+ bucket = aws_s3_bucket.backup_bucket.id
+ rule {
+ object_ownership = "BucketOwnerEnforced"
+ }
+}
+
+resource "aws_s3_bucket_versioning" "backup_bucket" {
+ bucket = aws_s3_bucket.backup_bucket.id
+ versioning_configuration {
+ status = "Enabled"
+ }
+}
+
+resource "aws_s3_bucket_public_access_block" "backup_bucket" {
+ bucket = aws_s3_bucket.backup_bucket.id
+ block_public_acls = true
+ block_public_policy = true
+ ignore_public_acls = true
+ restrict_public_buckets = true
+}
+
+resource "aws_s3_bucket_policy" "backup_bucket" {
+ bucket = aws_s3_bucket.backup_bucket.id
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Sid = "AllowCrossAccountBackup"
+ Effect = "Allow"
+ Principal = {
+ AWS = "arn:aws:iam::${var.bucket_cross_account_id}:root"
+ }
+ Action = "s3:*"
+ Resource = [
+ "arn:aws:s3:::${aws_s3_bucket.backup_bucket.id}",
+ "arn:aws:s3:::${aws_s3_bucket.backup_bucket.id}/*"
+ ]
+ }
+ ]
+ })
+}
+
+# ***************************************
+# IAM Role & Policy for MPC Backup Vault
+# ***************************************
+
+# Trust policy: Allow trusted principals to assume this role
+data "aws_iam_policy_document" "assume_role" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ effect = "Allow"
+ principals {
+ type = "AWS"
+ identifiers = var.trusted_principal_arns
+ }
+ }
+}
+
+resource "aws_iam_role" "mpc_backup_role" {
+ name = "mpc-backup-${var.party_name}"
+ assume_role_policy = data.aws_iam_policy_document.assume_role.json
+ tags = var.tags
+}
+
+# Policy allowing access to the bucket
+resource "aws_iam_policy" "mpc_aws" {
+ name = "mpc-backup-${var.party_name}"
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Sid = "AllowObjectActions"
+ Effect = "Allow"
+ Action = "s3:*Object"
+ Resource = [
+ "arn:aws:s3:::${aws_s3_bucket.backup_bucket.id}/*"
+ ]
+ },
+ {
+ Sid = "AllowListBucket"
+ Effect = "Allow"
+ Action = "s3:ListBucket"
+ Resource = [
+ "arn:aws:s3:::${aws_s3_bucket.backup_bucket.id}"
+ ]
+ }
+ ]
+ })
+}
+
+# Attach policy to the role
+resource "aws_iam_role_policy_attachment" "mpc_backup_attach" {
+ role = aws_iam_role.mpc_backup_role.name
+ policy_arn = aws_iam_policy.mpc_aws.arn
+}
diff --git a/modules/mpc-backup-vault/outputs.tf b/modules/mpc-backup-vault/outputs.tf
new file mode 100644
index 0000000..fd097be
--- /dev/null
+++ b/modules/mpc-backup-vault/outputs.tf
@@ -0,0 +1,19 @@
+output "bucket_name" {
+ description = "The name of the created S3 bucket"
+ value = aws_s3_bucket.backup_bucket.id
+}
+
+output "bucket_arn" {
+ description = "The ARN of the created S3 bucket"
+ value = aws_s3_bucket.backup_bucket.arn
+}
+
+output "role_name" {
+ description = "The name of the IAM role created for accessing the bucket"
+ value = aws_iam_role.mpc_backup_role.name
+}
+
+output "role_arn" {
+ description = "The ARN of the IAM role created for accessing the bucket"
+ value = aws_iam_role.mpc_backup_role.arn
+}
diff --git a/modules/mpc-backup-vault/variables.tf b/modules/mpc-backup-vault/variables.tf
new file mode 100644
index 0000000..7d1a6f5
--- /dev/null
+++ b/modules/mpc-backup-vault/variables.tf
@@ -0,0 +1,37 @@
+# Tagging
+variable "tags" {
+ type = map(string)
+ description = "A map of tags to assign to the resource"
+ default = {
+ "terraform" = "true"
+ "module" = "mpc-party"
+ }
+}
+
+variable "bucket_prefix" {
+ type = string
+ description = "The prefix for the S3 bucket names"
+ default = "mpc-backup-vault"
+}
+
+# MPC Party Configuration
+variable "party_name" {
+ type = string
+ description = "The name of the MPC party (used for resource naming and tagging)"
+
+ validation {
+ condition = can(regex("^[a-z0-9-]+$", var.party_name))
+ error_message = "Party name must contain only lowercase letters, numbers, and hyphens."
+ }
+}
+
+variable "trusted_principal_arns" {
+ type = list(string)
+ description = "List of ARNs (users, roles, or root accounts) that can assume the backup role."
+ default = []
+}
+
+variable "bucket_cross_account_id" {
+ type = string
+ description = "ID of the AWS account that can access the backup bucket."
+}
diff --git a/modules/mpc-backup-vault/versions.tf b/modules/mpc-backup-vault/versions.tf
new file mode 100644
index 0000000..03df166
--- /dev/null
+++ b/modules/mpc-backup-vault/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.10"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 6.0"
+ }
+ random = {
+ source = "hashicorp/random"
+ version = ">= 3.1"
+ }
+ }
+}
diff --git a/modules/mpc-party/README.md b/modules/mpc-party/README.md
index df44639..f2b91ca 100644
--- a/modules/mpc-party/README.md
+++ b/modules/mpc-party/README.md
@@ -377,8 +377,10 @@ The module can optionally create:
| [k8s\_namespace](#input\_k8s\_namespace) | The Kubernetes namespace for MPC party resources | `string` | `"kms-decentralized"` | no |
| [k8s\_service\_account\_name](#input\_k8s\_service\_account\_name) | The name of the Kubernetes service account for MPC party | `string` | n/a | yes |
| [kms\_backup\_external\_role\_arn](#input\_kms\_backup\_external\_role\_arn) | ARN of the backup vault for the KMS key | `string` | `null` | no |
+| [kms\_backup\_vault\_bucket\_name](#input\_kms\_backup\_vault\_bucket\_name) | Backup vault S3 bucket name | `string` | `null` | no |
| [kms\_backup\_vault\_customer\_master\_key\_spec](#input\_kms\_backup\_vault\_customer\_master\_key\_spec) | Key spec for the backup vault | `string` | `"ASYMMETRIC_DEFAULT"` | no |
| [kms\_backup\_vault\_key\_usage](#input\_kms\_backup\_vault\_key\_usage) | Key usage for the backup vault | `string` | `"ENCRYPT_DECRYPT"` | no |
+| [kms\_backup\_vault\_kms\_key\_arn](#input\_kms\_backup\_vault\_kms\_key\_arn) | KMS key ARN for the backup vault | `string` | `null` | no |
| [kms\_connector\_enable\_txsender\_key](#input\_kms\_connector\_enable\_txsender\_key) | Whether to enable the KMS key for the kms-connector txsender | `bool` | `false` | no |
| [kms\_connector\_txsender\_key\_spec](#input\_kms\_connector\_txsender\_key\_spec) | Specification for the KMS-Connector txsender (e.g., ECC\_SECG\_P256K1 for Ethereum key signing) | `string` | `"ECC_SECG_P256K1"` | no |
| [kms\_connector\_txsender\_key\_usage](#input\_kms\_connector\_txsender\_key\_usage) | Key usage for KMS-Connector txsender | `string` | `"SIGN_VERIFY"` | no |
diff --git a/modules/mpc-party/main.tf b/modules/mpc-party/main.tf
index 25d4717..a4d124d 100644
--- a/modules/mpc-party/main.tf
+++ b/modules/mpc-party/main.tf
@@ -189,26 +189,46 @@ resource "aws_iam_policy" "mpc_aws" {
name = "mpc-${var.cluster_name}-${var.party_name}"
policy = jsonencode({
Version = "2012-10-17"
- Statement = [
- {
- Sid = "AllowObjectActions"
- Effect = "Allow"
- Action = "s3:*Object"
- Resource = [
- "arn:aws:s3:::${aws_s3_bucket.vault_private_bucket.id}/*",
- "arn:aws:s3:::${aws_s3_bucket.vault_public_bucket.id}/*",
- ]
- },
- {
- Sid = "AllowListBucket"
- Effect = "Allow"
- Action = "s3:ListBucket"
- Resource = [
- "arn:aws:s3:::${aws_s3_bucket.vault_private_bucket.id}",
- "arn:aws:s3:::${aws_s3_bucket.vault_public_bucket.id}",
- ]
- }
- ]
+ Statement = concat(
+ [
+ {
+ Sid = "AllowObjectActions"
+ Effect = "Allow"
+ Action = "s3:*Object"
+ Resource = concat(
+ [
+ "arn:aws:s3:::${aws_s3_bucket.vault_private_bucket.id}/*",
+ "arn:aws:s3:::${aws_s3_bucket.vault_public_bucket.id}/*",
+ ],
+ var.kms_enable_backup_vault && var.kms_backup_vault_bucket_name != null ? [
+ "arn:aws:s3:::${var.kms_backup_vault_bucket_name}/*"
+ ] : []
+ )
+ },
+ {
+ Sid = "AllowListBucket"
+ Effect = "Allow"
+ Action = "s3:ListBucket"
+ Resource = concat(
+ [
+ "arn:aws:s3:::${aws_s3_bucket.vault_private_bucket.id}",
+ "arn:aws:s3:::${aws_s3_bucket.vault_public_bucket.id}",
+ ],
+ var.kms_enable_backup_vault && var.kms_backup_vault_bucket_name != null ? [
+ "arn:aws:s3:::${var.kms_backup_vault_bucket_name}"
+ ] : []
+ )
+ }
+ ],
+ var.kms_enable_backup_vault && var.kms_backup_vault_kms_key_arn != null ? [
+ {
+ Sid = "AllowCrossAccountKeyBackup"
+ Effect = "Allow"
+ Action = "kms:GetPublicKey"
+ Resource = var.kms_backup_vault_kms_key_arn
+ }
+ ] : []
+ )
})
}
diff --git a/modules/mpc-party/variables.tf b/modules/mpc-party/variables.tf
index 339cd1f..2e012d8 100644
--- a/modules/mpc-party/variables.tf
+++ b/modules/mpc-party/variables.tf
@@ -402,18 +402,37 @@ variable "kms_connector_txsender_key_spec" {
default = "ECC_SECG_P256K1"
}
+#******************************************************
+# Backup Vault Configuration
+#******************************************************
variable "kms_enable_backup_vault" {
type = bool
description = "Whether to enable the backup vault for the KMS key"
default = false
}
+variable "kms_backup_vault_bucket_name" {
+ type = string
+ description = "Backup vault S3 bucket name"
+ default = null
+}
+
+variable "kms_backup_vault_kms_key_arn" {
+ type = string
+ description = "KMS key ARN for the backup vault"
+ default = null
+}
+
+#******************************************************
+# We use :
+# - mpc-backup-key terraform module to create the kms backup key
+# - mpc-backup-vault terraform module to create the kms backup bucket
+#******************************************************
variable "kms_backup_external_role_arn" {
type = string
description = "ARN of the backup vault for the KMS key"
default = null
}
-
variable "kms_backup_vault_key_usage" {
type = string
description = "Key usage for the backup vault"
@@ -425,6 +444,7 @@ variable "kms_backup_vault_customer_master_key_spec" {
description = "Key spec for the backup vault"
default = "ASYMMETRIC_DEFAULT"
}
+#******************************************************
variable "nodegroup_enable_ssm_managed_instance" {
type = bool