mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-02 14:26:23 -04:00
terraform-provider: implement constellation_cluster
resource (#2691)
* terraform: move module to legacy-directory * constellation-lib: refactor service account marshalling * terraform-provider: normalize Azure image URIs * constellation-lib: refactor Kubeconfig endpoint rewriting * terraform-provider: add conversion functions for AWS and GCP * terraform-provider: implement `constellation_cluster` resource * terraform-provider: refactor conversion * terraform-provider: implement image and k8s upgrades * terraform-provider: fix linter checks * terraform-provider: refactor to bundle init & upgrade method * constellation-lib: rewrite Kubeconfig endpoint in init * terraform-provider: bind logger and dialer constructors to struct * terraform-provider: move applier to function pointer * terraform-provider: gcp conversion fixes Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * terraform-provider: fix Azure UAMI input * terraform-provider: rename Kubeconfig variable * terraform-provider: tidy * terraform-provider: regenerate docs * constellation-lib: provide Kubeconfig in testing initserver --------- Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
This commit is contained in:
parent
767bac4766
commit
60fc73e0e7
40 changed files with 1469 additions and 323 deletions
67
terraform/legacy-module/aws-constellation/main.tf
Normal file
67
terraform/legacy-module/aws-constellation/main.tf
Normal file
|
@ -0,0 +1,67 @@
|
|||
locals {
|
||||
region = substr(var.zone, 0, length(var.zone) - 1)
|
||||
}
|
||||
|
||||
module "aws_iam" {
|
||||
source = "../../infrastructure/iam/aws"
|
||||
name_prefix = var.name_prefix
|
||||
region = local.region
|
||||
}
|
||||
|
||||
resource "null_resource" "ensure_yq" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
../common/install-yq.sh
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
module "fetch_image" {
|
||||
source = "../common/fetch-image"
|
||||
csp = "aws"
|
||||
attestation_variant = var.enable_snp ? "aws-sev-snp" : "aws-nitro-tpm"
|
||||
region = local.region
|
||||
image = var.image
|
||||
depends_on = [module.aws_iam, null_resource.ensure_yq]
|
||||
}
|
||||
|
||||
module "aws" {
|
||||
source = "../../infrastructure/aws"
|
||||
name = var.name
|
||||
node_groups = var.node_groups
|
||||
iam_instance_profile_worker_nodes = module.aws_iam.worker_nodes_instance_profile
|
||||
iam_instance_profile_control_plane = module.aws_iam.control_plane_instance_profile
|
||||
ami = module.fetch_image.image
|
||||
region = local.region
|
||||
zone = var.zone
|
||||
debug = var.debug
|
||||
enable_snp = var.enable_snp
|
||||
custom_endpoint = var.custom_endpoint
|
||||
}
|
||||
|
||||
module "constellation" {
|
||||
source = "../constellation-cluster"
|
||||
csp = "aws"
|
||||
debug = var.debug
|
||||
name = var.name
|
||||
image = var.image
|
||||
microservice_version = var.microservice_version
|
||||
kubernetes_version = var.kubernetes_version
|
||||
uid = module.aws.uid
|
||||
clusterEndpoint = module.aws.out_of_cluster_endpoint
|
||||
inClusterEndpoint = module.aws.in_cluster_endpoint
|
||||
initSecretHash = module.aws.initSecret
|
||||
ipCidrNode = module.aws.ip_cidr_nodes
|
||||
apiServerCertSANs = module.aws.api_server_cert_sans
|
||||
node_groups = var.node_groups
|
||||
aws_config = {
|
||||
region = local.region
|
||||
zone = var.zone
|
||||
iam_instance_profile_worker_nodes = module.aws_iam.worker_nodes_instance_profile
|
||||
iam_instance_profile_control_plane = module.aws_iam.control_plane_instance_profile
|
||||
}
|
||||
depends_on = [module.aws, null_resource.ensure_yq]
|
||||
}
|
72
terraform/legacy-module/aws-constellation/variables.tf
Normal file
72
terraform/legacy-module/aws-constellation/variables.tf
Normal file
|
@ -0,0 +1,72 @@
|
|||
variable "name" {
|
||||
type = string
|
||||
description = "Name of the Constellation cluster."
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
type = string
|
||||
description = "Node image reference or semantic release version. When not set, the latest default version will be used."
|
||||
default = "@@CONSTELLATION_VERSION@@"
|
||||
}
|
||||
|
||||
variable "microservice_version" {
|
||||
type = string
|
||||
description = "Microservice version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "kubernetes_version" {
|
||||
type = string
|
||||
description = "Kubernetes version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "node_groups" {
|
||||
type = map(object({
|
||||
role = string
|
||||
initial_count = optional(number)
|
||||
instance_type = string
|
||||
disk_size = number
|
||||
disk_type = string
|
||||
zone = string
|
||||
}))
|
||||
description = "A map of node group names to node group configurations."
|
||||
validation {
|
||||
condition = can([for group in var.node_groups : group.role == "control-plane" || group.role == "worker"])
|
||||
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
type = string
|
||||
description = "The AWS availability zone name to create the cluster in."
|
||||
}
|
||||
|
||||
variable "debug" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "DON'T USE IN PRODUCTION: Enable debug mode and allow the use of debug images."
|
||||
}
|
||||
|
||||
variable "enable_snp" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Enable AMD SEV-SNP."
|
||||
}
|
||||
|
||||
variable "custom_endpoint" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Custom endpoint (DNS Name) to use for the Constellation API server. If not set, the default endpoint will be used."
|
||||
}
|
||||
|
||||
variable "internal_load_balancer" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Use an internal load balancer."
|
||||
}
|
||||
|
||||
variable "name_prefix" {
|
||||
type = string
|
||||
description = "Prefix for all resources."
|
||||
}
|
67
terraform/legacy-module/azure-constellation/main.tf
Normal file
67
terraform/legacy-module/azure-constellation/main.tf
Normal file
|
@ -0,0 +1,67 @@
|
|||
resource "null_resource" "ensure_yq" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
../common/install-yq.sh
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
module "fetch_image" {
|
||||
source = "../common/fetch-image"
|
||||
csp = "azure"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
image = var.image
|
||||
depends_on = [null_resource.ensure_yq]
|
||||
}
|
||||
|
||||
module "azure_iam" {
|
||||
source = "../../infrastructure/iam/azure"
|
||||
region = var.location
|
||||
service_principal_name = var.service_principal_name
|
||||
resource_group_name = var.resource_group_name
|
||||
}
|
||||
|
||||
module "azure" {
|
||||
source = "../../infrastructure/azure"
|
||||
name = var.name
|
||||
user_assigned_identity = module.azure_iam.uami_id
|
||||
node_groups = var.node_groups
|
||||
location = var.location
|
||||
image_id = module.fetch_image.image
|
||||
debug = var.debug
|
||||
resource_group = module.azure_iam.base_resource_group
|
||||
create_maa = var.create_maa
|
||||
}
|
||||
|
||||
module "constellation" {
|
||||
source = "../constellation-cluster"
|
||||
csp = "azure"
|
||||
debug = var.debug
|
||||
name = var.name
|
||||
image = var.image
|
||||
microservice_version = var.microservice_version
|
||||
kubernetes_version = var.kubernetes_version
|
||||
uid = module.azure.uid
|
||||
clusterEndpoint = module.azure.out_of_cluster_endpoint
|
||||
inClusterEndpoint = module.azure.in_cluster_endpoint
|
||||
initSecretHash = module.azure.initSecret
|
||||
ipCidrNode = module.azure.ip_cidr_nodes
|
||||
apiServerCertSANs = module.azure.api_server_cert_sans
|
||||
node_groups = var.node_groups
|
||||
azure_config = {
|
||||
subscription = module.azure_iam.subscription_id
|
||||
tenant = module.azure_iam.tenant_id
|
||||
location = var.location
|
||||
resourceGroup = module.azure.resource_group
|
||||
userAssignedIdentity = module.azure_iam.uami_id
|
||||
deployCSIDriver = var.deploy_csi_driver
|
||||
secureBoot = var.secure_boot
|
||||
maaURL = module.azure.attestationURL
|
||||
networkSecurityGroupName = module.azure.network_security_group_name
|
||||
loadBalancerName = module.azure.loadbalancer_name
|
||||
}
|
||||
depends_on = [null_resource.ensure_yq]
|
||||
}
|
89
terraform/legacy-module/azure-constellation/variables.tf
Normal file
89
terraform/legacy-module/azure-constellation/variables.tf
Normal file
|
@ -0,0 +1,89 @@
|
|||
variable "name" {
|
||||
type = string
|
||||
description = "Name of the Constellation cluster."
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
type = string
|
||||
description = "Node image reference or semantic release version. When not set, the latest default version will be used."
|
||||
default = "@@CONSTELLATION_VERSION@@"
|
||||
}
|
||||
|
||||
variable "microservice_version" {
|
||||
type = string
|
||||
description = "Microservice version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "kubernetes_version" {
|
||||
type = string
|
||||
description = "Kubernetes version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "debug" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "DON'T USE IN PRODUCTION: Enable debug mode and allow the use of debug images."
|
||||
}
|
||||
|
||||
variable "custom_endpoint" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Custom endpoint (DNS Name) to use for the Constellation API server. If not set, the default endpoint will be used."
|
||||
}
|
||||
|
||||
variable "internal_load_balancer" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Use an internal load balancer."
|
||||
}
|
||||
|
||||
variable "node_groups" {
|
||||
type = map(object({
|
||||
role = string
|
||||
initial_count = optional(number)
|
||||
instance_type = string
|
||||
disk_size = number
|
||||
disk_type = string
|
||||
zones = optional(list(string))
|
||||
}))
|
||||
description = "A map of node group names to node group configurations."
|
||||
validation {
|
||||
condition = can([for group in var.node_groups : group.role == "control-plane" || group.role == "worker"])
|
||||
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "service_principal_name" {
|
||||
type = string
|
||||
description = "Name of the service principal used to create the cluster."
|
||||
}
|
||||
|
||||
variable "resource_group_name" {
|
||||
type = string
|
||||
description = "Name of the resource group the cluster's resources are created in."
|
||||
}
|
||||
|
||||
variable "location" {
|
||||
type = string
|
||||
description = "Azure datacenter region the cluster will be deployed in."
|
||||
}
|
||||
|
||||
variable "deploy_csi_driver" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Deploy the Azure Disk CSI driver with on-node encryption into the cluster."
|
||||
}
|
||||
|
||||
variable "secure_boot" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob."
|
||||
}
|
||||
|
||||
variable "create_maa" {
|
||||
type = bool
|
||||
default = true
|
||||
description = "Create an MAA for attestation."
|
||||
}
|
48
terraform/legacy-module/common/fetch-image/.terraform.lock.hcl
generated
Normal file
48
terraform/legacy-module/common/fetch-image/.terraform.lock.hcl
generated
Normal file
|
@ -0,0 +1,48 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/local" {
|
||||
version = "2.4.0"
|
||||
hashes = [
|
||||
"h1:7RnIbO3CFakblTJs7o0mUiY44dc9xGYsLhSNFSNS1Ds=",
|
||||
"h1:Bs7LAkV/iQTLv72j+cTMrvx2U3KyXrcVHaGbdns1NcE=",
|
||||
"h1:OMqURhlP2IgLEgUCzSlaKXyb/IbnKForgDSjZF/NY4Y=",
|
||||
"h1:R97FTYETo88sT2VHfMgkPU3lzCsZLunPftjSI5vfKe8=",
|
||||
"h1:ZUEYUmm2t4vxwzxy1BvN1wL6SDWrDxfH7pxtzX8c6d0=",
|
||||
"zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9",
|
||||
"zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf",
|
||||
"zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35",
|
||||
"zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04",
|
||||
"zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406",
|
||||
"zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6",
|
||||
"zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7",
|
||||
"zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2",
|
||||
"zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc",
|
||||
"zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/null" {
|
||||
version = "3.2.1"
|
||||
hashes = [
|
||||
"h1:FbGfc+muBsC17Ohy5g806iuI1hQc4SIexpYCrQHQd8w=",
|
||||
"h1:tSj1mL6OQ8ILGqR2mDu7OYYYWf+hoir0pf9KAQ8IzO8=",
|
||||
"h1:vUW21lLLsKlxtBf0QF7LKJreKxs0CM7YXGzqW1N/ODY=",
|
||||
"h1:wqgRvlyVIbkCeCQs+5jj6zVuQL0KDxZZtNofGqqlSdI=",
|
||||
"h1:ydA0/SNRVB1o95btfshvYsmxA+jZFRZcvKzZSB+4S1M=",
|
||||
"zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840",
|
||||
"zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb",
|
||||
"zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5",
|
||||
"zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238",
|
||||
"zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc",
|
||||
"zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970",
|
||||
"zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2",
|
||||
"zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5",
|
||||
"zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f",
|
||||
"zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694",
|
||||
]
|
||||
}
|
38
terraform/legacy-module/common/fetch-image/main.tf
Normal file
38
terraform/legacy-module/common/fetch-image/main.tf
Normal file
|
@ -0,0 +1,38 @@
|
|||
locals {
|
||||
image_ref = startswith(var.image, "v") ? "ref/-/stream/stable/${var.image}" : var.image
|
||||
region_filter = var.region != "" ? " and .region == \"${var.region}\"" : "" # apply region filter only if region field exists for the CSP
|
||||
|
||||
fetch_image_command = <<EOT
|
||||
curl -s https://cdn.confidential.cloud/constellation/v2/${local.image_ref}/image/info.json | \
|
||||
./yq eval '.list[] | select(.csp == "${var.csp}" and .attestationVariant == "${var.attestation_variant}"${local.region_filter}) | .reference' - | tr -d '\n' > "image.txt"
|
||||
|
||||
if [ '${var.csp}' = 'azure' ]; then
|
||||
sed -i 's/CommunityGalleries/communityGalleries/g' image.txt
|
||||
sed -i 's/Images/images/g' image.txt
|
||||
sed -i 's/Versions/versions/g' image.txt
|
||||
fi
|
||||
EOT
|
||||
}
|
||||
|
||||
|
||||
resource "null_resource" "fetch_image" {
|
||||
provisioner "local-exec" {
|
||||
command = local.fetch_image_command
|
||||
|
||||
environment = {
|
||||
attestation_variant = var.attestation_variant
|
||||
}
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "rm image.txt"
|
||||
}
|
||||
triggers = {
|
||||
always_run = "${timestamp()}"
|
||||
}
|
||||
}
|
||||
|
||||
data "local_file" "image" {
|
||||
filename = "image.txt"
|
||||
depends_on = [null_resource.fetch_image]
|
||||
}
|
4
terraform/legacy-module/common/fetch-image/output.tf
Normal file
4
terraform/legacy-module/common/fetch-image/output.tf
Normal file
|
@ -0,0 +1,4 @@
|
|||
output "image" {
|
||||
description = "The resolved image ID of the CSP."
|
||||
value = data.local_file.image.content
|
||||
}
|
20
terraform/legacy-module/common/fetch-image/variables.tf
Normal file
20
terraform/legacy-module/common/fetch-image/variables.tf
Normal file
|
@ -0,0 +1,20 @@
|
|||
variable "csp" {
|
||||
description = "The cloud service provider to fetch image data for."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "attestation_variant" {
|
||||
description = "The attestation variant to fetch image data for."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "The region to fetch image data for."
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
description = "The image reference or semantical release version to fetch image data for."
|
||||
type = string
|
||||
}
|
43
terraform/legacy-module/common/install-yq.sh
Executable file
43
terraform/legacy-module/common/install-yq.sh
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env bash
|
||||
version="v4.35.2"
|
||||
if [[ -f ./yq ]] && ./yq --version | grep -q "${version}"; then
|
||||
echo "yq is already available and up to date."
|
||||
exit 0
|
||||
fi
|
||||
if [[ -f ./yq ]]; then
|
||||
echo "yq is already available but not at the required version. Replacing with ${version}."
|
||||
rm -f yq
|
||||
fi
|
||||
|
||||
echo "Fetching yq ${version}"
|
||||
os=$(uname -s)
|
||||
arch=$(uname -m)
|
||||
url=""
|
||||
|
||||
if [[ ${os} == "Darwin" ]]; then
|
||||
if [[ ${arch} == "arm64" ]]; then
|
||||
url="https://github.com/mikefarah/yq/releases/download/${version}/yq_darwin_arm64"
|
||||
elif [[ ${arch} == "x86_64" ]]; then
|
||||
url="https://github.com/mikefarah/yq/releases/download/${version}/yq_darwin_amd64"
|
||||
fi
|
||||
elif [[ ${os} == "Linux" ]]; then
|
||||
if [[ ${arch} == "x86_64" ]]; then
|
||||
url="https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_amd64"
|
||||
elif [[ ${arch} == "arm64" ]]; then
|
||||
url="https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_arm64"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z ${url} ]]; then
|
||||
echo "os \"${os}\" and/or architecture \"${arch}\" is not supported."
|
||||
exit 1
|
||||
else
|
||||
echo "Downloading yq from ${url}"
|
||||
curl -o yq -L "${url}"
|
||||
chmod +x ./yq
|
||||
./yq --version
|
||||
if ! ./yq --version | grep -q "${version}"; then # check that yq was installed correctly
|
||||
echo "Version is incorrect"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
25
terraform/legacy-module/constellation-cluster/.terraform.lock.hcl
generated
Normal file
25
terraform/legacy-module/constellation-cluster/.terraform.lock.hcl
generated
Normal file
|
@ -0,0 +1,25 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/null" {
|
||||
version = "3.2.1"
|
||||
hashes = [
|
||||
"h1:FbGfc+muBsC17Ohy5g806iuI1hQc4SIexpYCrQHQd8w=",
|
||||
"h1:tSj1mL6OQ8ILGqR2mDu7OYYYWf+hoir0pf9KAQ8IzO8=",
|
||||
"h1:vUW21lLLsKlxtBf0QF7LKJreKxs0CM7YXGzqW1N/ODY=",
|
||||
"h1:wqgRvlyVIbkCeCQs+5jj6zVuQL0KDxZZtNofGqqlSdI=",
|
||||
"h1:ydA0/SNRVB1o95btfshvYsmxA+jZFRZcvKzZSB+4S1M=",
|
||||
"zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840",
|
||||
"zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb",
|
||||
"zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5",
|
||||
"zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238",
|
||||
"zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc",
|
||||
"zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970",
|
||||
"zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2",
|
||||
"zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5",
|
||||
"zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f",
|
||||
"zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694",
|
||||
]
|
||||
}
|
34
terraform/legacy-module/constellation-cluster/install-constellation.sh
Executable file
34
terraform/legacy-module/constellation-cluster/install-constellation.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
if [[ -f ./constellation ]]; then
|
||||
echo "constellation CLI is already available."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
os=$(uname -s)
|
||||
arch=$(uname -m)
|
||||
version=$1
|
||||
url=""
|
||||
|
||||
echo "Fetching constellation ${version}"
|
||||
|
||||
if [[ ${os} == "Darwin" ]]; then
|
||||
if [[ ${arch} == "arm64" ]]; then
|
||||
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-darwin-arm64"
|
||||
elif [[ ${arch} == "x86_64" ]]; then
|
||||
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-darwin-amd64"
|
||||
fi
|
||||
elif [[ ${os} == "Linux" ]]; then
|
||||
if [[ ${arch} == "x86_64" ]]; then
|
||||
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-linux-amd64"
|
||||
elif [[ ${arch} == "arm64" ]]; then
|
||||
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-linux-arm64"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z ${url} ]]; then
|
||||
echo "os \"${os}\" and/or architecture \"${arch}\" is not supported."
|
||||
exit 1
|
||||
else
|
||||
curl -o constellation -L "${url}"
|
||||
chmod +x constellation
|
||||
fi
|
191
terraform/legacy-module/constellation-cluster/main.tf
Normal file
191
terraform/legacy-module/constellation-cluster/main.tf
Normal file
|
@ -0,0 +1,191 @@
|
|||
locals {
|
||||
yq_node_groups = join("\n", flatten([
|
||||
for name, group in var.node_groups : [
|
||||
"./yq eval '.nodeGroups.${name}.role = \"${group.role}\"' -i constellation-conf.yaml",
|
||||
"./yq eval '.nodeGroups.${name}.zone = \"${group.zone}\"' -i constellation-conf.yaml",
|
||||
"./yq eval '.nodeGroups.${name}.instanceType = \"${group.instance_type}\"' -i constellation-conf.yaml",
|
||||
"./yq eval '.nodeGroups.${name}.stateDiskSizeGB = ${group.disk_size}' -i constellation-conf.yaml",
|
||||
"./yq eval '.nodeGroups.${name}.stateDiskType = \"${group.disk_type}\"' -i constellation-conf.yaml",
|
||||
"./yq eval '.nodeGroups.${name}.initialCount = ${group.initial_count}' -i constellation-conf.yaml"
|
||||
]
|
||||
]))
|
||||
gcp_sa_file_path = "service_account_file.json"
|
||||
}
|
||||
|
||||
resource "null_resource" "ensure_cli" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
${path.module}/install-constellation.sh ${var.constellation_version}
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
// terraform_data resource so that it is run only once
|
||||
resource "terraform_data" "config_generate" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./constellation config generate ${var.csp}
|
||||
EOT
|
||||
}
|
||||
depends_on = [
|
||||
null_resource.ensure_cli
|
||||
]
|
||||
}
|
||||
|
||||
resource "null_resource" "aws_config" {
|
||||
count = var.aws_config != null ? 1 : 0
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./yq eval '.provider.aws.region = "${var.aws_config.region}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.aws.zone = "${var.aws_config.zone}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.aws.iamProfileControlPlane = "${var.aws_config.iam_instance_profile_control_plane}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.aws.iamProfileWorkerNodes = "${var.aws_config.iam_instance_profile_worker_nodes}"' -i constellation-conf.yaml
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
depends_on = [
|
||||
terraform_data.config_generate
|
||||
]
|
||||
}
|
||||
|
||||
resource "null_resource" "azure_config" {
|
||||
count = var.azure_config != null ? 1 : 0
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./yq eval '.provider.azure.subscription = "${var.azure_config.subscription}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.tenant = "${var.azure_config.tenant}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.location = "${var.azure_config.location}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.resourceGroup = "${var.azure_config.resourceGroup}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.userAssignedIdentity = "${var.azure_config.userAssignedIdentity}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.deployCSIDriver = ${var.azure_config.deployCSIDriver}' -i constellation-conf.yaml
|
||||
./yq eval '.provider.azure.secureBoot = ${var.azure_config.secureBoot}' -i constellation-conf.yaml
|
||||
./yq eval '.infrastructure.azure.resourceGroup = "${var.azure_config.resourceGroup}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.azure.subscriptionID = "${var.azure_config.subscription}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.azure.networkSecurityGroupName = "${var.azure_config.networkSecurityGroupName}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.azure.loadBalancerName = "${var.azure_config.loadBalancerName}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.azure.userAssignedIdentity = "${var.azure_config.userAssignedIdentity}"' -i constellation-state.yaml
|
||||
if [ '${var.azure_config.maaURL}' != '' ]; then
|
||||
./yq eval '.infrastructure.azure.attestationURL = "${var.azure_config.maaURL}"' -i constellation-state.yaml
|
||||
./constellation maa-patch ${var.azure_config.maaURL}
|
||||
fi
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
depends_on = [
|
||||
terraform_data.config_generate
|
||||
]
|
||||
}
|
||||
|
||||
resource "null_resource" "service_account_file" {
|
||||
count = var.gcp_config != null ? 1 : 0
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
echo ${var.gcp_config.serviceAccountKey} | base64 -d > "${local.gcp_sa_file_path}"
|
||||
EOT
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "rm ${self.triggers.file_path}"
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
file_path = local.gcp_sa_file_path
|
||||
}
|
||||
}
|
||||
|
||||
resource "null_resource" "gcp_config" {
|
||||
count = var.gcp_config != null ? 1 : 0
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./yq eval '.provider.gcp.project = "${var.gcp_config.project}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.gcp.region = "${var.gcp_config.region}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.gcp.zone = "${var.gcp_config.zone}"' -i constellation-conf.yaml
|
||||
./yq eval '.provider.gcp.serviceAccountKeyPath = "${local.gcp_sa_file_path}"' -i constellation-conf.yaml
|
||||
./yq eval '.infrastructure.gcp.projectID = "${var.gcp_config.project}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.gcp.ipCidrPod = "${var.gcp_config.ipCidrPod}"' -i constellation-state.yaml
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
depends_on = [
|
||||
terraform_data.config_generate, null_resource.service_account_file
|
||||
]
|
||||
}
|
||||
|
||||
resource "null_resource" "config" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./yq eval '.name = "${var.name}"' -i constellation-conf.yaml
|
||||
if [ "${var.image}" != "" ]; then
|
||||
./yq eval '.image = "${var.image}"' -i constellation-conf.yaml
|
||||
fi
|
||||
if [ "${var.kubernetes_version}" != "" ]; then
|
||||
./yq eval '.kubernetesVersion = "${var.kubernetes_version}"' -i constellation-conf.yaml
|
||||
fi
|
||||
if [ "${var.microservice_version}" != "" ]; then
|
||||
./yq eval '.microserviceVersion = "${var.microservice_version}"' -i constellation-conf.yaml
|
||||
fi
|
||||
if [ "${var.serviceCidr}" != "" ]; then
|
||||
./yq eval '.serviceCIDR = "${var.serviceCidr}"' -i constellation-conf.yaml
|
||||
fi
|
||||
${local.yq_node_groups}
|
||||
./constellation config fetch-measurements ${var.debug == true ? "--insecure" : ""}
|
||||
EOT
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
null_resource.aws_config, null_resource.gcp_config, null_resource.azure_config
|
||||
]
|
||||
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource "null_resource" "infra_state" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
./yq eval '.infrastructure.uid = "${var.uid}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.inClusterEndpoint = "${var.inClusterEndpoint}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.clusterEndpoint = "${var.clusterEndpoint}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.initSecret = "'"$(echo "${var.initSecretHash}" | tr -d '\n' | hexdump -ve '/1 "%02x"')"'"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.apiServerCertSANs = ${jsonencode(var.apiServerCertSANs)}' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.name = "${var.name}"' -i constellation-state.yaml
|
||||
./yq eval '.infrastructure.ipCidrNode = "${var.ipCidrNode}"' -i constellation-state.yaml
|
||||
EOT
|
||||
}
|
||||
depends_on = [
|
||||
terraform_data.config_generate
|
||||
]
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource "null_resource" "apply" {
|
||||
provisioner "local-exec" {
|
||||
command = "./constellation apply --debug --yes --skip-phases infrastructure"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "./constellation terminate --yes && rm constellation-conf.yaml constellation-mastersecret.json && rm -r constellation-upgrade"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
null_resource.infra_state, null_resource.config, null_resource.ensure_cli
|
||||
]
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
133
terraform/legacy-module/constellation-cluster/variables.tf
Normal file
133
terraform/legacy-module/constellation-cluster/variables.tf
Normal file
|
@ -0,0 +1,133 @@
|
|||
variable "constellation_version" {
|
||||
type = string
|
||||
description = "Constellation CLI version to use."
|
||||
default = "@@CONSTELLATION_VERSION@@"
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
type = string
|
||||
description = "The node image reference or semantic release version."
|
||||
}
|
||||
|
||||
variable "csp" {
|
||||
type = string
|
||||
description = "The cloud service provider to use."
|
||||
validation {
|
||||
condition = var.csp == "aws" || var.csp == "gcp" || var.csp == "azure"
|
||||
error_message = "The cloud service provider to use."
|
||||
}
|
||||
}
|
||||
|
||||
variable "node_groups" {
|
||||
type = map(object({
|
||||
role = string
|
||||
initial_count = optional(number)
|
||||
instance_type = string
|
||||
disk_size = number
|
||||
disk_type = string
|
||||
zone = optional(string, "") # For AWS, GCP
|
||||
zones = optional(list(string), []) # For Azure
|
||||
}))
|
||||
description = "A map of node group names to node group configurations."
|
||||
validation {
|
||||
condition = can([for group in var.node_groups : group.role == "control-plane" || group.role == "worker"])
|
||||
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
type = string
|
||||
description = "Name used in the cluster's named resources / cluster name."
|
||||
}
|
||||
|
||||
variable "uid" {
|
||||
type = string
|
||||
description = "The UID of the Constellation."
|
||||
}
|
||||
|
||||
variable "clusterEndpoint" {
|
||||
type = string
|
||||
description = "Endpoint of the cluster."
|
||||
}
|
||||
|
||||
variable "inClusterEndpoint" {
|
||||
type = string
|
||||
description = "The endpoint the cluster uses to reach itself. This might differ from the ClusterEndpoint in case e.g. an internal load balancer is used."
|
||||
}
|
||||
|
||||
variable "initSecretHash" {
|
||||
type = string
|
||||
description = "Init secret hash."
|
||||
}
|
||||
|
||||
variable "ipCidrNode" {
|
||||
type = string
|
||||
description = "Node IP CIDR."
|
||||
}
|
||||
|
||||
variable "serviceCidr" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Kubernetes service CIDR. This is only used during first initialization of Constellation."
|
||||
}
|
||||
|
||||
variable "apiServerCertSANs" {
|
||||
type = list(string)
|
||||
description = "List of additional SANs (Subject Alternative Names) for the Kubernetes API server certificate."
|
||||
}
|
||||
|
||||
variable "aws_config" {
|
||||
type = object({
|
||||
region = string
|
||||
zone = string
|
||||
iam_instance_profile_worker_nodes = string
|
||||
iam_instance_profile_control_plane = string
|
||||
})
|
||||
description = "The cluster config for AWS."
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "azure_config" {
|
||||
type = object({
|
||||
subscription = string
|
||||
tenant = string
|
||||
location = string
|
||||
resourceGroup = string
|
||||
userAssignedIdentity = string
|
||||
deployCSIDriver = bool
|
||||
secureBoot = bool
|
||||
maaURL = string
|
||||
networkSecurityGroupName = string
|
||||
loadBalancerName = string
|
||||
})
|
||||
description = "The cluster config for Azure."
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "gcp_config" {
|
||||
type = object({
|
||||
region = string
|
||||
zone = string
|
||||
project = string
|
||||
ipCidrPod = string
|
||||
serviceAccountKey = string
|
||||
})
|
||||
description = "The cluster config for GCP."
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "kubernetes_version" {
|
||||
type = string
|
||||
description = "Kubernetes version."
|
||||
}
|
||||
|
||||
variable "microservice_version" {
|
||||
type = string
|
||||
description = "Microservice version."
|
||||
}
|
||||
|
||||
variable "debug" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "DON'T USE IN PRODUCTION: Enable debug mode and allow the use of debug images."
|
||||
}
|
69
terraform/legacy-module/gcp-constellation/main.tf
Normal file
69
terraform/legacy-module/gcp-constellation/main.tf
Normal file
|
@ -0,0 +1,69 @@
|
|||
locals {
|
||||
region = substr(var.zone, 0, length(var.zone) - 2)
|
||||
}
|
||||
|
||||
module "gcp_iam" {
|
||||
source = "../../infrastructure/iam/gcp"
|
||||
project_id = var.project
|
||||
service_account_id = var.service_account_id
|
||||
region = local.region
|
||||
zone = var.zone
|
||||
}
|
||||
|
||||
|
||||
resource "null_resource" "ensure_yq" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
../common/install-yq.sh
|
||||
EOT
|
||||
}
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
module "fetch_image" {
|
||||
source = "../common/fetch-image"
|
||||
csp = "gcp"
|
||||
attestation_variant = "gcp-sev-es"
|
||||
image = var.image
|
||||
depends_on = [null_resource.ensure_yq]
|
||||
}
|
||||
|
||||
|
||||
module "gcp" {
|
||||
source = "../../infrastructure/gcp"
|
||||
project = var.project
|
||||
image_id = module.fetch_image.image
|
||||
name = var.name
|
||||
node_groups = var.node_groups
|
||||
region = local.region
|
||||
zone = var.zone
|
||||
debug = var.debug
|
||||
custom_endpoint = var.custom_endpoint
|
||||
}
|
||||
|
||||
module "constellation" {
|
||||
source = "../constellation-cluster"
|
||||
csp = "gcp"
|
||||
debug = var.debug
|
||||
name = var.name
|
||||
image = var.image
|
||||
microservice_version = var.microservice_version
|
||||
kubernetes_version = var.kubernetes_version
|
||||
uid = module.gcp.uid
|
||||
clusterEndpoint = module.gcp.out_of_cluster_endpoint
|
||||
inClusterEndpoint = module.gcp.in_cluster_endpoint
|
||||
initSecretHash = module.gcp.initSecret
|
||||
ipCidrNode = module.gcp.ip_cidr_nodes
|
||||
apiServerCertSANs = module.gcp.api_server_cert_sans
|
||||
node_groups = var.node_groups
|
||||
gcp_config = {
|
||||
region = local.region
|
||||
zone = var.zone
|
||||
project = var.project
|
||||
ipCidrPod = module.gcp.ip_cidr_pods
|
||||
serviceAccountKey = module.gcp_iam.sa_key
|
||||
}
|
||||
depends_on = [module.gcp, null_resource.ensure_yq]
|
||||
}
|
72
terraform/legacy-module/gcp-constellation/variables.tf
Normal file
72
terraform/legacy-module/gcp-constellation/variables.tf
Normal file
|
@ -0,0 +1,72 @@
|
|||
variable "name" {
|
||||
type = string
|
||||
description = "Name of the Constellation cluster."
|
||||
}
|
||||
|
||||
variable "project" {
|
||||
type = string
|
||||
description = "The project ID to deploy the cluster to."
|
||||
}
|
||||
|
||||
variable "service_account_id" {
|
||||
type = string
|
||||
description = "The service account ID to use for the cluster."
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
type = string
|
||||
description = "Node image reference or semantic release version. When not set, the latest default version will be used."
|
||||
default = "@@CONSTELLATION_VERSION@@"
|
||||
}
|
||||
|
||||
variable "microservice_version" {
|
||||
type = string
|
||||
description = "Microservice version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "kubernetes_version" {
|
||||
type = string
|
||||
description = "Kubernetes version. When not set, the latest default version will be used."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "node_groups" {
|
||||
type = map(object({
|
||||
role = string
|
||||
initial_count = optional(number)
|
||||
instance_type = string
|
||||
disk_size = number
|
||||
disk_type = string
|
||||
zone = string
|
||||
}))
|
||||
description = "A map of node group names to node group configurations."
|
||||
validation {
|
||||
condition = can([for group in var.node_groups : group.role == "control-plane" || group.role == "worker"])
|
||||
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
type = string
|
||||
description = "The availability zone name to create the cluster in."
|
||||
}
|
||||
|
||||
variable "debug" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "DON'T USE IN PRODUCTION: Enable debug mode and allow the use of debug images."
|
||||
}
|
||||
|
||||
|
||||
variable "custom_endpoint" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Custom endpoint (DNS Name) to use for the Constellation API server. If not set, the default endpoint will be used."
|
||||
}
|
||||
|
||||
variable "internal_load_balancer" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Use an internal load balancer."
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue