diff --git a/modules/flyte/README.md b/modules/flyte/README.md
new file mode 100644
index 00000000..a1e7d013
--- /dev/null
+++ b/modules/flyte/README.md
@@ -0,0 +1,59 @@
+# flyte
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0 |
+| [aws](#requirement\_aws) | ~> 5.0 |
+| [null](#requirement\_null) | >= 3.1.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | ~> 5.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_iam_policy.flyte_controlplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_policy.flyte_dataplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
+| [aws_iam_role.flyte_controlplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_iam_role.flyte_dataplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_iam_role_policy_attachment.flyte_controlplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_iam_role_policy_attachment.flyte_dataplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_s3_bucket.flyte_data](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
+| [aws_s3_bucket.flyte_metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
+| [aws_s3_bucket_policy.flyte_data](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
+| [aws_s3_bucket_policy.flyte_metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
+| [aws_s3_bucket_server_side_encryption_configuration.flye_metadata_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
+| [aws_s3_bucket_server_side_encryption_configuration.flyte_data_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
+| [aws_iam_policy_document.flyte_controlplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.flyte_data](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.flyte_dataplane](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.flyte_metadata](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 |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [compute\_namespace](#input\_compute\_namespace) | Name of Domino compute namespace for this deploy | `string` | n/a | yes |
+| [eks\_info](#input\_eks\_info) | cluster = {
specs {
name = Cluster name.
account\_id = AWS account id where the cluster resides.
}
oidc = {
arn = OIDC provider ARN.
url = OIDC provider url.
cert = {
thumbprint\_list = OIDC cert thumbprints.
url = OIDC cert URL.
}
} |
object({| n/a | yes | +| [force\_destroy\_on\_deletion](#input\_force\_destroy\_on\_deletion) | Whether to force destroy flyte s3 buckets on deletion | `bool` | `true` | no | +| [platform\_namespace](#input\_platform\_namespace) | Name of Domino platform namespace for this deploy | `string` | n/a | yes | +| [serviceaccount\_names](#input\_serviceaccount\_names) | Service account names for Flyte |
cluster = object({
specs = object({
name = string
account_id = string
})
oidc = object({
arn = string
url = string
cert = object({
thumbprint_list = list(string)
url = string
})
})
})
})
object({| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [eks](#output\_eks) | Flyte eks info | + diff --git a/modules/flyte/iam.tf b/modules/flyte/iam.tf new file mode 100644 index 00000000..695de67b --- /dev/null +++ b/modules/flyte/iam.tf @@ -0,0 +1,102 @@ +resource "aws_iam_role" "flyte_controlplane" { + name = "${local.deploy_id}-flyte-controlplane" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRoleWithWebIdentity" + Effect = "Allow" + Principal = { + Federated = local.oidc_provider_arn + } + Condition : { + StringEquals : { + "${trimprefix(local.oidc_provider_url, "https://")}:aud" : "sts.amazonaws.com", + "${trimprefix(local.oidc_provider_url, "https://")}:sub" : [ + "system:serviceaccount:${var.platform_namespace}:${var.serviceaccount_names.flyteadmin}", + "system:serviceaccount:${var.platform_namespace}:${var.serviceaccount_names.flytepropeller}", + ] + } + } + }, + ] + }) +} + +data "aws_iam_policy_document" "flyte_controlplane" { + statement { + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}/*", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}" + ] + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket", + ] + } +} + +resource "aws_iam_policy" "flyte_controlplane" { + name = "${local.deploy_id}-flyte-controlplane" + policy = data.aws_iam_policy_document.flyte_controlplane.json +} + +resource "aws_iam_role_policy_attachment" "flyte_controlplane" { + role = aws_iam_role.flyte_controlplane.name + policy_arn = aws_iam_policy.flyte_controlplane.arn +} + +resource "aws_iam_role" "flyte_dataplane" { + name = "${local.deploy_id}-flyte-dataplane" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRoleWithWebIdentity" + Effect = "Allow" + Principal = { + Federated = local.oidc_provider_arn + } + Condition : { + StringEquals : { + "${trimprefix(local.oidc_provider_url, "https://")}:aud" : "sts.amazonaws.com", + "${trimprefix(local.oidc_provider_url, "https://")}:sub" : [ + "system:serviceaccount:${var.platform_namespace}:${var.serviceaccount_names.datacatalog}", + "system:serviceaccount:${var.compute_namespace}:*" + ] + } + } + }, + ] + }) +} + +data "aws_iam_policy_document" "flyte_dataplane" { + statement { + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}/*", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data.bucket}/*", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data.bucket}", + ] + + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket" + ] + } +} + +resource "aws_iam_policy" "flyte_dataplane" { + name = "${local.deploy_id}-flyte-dataplane" + policy = data.aws_iam_policy_document.flyte_dataplane.json +} + +resource "aws_iam_role_policy_attachment" "flyte_dataplane" { + role = aws_iam_role.flyte_dataplane.name + policy_arn = aws_iam_policy.flyte_dataplane.arn +} diff --git a/modules/flyte/main.tf b/modules/flyte/main.tf new file mode 100644 index 00000000..8c00e730 --- /dev/null +++ b/modules/flyte/main.tf @@ -0,0 +1,7 @@ +data "aws_partition" "current" {} + +locals { + deploy_id = var.eks_info.cluster.specs.name + oidc_provider_arn = var.eks_info.cluster.oidc.arn + oidc_provider_url = var.eks_info.cluster.oidc.cert.url +} \ No newline at end of file diff --git a/modules/flyte/outputs.tf b/modules/flyte/outputs.tf new file mode 100644 index 00000000..55071212 --- /dev/null +++ b/modules/flyte/outputs.tf @@ -0,0 +1,9 @@ +output "eks" { + description = "Flyte eks info" + value = { + metadata_bucket = aws_s3_bucket.flyte_metadata.bucket + data_bucket = aws_s3_bucket.flyte_data.bucket + controlplane_role_arn = aws_iam_role.flyte_controlplane.arn + dataplane_role_arn = aws_iam_role.flyte_dataplane.arn + } +} diff --git a/modules/flyte/s3.tf b/modules/flyte/s3.tf new file mode 100644 index 00000000..c7e2a50a --- /dev/null +++ b/modules/flyte/s3.tf @@ -0,0 +1,101 @@ +resource "aws_s3_bucket" "flyte_metadata" { + bucket = "${local.deploy_id}-flyte-metadata" + force_destroy = var.force_destroy_on_deletion + object_lock_enabled = false +} + +data "aws_iam_policy_document" "flyte_metadata" { + statement { + effect = "Deny" + + resources = [ + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket_policy" "flyte_metadata" { + bucket = aws_s3_bucket.flyte_metadata.id + policy = data.aws_iam_policy_document.flyte_metadata.json +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "flye_metadata_encryption" { + bucket = aws_s3_bucket.flyte_metadata.bucket + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + bucket_key_enabled = false + } + + lifecycle { + ignore_changes = [ + rule, + ] + } +} + +resource "aws_s3_bucket" "flyte_data" { + bucket = "${local.deploy_id}-flyte-data" + force_destroy = var.force_destroy_on_deletion + object_lock_enabled = false +} + +data "aws_iam_policy_document" "flyte_data" { + statement { + effect = "Deny" + + resources = [ + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data.bucket}", + "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket_policy" "flyte_data" { + bucket = aws_s3_bucket.flyte_data.id + policy = data.aws_iam_policy_document.flyte_data.json +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "flyte_data_encryption" { + bucket = aws_s3_bucket.flyte_data.bucket + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + bucket_key_enabled = false + } + + lifecycle { + ignore_changes = [ + rule, + ] + } +} \ No newline at end of file diff --git a/modules/flyte/variables.tf b/modules/flyte/variables.tf new file mode 100644 index 00000000..60f6a65e --- /dev/null +++ b/modules/flyte/variables.tf @@ -0,0 +1,60 @@ +variable "force_destroy_on_deletion" { + description = "Whether to force destroy flyte s3 buckets on deletion" + type = bool + default = true +} + +variable "eks_info" { + description = <
datacatalog = optional(string, "datacatalog")
flyteadmin = optional(string, "flyteadmin")
flytepropeller = optional(string, "flytepropeller")
})
object({| `{}` | no | | [eks](#input\_eks) | creation\_role\_name = Name of the role to import.
provision_cost_usage_report = optional(bool, false)
})
object({| `{}` | no | -| [flyte](#input\_flyte) | enabled = Whether to provision any Flyte related resources |
creation_role_name = optional(string, null)
k8s_version = optional(string, "1.27")
nodes_master = optional(bool, false)
kubeconfig = optional(object({
extra_args = optional(string, "")
path = optional(string, null)
}), {})
public_access = optional(object({
enabled = optional(bool, false)
cidrs = optional(list(string), [])
}), {})
custom_role_maps = optional(list(object({
rolearn = string
username = string
groups = list(string)
})), [])
master_role_names = optional(list(string), [])
cluster_addons = optional(list(string), ["kube-proxy", "coredns", "vpc-cni"])
ssm_log_group_name = optional(string, "session-manager")
vpc_cni = optional(object({
prefix_delegation = optional(bool)
annotate_pod_ip = optional(bool)
}))
identity_providers = optional(list(object({
client_id = string
groups_claim = optional(string, null)
groups_prefix = optional(string, null)
identity_provider_config_name = string
issuer_url = optional(string, null)
required_claims = optional(string, null)
username_claim = optional(string, null)
username_prefix = optional(string, null)
})), [])
})
object({| `{}` | no | | [ignore\_tags](#input\_ignore\_tags) | Tag keys to be ignored by the aws provider. | `list(string)` | `[]` | no | | [kms](#input\_kms) | enabled = "Toggle, if set use either the specified KMS key\_id or a Domino-generated one"
enabled = optional(bool, false)
})
object({| `{}` | no | | [network](#input\_network) | vpc = {
enabled = optional(bool, true)
key_id = optional(string, null)
additional_policies = optional(list(string), [])
})
object({| `{}` | no | diff --git a/modules/infra/main.tf b/modules/infra/main.tf index c04b0d3d..ff3f1006 100644 --- a/modules/infra/main.tf +++ b/modules/infra/main.tf @@ -31,7 +31,6 @@ module "storage" { network_info = module.network.info kms_info = local.kms_info storage = var.storage - flyte = var.flyte } data "aws_ec2_instance_type" "all" { diff --git a/modules/infra/submodules/storage/README.md b/modules/infra/submodules/storage/README.md index a77c82d7..adfe3252 100644 --- a/modules/infra/submodules/storage/README.md +++ b/modules/infra/submodules/storage/README.md @@ -37,8 +37,6 @@ No modules. | [aws_s3_bucket.backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.blobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.costs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket.flyte_data](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket.flyte_metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | @@ -59,8 +57,6 @@ No modules. | [aws_iam_policy_document.blobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.costs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.ecr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.flyte_data](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.flyte_metadata](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -72,7 +68,6 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | -| [flyte](#input\_flyte) | enabled = Whether to provision any Flyte related resources |
vpc = optional(object({
id = optional(string, null)
subnets = optional(object({
private = optional(list(string), [])
public = optional(list(string), [])
pod = optional(list(string), [])
}), {})
}), {})
network_bits = optional(object({
public = optional(number, 27)
private = optional(number, 19)
pod = optional(number, 19)
}
), {})
cidrs = optional(object({
vpc = optional(string, "10.0.0.0/16")
pod = optional(string, "100.64.0.0/16")
}), {})
use_pod_cidr = optional(bool, true)
})
object({| `{}` | no | | [kms\_info](#input\_kms\_info) | key\_id = KMS key id.
enabled = optional(bool, false)
})
object({| n/a | yes | | [network\_info](#input\_network\_info) | id = VPC ID.
key_id = string
key_arn = string
enabled = bool
})
object({| n/a | yes | | [storage](#input\_storage) | storage = {
vpc_id = string
subnets = object({
public = optional(list(object({
name = string
subnet_id = string
az = string
az_id = string
})), [])
private = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
pod = optional(list(object({
name = string
subnet_id = string
az = string
az_id = string
})), [])
})
})
object({| n/a | yes | diff --git a/modules/infra/submodules/storage/main.tf b/modules/infra/submodules/storage/main.tf index 137cbbb7..bb378f33 100644 --- a/modules/infra/submodules/storage/main.tf +++ b/modules/infra/submodules/storage/main.tf @@ -24,18 +24,6 @@ locals { policy_json = data.aws_iam_policy_document.costs[0].json arn = aws_s3_bucket.costs[0].arn } : {} - flyte_metadata = var.flyte.enabled ? { - bucket_name = aws_s3_bucket.flyte_metadata[0].bucket - id = aws_s3_bucket.flyte_metadata[0].id - policy_json = data.aws_iam_policy_document.flyte_metadata[0].json - arn = aws_s3_bucket.flyte_metadata[0].arn - } : {} - flyte_data = var.flyte.enabled ? { - bucket_name = aws_s3_bucket.flyte_data[0].bucket - id = aws_s3_bucket.flyte_data[0].id - policy_json = data.aws_iam_policy_document.flyte_data[0].json - arn = aws_s3_bucket.flyte_data[0].arn - } : {} logs = { bucket_name = aws_s3_bucket.logs.bucket id = aws_s3_bucket.logs.id diff --git a/modules/infra/submodules/storage/s3.tf b/modules/infra/submodules/storage/s3.tf index 99e9ebee..13c4bdd5 100644 --- a/modules/infra/submodules/storage/s3.tf +++ b/modules/infra/submodules/storage/s3.tf @@ -603,69 +603,3 @@ data "aws_iam_policy_document" "costs" { } } } - -resource "aws_s3_bucket" "flyte_metadata" { - count = var.flyte.enabled ? 1 : 0 - bucket = "${var.deploy_id}-flyte-metadata" - force_destroy = var.storage.s3.force_destroy_on_deletion - object_lock_enabled = false -} - -data "aws_iam_policy_document" "flyte_metadata" { - count = var.flyte.enabled ? 1 : 0 - - statement { - effect = "Deny" - - resources = [ - "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata[0].bucket}", - "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_metadata[0].bucket}/*", - ] - - actions = ["s3:*"] - - condition { - test = "Bool" - variable = "aws:SecureTransport" - values = ["false"] - } - - principals { - type = "AWS" - identifiers = ["*"] - } - } -} - -resource "aws_s3_bucket" "flyte_data" { - count = var.flyte.enabled ? 1 : 0 - bucket = "${var.deploy_id}-flyte-data" - force_destroy = var.storage.s3.force_destroy_on_deletion - object_lock_enabled = false -} - -data "aws_iam_policy_document" "flyte_data" { - count = var.flyte.enabled ? 1 : 0 - - statement { - effect = "Deny" - - resources = [ - "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data[0].bucket}", - "arn:${data.aws_partition.current.partition}:s3:::${aws_s3_bucket.flyte_data[0].bucket}/*", - ] - - actions = ["s3:*"] - - condition { - test = "Bool" - variable = "aws:SecureTransport" - values = ["false"] - } - - principals { - type = "AWS" - identifiers = ["*"] - } - } -} diff --git a/modules/infra/submodules/storage/variables.tf b/modules/infra/submodules/storage/variables.tf index 56f6b40a..9a535c86 100644 --- a/modules/infra/submodules/storage/variables.tf +++ b/modules/infra/submodules/storage/variables.tf @@ -122,14 +122,3 @@ variable "network_info" { }) }) } - -variable "flyte" { - description = <
efs = optional(object({
access_point_path = optional(string)
backup_vault = optional(object({
create = optional(bool)
force_destroy = optional(bool)
backup = optional(object({
schedule = optional(string)
cold_storage_after = optional(number)
delete_after = optional(number)
}))
}))
}))
s3 = optional(object({
force_destroy_on_deletion = optional(bool)
}))
ecr = optional(object({
force_destroy_on_deletion = optional(bool)
}))
enable_remote_backup = optional(bool)
costs_enabled = optional(bool)
})
list(object({| `[]` | no | | [eks\_info](#input\_eks\_info) | cluster = {
name = string
namespace = string
serviceaccount_name = string
policy = string #json
}))
object({| n/a | yes | | [external\_dns](#input\_external\_dns) | Config to enable irsa for external-dns |
nodes = object({
roles = list(object({
arn = string
name = string
}))
})
cluster = object({
specs = object({
name = string
account_id = string
})
oidc = object({
arn = string
url = string
cert = object({
thumbprint_list = list(string)
url = string
})
})
})
})
object({| `{}` | no | -| [flyte](#input\_flyte) | enabled = Whether to provision any Flyte related resources
enabled = optional(bool, false)
hosted_zone_name = optional(string, null)
hosted_zone_private = optional(string, false)
namespace = optional(string, "domino-platform")
serviceaccount_name = optional(string, "external-dns")
rm_role_policy = optional(object({
remove = optional(bool, false)
detach_from_role = optional(bool, false)
policy_name = optional(string, "")
}), {})
})
object({| `{}` | no | | [use\_cluster\_odc\_idp](#input\_use\_cluster\_odc\_idp) | Toogle to uset the oidc idp connector in the trust policy.
enabled = optional(bool, false)
})