mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
terraform: add Terraform module for Azure (#2566)
* add Azure Terraform module * add maa-patching command to cli * refactor release process * factor out image fetching to own action * add CI * generate * fix some unnecessary changes Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * use `constellation maa-patch` in ci * insecure flag when using debug image Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * only update maa url if existing Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * make node group zone optional on aws and gcp Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * [remove] register updated workflow Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * Revert "[remove] register updated workflow" This reverts commit e70b9515b7eabbcbe0d41fa1296c48750cd02ace. * create MAA Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * make maa-patching only run on azure Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * add comment Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * require node group zone for GCP and AWS * remove unnecessary bazel action * stamp version to correct file * refer to `maa-patch` command in docs * run Azure test in weekly e2e * comment / naming improvements * remove sa_account resource * disable spellcheck ot use "URL" * `create_maa` variable * don't write maa url to config Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * default to nightly image * use input ref and stream * fix command check * don't set region in weekly e2e call * patch maa if url is not empty Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * remove `create_maa` variable * remove binaries Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * remove undefined input * replace invalid attestation URL error message Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com> * fix punctuation Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com> * skip hidden commands in clidocgen Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * enable spellcheck before code block * move spellcheck trigger out of info block Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * fix workflow dependencies * let image default to CLI version --------- Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>
This commit is contained in:
parent
e8f0c58558
commit
8e4feb7e2a
69
.github/actions/find_latest_image/action.yml
vendored
Normal file
69
.github/actions/find_latest_image/action.yml
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
name: Find latest image
|
||||||
|
description: 'Find the latest image reference for a given ref/stream.'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
git-ref:
|
||||||
|
description: 'Git ref to checkout.'
|
||||||
|
imageVersion:
|
||||||
|
description: 'Image version to use. If set, no image will be searched for and the specified image will be returned.'
|
||||||
|
ref:
|
||||||
|
description: 'The ref the image was built on. (e.g. "main")'
|
||||||
|
default: 'main'
|
||||||
|
stream:
|
||||||
|
description: 'The publication stream of the image. (e.g. "debug")'
|
||||||
|
default: 'debug'
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
image:
|
||||||
|
description: "Image reference to be used in the cluster."
|
||||||
|
value: ${{ steps.find-latest-image.outputs.output }}${{ steps.check-input.outputs.image }}
|
||||||
|
isDebugImage:
|
||||||
|
description: "Whether the image is a debug image."
|
||||||
|
value: ${{ steps.isDebugImage.outputs.isDebugImage }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Checkout head
|
||||||
|
if: inputs.imageVersion == '' && inputs.git-ref == 'head'
|
||||||
|
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||||
|
with:
|
||||||
|
ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }}
|
||||||
|
|
||||||
|
- name: Checkout ref
|
||||||
|
if: inputs.imageVersion == '' && inputs.git-ref != 'head'
|
||||||
|
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.git-ref }}
|
||||||
|
|
||||||
|
- name: Login to AWS
|
||||||
|
if: inputs.imageVersion == ''
|
||||||
|
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||||
|
with:
|
||||||
|
role-to-assume: arn:aws:iam::795746500882:role/GithubConstellationVersionsAPIRead
|
||||||
|
aws-region: eu-central-1
|
||||||
|
|
||||||
|
- name: Find latest image
|
||||||
|
id: find-latest-image
|
||||||
|
if: inputs.imageVersion == ''
|
||||||
|
uses: ./.github/actions/versionsapi
|
||||||
|
with:
|
||||||
|
command: latest
|
||||||
|
ref: ${{ inputs.ref }}
|
||||||
|
stream: ${{ inputs.stream }}
|
||||||
|
|
||||||
|
- name: Is debug image?
|
||||||
|
id: isDebugImage
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
case "${{ inputs.imageVersion }}" in
|
||||||
|
"")
|
||||||
|
echo "isDebugImage=true" | tee -a "$GITHUB_OUTPUT"
|
||||||
|
;;
|
||||||
|
*"/stream/debug/"*)
|
||||||
|
echo "isDebugImage=true" | tee -a "$GITHUB_OUTPUT"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "isDebugImage=false" | tee -a "$GITHUB_OUTPUT"
|
||||||
|
;;
|
||||||
|
esac
|
@ -84,7 +84,7 @@ runs:
|
|||||||
working-directory: ${{ github.workspace }}/e2e-infra
|
working-directory: ${{ github.workspace }}/e2e-infra
|
||||||
if: inputs.cloudProvider == 'azure'
|
if: inputs.cloudProvider == 'azure'
|
||||||
run: |
|
run: |
|
||||||
bazel run //hack/maa-patch:maa-patch $(terraform output attestationURL | jq -r)
|
./constellation maa-patch $(terraform output attestationURL | jq -r)
|
||||||
|
|
||||||
- name: Write outputs to state file
|
- name: Write outputs to state file
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
name: Upload Terraform module
|
name: Upload Terraform module
|
||||||
description: "Upload the Terraform module as an artifact."
|
description: "Upload the Terraform module as an artifact."
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "The Constellation CLI version to use in the Terraform Module. Leave empty when a built CLI is already present when applying the module."
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
@ -9,15 +14,23 @@ runs:
|
|||||||
cp -r terraform terraform-module
|
cp -r terraform terraform-module
|
||||||
find terraform-module -name "*.go" -type f -delete
|
find terraform-module -name "*.go" -type f -delete
|
||||||
find terraform-module -name "*.bazel" -type f -delete
|
find terraform-module -name "*.bazel" -type f -delete
|
||||||
|
|
||||||
|
- name: Stamp version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sed -i "s/@@CONSTELLATION_VERSION@@/${{ inputs.version }}/g" terraform-module/constellation-cluster/variables.tf
|
||||||
|
|
||||||
- name: Zip terraform dir
|
- name: Zip terraform dir
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
zip -r terraform-module.zip terraform-module
|
zip -r terraform-module.zip terraform-module
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||||
with:
|
with:
|
||||||
name: terraform-module
|
name: terraform-module
|
||||||
path: terraform-module.zip
|
path: terraform-module.zip
|
||||||
|
|
||||||
- name: Cleanup Terraform module dir
|
- name: Cleanup Terraform module dir
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
107
.github/workflows/e2e-test-tf-module.yml
vendored
107
.github/workflows/e2e-test-tf-module.yml
vendored
@ -6,32 +6,28 @@ on:
|
|||||||
ref:
|
ref:
|
||||||
type: string
|
type: string
|
||||||
description: "Git ref to checkout"
|
description: "Git ref to checkout"
|
||||||
required: false
|
|
||||||
cloudProvider:
|
cloudProvider:
|
||||||
description: "Which cloud provider to use."
|
description: "Which cloud provider to use."
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
- "aws"
|
- "aws"
|
||||||
|
- "azure"
|
||||||
- "gcp"
|
- "gcp"
|
||||||
required: true
|
required: true
|
||||||
regionZone:
|
regionZone:
|
||||||
description: "Region or zone to create the cluster in. Leave empty for default region/zone."
|
description: "Region or zone to create the cluster in. Leave empty for default region/zone."
|
||||||
type: string
|
type: string
|
||||||
image:
|
image:
|
||||||
description: "Node image version of the cluster."
|
description: "OS Image version used in the cluster's VMs, as specified in the Constellation config. If not set, the latest nightly image from main is used."
|
||||||
type: string
|
type: string
|
||||||
required: true
|
|
||||||
cliVersion:
|
cliVersion:
|
||||||
description: "Constellation CLI version to use. Empty value means build from source."
|
description: "Constellation CLI version to use. Empty value means build from source."
|
||||||
type: string
|
type: string
|
||||||
default: ""
|
|
||||||
required: false
|
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
ref:
|
ref:
|
||||||
type: string
|
type: string
|
||||||
description: "Git ref to checkout"
|
description: "Git ref to checkout"
|
||||||
required: false
|
|
||||||
cloudProvider:
|
cloudProvider:
|
||||||
description: "Which cloud provider to use."
|
description: "Which cloud provider to use."
|
||||||
type: string
|
type: string
|
||||||
@ -40,16 +36,14 @@ on:
|
|||||||
description: "Which zone to use."
|
description: "Which zone to use."
|
||||||
type: string
|
type: string
|
||||||
image:
|
image:
|
||||||
description: "Node image reference which is compatible with the current dev release version."
|
description: "OS Image version used in the cluster's VMs, as specified in the Constellation config. If not set, the latest nightly image from main is used."
|
||||||
type: string
|
type: string
|
||||||
required: true
|
|
||||||
cliVersion:
|
cliVersion:
|
||||||
description: "Constellation CLI version to use. Empty value means build from source."
|
description: "Constellation CLI version to use. Empty value means build from source."
|
||||||
type: string
|
type: string
|
||||||
default: ""
|
|
||||||
required: false
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
tf-module-test:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
@ -62,16 +56,30 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ inputs.ref || github.head_ref }}
|
ref: ${{ inputs.ref || github.head_ref }}
|
||||||
|
|
||||||
- name: Upload module
|
- name: Get Latest Image
|
||||||
|
id: find-latest-image
|
||||||
|
uses: ./.github/actions/find_latest_image
|
||||||
|
with:
|
||||||
|
git-ref: ${{ inputs.ref }}
|
||||||
|
imageVersion: ${{ inputs.image }}
|
||||||
|
ref: main
|
||||||
|
stream: nightly
|
||||||
|
|
||||||
|
- name: Upload Terraform module
|
||||||
uses: ./.github/actions/upload_terraform_module
|
uses: ./.github/actions/upload_terraform_module
|
||||||
|
with:
|
||||||
|
version: ${{ inputs.cliVersion }}
|
||||||
|
|
||||||
- name: Download Terraform module
|
- name: Download Terraform module
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||||
with:
|
with:
|
||||||
name: terraform-module
|
name: terraform-module
|
||||||
|
|
||||||
- name: Unzip Terraform module
|
- name: Unzip Terraform module
|
||||||
run: unzip terraform-module.zip
|
shell: bash
|
||||||
|
run: |
|
||||||
|
unzip terraform-module.zip -d ${{ github.workspace }}
|
||||||
|
rm terraform-module.zip
|
||||||
|
|
||||||
- name: Create resource prefix
|
- name: Create resource prefix
|
||||||
id: create-prefix
|
id: create-prefix
|
||||||
@ -83,29 +91,62 @@ jobs:
|
|||||||
|
|
||||||
- name: Create AWS Terraform variable input file
|
- name: Create AWS Terraform variable input file
|
||||||
if: inputs.cloudProvider == 'aws'
|
if: inputs.cloudProvider == 'aws'
|
||||||
working-directory: ./terraform-module/aws-constellation
|
working-directory: ${{ github.workspace }}/terraform-module/aws-constellation
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cat > terraform.tfvars <<EOF
|
cat > terraform.tfvars <<EOF
|
||||||
name = "${{ steps.create-prefix.outputs.prefix }}"
|
name = "${{ steps.create-prefix.outputs.prefix }}"
|
||||||
image = "${{ inputs.image }}"
|
image = "${{ steps.find-latest-image.outputs.image }}"
|
||||||
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
||||||
name_prefix = "${{ steps.create-prefix.outputs.prefix }}"
|
name_prefix = "${{ steps.create-prefix.outputs.prefix }}"
|
||||||
|
debug = ${{ steps.find-latest-image.outputs.isDebugImage }}
|
||||||
node_groups = {
|
node_groups = {
|
||||||
control_plane_default = {
|
control_plane_default = {
|
||||||
role = "control-plane"
|
role = "control-plane"
|
||||||
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
|
||||||
instance_type = "m6a.xlarge"
|
instance_type = "m6a.xlarge"
|
||||||
disk_size = 30
|
disk_size = 30
|
||||||
disk_type = "gp3"
|
disk_type = "gp3"
|
||||||
initial_count = 2
|
initial_count = 2
|
||||||
|
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
||||||
},
|
},
|
||||||
worker_default = {
|
worker_default = {
|
||||||
role = "worker"
|
role = "worker"
|
||||||
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
|
||||||
instance_type = "m6a.xlarge"
|
instance_type = "m6a.xlarge"
|
||||||
disk_size = 30
|
disk_size = 30
|
||||||
disk_type = "gp3"
|
disk_type = "gp3"
|
||||||
initial_count = 2
|
initial_count = 2
|
||||||
|
zone = "${{ inputs.regionZone || 'us-east-2c' }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cat terraform.tfvars
|
||||||
|
|
||||||
|
- name: Create Azure Terraform variable input file
|
||||||
|
if: inputs.cloudProvider == 'azure'
|
||||||
|
working-directory: ${{ github.workspace }}/terraform-module/azure-constellation
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cat > terraform.tfvars <<EOF
|
||||||
|
name = "${{ steps.create-prefix.outputs.prefix }}"
|
||||||
|
image = "${{ steps.find-latest-image.outputs.image }}"
|
||||||
|
location = "${{ inputs.regionZone || 'northeurope' }}"
|
||||||
|
service_principal_name = "${{ steps.create-prefix.outputs.prefix }}-sp"
|
||||||
|
resource_group_name = "${{ steps.create-prefix.outputs.prefix }}-rg"
|
||||||
|
debug = ${{ steps.find-latest-image.outputs.isDebugImage }}
|
||||||
|
node_groups = {
|
||||||
|
control_plane_default = {
|
||||||
|
role = "control-plane"
|
||||||
|
instance_type = "Standard_DC4as_v5"
|
||||||
|
disk_size = 30
|
||||||
|
disk_type = "Premium_LRS"
|
||||||
|
initial_count = 2
|
||||||
|
},
|
||||||
|
worker_default = {
|
||||||
|
role = "worker"
|
||||||
|
instance_type = "Standard_DC4as_v5"
|
||||||
|
disk_size = 30
|
||||||
|
disk_type = "Premium_LRS"
|
||||||
|
initial_count = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@ -113,36 +154,39 @@ jobs:
|
|||||||
|
|
||||||
- name: Create GCP Terraform variable input file
|
- name: Create GCP Terraform variable input file
|
||||||
if: inputs.cloudProvider == 'gcp'
|
if: inputs.cloudProvider == 'gcp'
|
||||||
working-directory: ./terraform-module/gcp-constellation
|
working-directory: ${{ github.workspace }}/terraform-module/gcp-constellation
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cat > terraform.tfvars <<EOF
|
cat > terraform.tfvars <<EOF
|
||||||
name = "${{ steps.create-prefix.outputs.prefix }}"
|
name = "${{ steps.create-prefix.outputs.prefix }}"
|
||||||
project = "${{ secrets.GCP_E2E_PROJECT }}"
|
project = "${{ secrets.GCP_E2E_PROJECT }}"
|
||||||
service_account_id = "${{ steps.create-prefix.outputs.prefix }}-sa"
|
service_account_id = "${{ steps.create-prefix.outputs.prefix }}-sa"
|
||||||
image = "${{ inputs.image }}"
|
image = "${{ steps.find-latest-image.outputs.image }}"
|
||||||
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
||||||
|
debug = ${{ steps.find-latest-image.outputs.isDebugImage }}
|
||||||
node_groups = {
|
node_groups = {
|
||||||
control_plane_default = {
|
control_plane_default = {
|
||||||
role = "control-plane"
|
role = "control-plane"
|
||||||
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
|
||||||
instance_type = "n2d-standard-4"
|
instance_type = "n2d-standard-4"
|
||||||
disk_size = 30
|
disk_size = 30
|
||||||
disk_type = "pd-ssd"
|
disk_type = "pd-ssd"
|
||||||
initial_count = 2
|
initial_count = 2
|
||||||
|
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
||||||
},
|
},
|
||||||
worker_default = {
|
worker_default = {
|
||||||
role = "worker"
|
role = "worker"
|
||||||
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
|
||||||
instance_type = "n2d-standard-4"
|
instance_type = "n2d-standard-4"
|
||||||
disk_size = 30
|
disk_size = 30
|
||||||
disk_type = "pd-ssd"
|
disk_type = "pd-ssd"
|
||||||
initial_count = 2
|
initial_count = 2
|
||||||
|
zone = "${{ inputs.regionZone || 'europe-west3-b' }}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
cat terraform.tfvars
|
cat terraform.tfvars
|
||||||
|
|
||||||
- name: Install dependencies (Terraform)
|
- name: Install dependencies (Terraform)
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt update && sudo apt install gpg
|
sudo apt update && sudo apt install gpg
|
||||||
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
||||||
@ -178,7 +222,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -fsSL -o constellation https://github.com/edgelesssys/constellation/releases/download/${{ inputs.cliVersion }}/constellation-linux-amd64
|
curl -fsSL -o constellation https://github.com/edgelesssys/constellation/releases/download/${{ inputs.cliVersion }}/constellation-linux-amd64
|
||||||
chmod u+x ./constellation
|
chmod u+x constellation
|
||||||
./constellation version
|
./constellation version
|
||||||
sudo sh -c 'echo "127.0.0.1 license.confidential.cloud" >> /etc/hosts'
|
sudo sh -c 'echo "127.0.0.1 license.confidential.cloud" >> /etc/hosts'
|
||||||
|
|
||||||
@ -191,6 +235,12 @@ jobs:
|
|||||||
# extend token expiry to 6 hours to ensure constellation can terminate
|
# extend token expiry to 6 hours to ensure constellation can terminate
|
||||||
role-duration-seconds: 21600
|
role-duration-seconds: 21600
|
||||||
|
|
||||||
|
- name: Login to Azure (IAM + Cluster service principal)
|
||||||
|
if: inputs.cloudProvider == 'azure'
|
||||||
|
uses: ./.github/actions/login_azure
|
||||||
|
with:
|
||||||
|
azure_credentials: ${{ secrets.AZURE_E2E_TF_CREDENTIALS }}
|
||||||
|
|
||||||
- name: Login to GCP (IAM + Cluster service account)
|
- name: Login to GCP (IAM + Cluster service account)
|
||||||
if: inputs.cloudProvider == 'gcp'
|
if: inputs.cloudProvider == 'gcp'
|
||||||
uses: ./.github/actions/login_gcp
|
uses: ./.github/actions/login_gcp
|
||||||
@ -199,22 +249,25 @@ jobs:
|
|||||||
|
|
||||||
- name: Apply Terraform Cluster
|
- name: Apply Terraform Cluster
|
||||||
id: apply_terraform
|
id: apply_terraform
|
||||||
working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation
|
working-directory: ${{ github.workspace }}/terraform-module/${{ inputs.cloudProvider }}-constellation
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cp ../../constellation .
|
cp ../../constellation .
|
||||||
terraform init
|
terraform init
|
||||||
terraform apply -var-file=terraform.tfvars -auto-approve
|
terraform apply -var-file=terraform.tfvars -auto-approve
|
||||||
|
|
||||||
- name: Destroy Terraform Cluster
|
- name: Destroy Terraform Cluster
|
||||||
# outcome is part of the steps context (https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context)
|
# outcome is part of the steps context (https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context)
|
||||||
if: always() && steps.apply_terraform.outcome != 'skipped'
|
if: always() && steps.apply_terraform.outcome != 'skipped'
|
||||||
working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation
|
working-directory: ${{ github.workspace }}/terraform-module/${{ inputs.cloudProvider }}-constellation
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
terraform init
|
terraform init
|
||||||
terraform destroy -var-file=terraform.tfvars -auto-approve
|
terraform destroy -var-file=terraform.tfvars -auto-approve
|
||||||
|
|
||||||
- name: Verify cleanup
|
- name: Verify cleanup
|
||||||
working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation
|
working-directory: ${{ github.workspace }}/terraform-module/${{ inputs.cloudProvider }}-constellation
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ -f constellation-mastersecret.json ] || [ -f constellation-conf.yaml ]; then
|
if [ -f constellation-mastersecret.json ] || [ -f constellation-conf.yaml ]; then
|
||||||
echo "Files constellation-mastersecret.json or constellation-conf.yaml still exist"
|
echo "Files constellation-mastersecret.json or constellation-conf.yaml still exist"
|
||||||
|
12
.github/workflows/e2e-test-weekly.yml
vendored
12
.github/workflows/e2e-test-weekly.yml
vendored
@ -376,20 +376,14 @@ jobs:
|
|||||||
max-parallel: 5
|
max-parallel: 5
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- test: "GCP"
|
- provider: "gcp"
|
||||||
provider: "gcp"
|
- provider: "aws"
|
||||||
regionZone: "europe-west2-a"
|
- provider: "azure"
|
||||||
- test: "AWS"
|
|
||||||
provider: "aws"
|
|
||||||
regionZone: "us-east-2c"
|
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
needs: [find-latest-image]
|
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
uses: ./.github/workflows/e2e-test-tf-module.yml
|
uses: ./.github/workflows/e2e-test-tf-module.yml
|
||||||
with:
|
with:
|
||||||
cloudProvider: "${{ matrix.provider }}"
|
cloudProvider: "${{ matrix.provider }}"
|
||||||
regionZone: "${{ matrix.regionZone }}"
|
|
||||||
image: ${{ needs.find-latest-image.outputs.image-main-nightly }}
|
|
||||||
|
58
.github/workflows/e2e-test.yml
vendored
58
.github/workflows/e2e-test.yml
vendored
@ -151,64 +151,18 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
image: ${{ steps.find-latest-image.outputs.output }}${{ steps.check-input.outputs.image }}
|
image: ${{ steps.find-latest-image.outputs.image }}
|
||||||
isDebugImage: ${{ steps.isDebugImage.outputs.isDebugImage }}
|
isDebugImage: ${{ steps.find-latest-image.outputs.isDebugImage }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check input
|
- name: Get Latest Image
|
||||||
id: check-input
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [[ -z "${{ inputs.imageVersion }}" ]]; then
|
|
||||||
echo "Using latest debug image from main."
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "image=${{ inputs.imageVersion }}" | tee -a "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Checkout head
|
|
||||||
if: inputs.imageVersion == '' && inputs.git-ref == 'head'
|
|
||||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
|
||||||
with:
|
|
||||||
ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }}
|
|
||||||
|
|
||||||
- name: Checkout ref
|
|
||||||
if: inputs.imageVersion == '' && inputs.git-ref != 'head'
|
|
||||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
|
||||||
with:
|
|
||||||
ref: ${{ inputs.git-ref }}
|
|
||||||
|
|
||||||
- name: Login to AWS
|
|
||||||
if: inputs.imageVersion == ''
|
|
||||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
|
||||||
with:
|
|
||||||
role-to-assume: arn:aws:iam::795746500882:role/GithubConstellationVersionsAPIRead
|
|
||||||
aws-region: eu-central-1
|
|
||||||
|
|
||||||
- name: Find latest image
|
|
||||||
id: find-latest-image
|
id: find-latest-image
|
||||||
if: inputs.imageVersion == ''
|
uses: ./.github/actions/find_latest_image
|
||||||
uses: ./.github/actions/versionsapi
|
|
||||||
with:
|
with:
|
||||||
command: latest
|
git-ref: ${{ inputs.git-ref }}
|
||||||
|
imageVersion: ${{ inputs.imageVersion }}
|
||||||
ref: main
|
ref: main
|
||||||
stream: debug
|
stream: debug
|
||||||
|
|
||||||
- name: Is debug image?
|
|
||||||
id: isDebugImage
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
case "${{ inputs.imageVersion }}" in
|
|
||||||
"")
|
|
||||||
echo "isDebugImage=true" | tee -a "$GITHUB_OUTPUT"
|
|
||||||
;;
|
|
||||||
*"/stream/debug/"*)
|
|
||||||
echo "isDebugImage=true" | tee -a "$GITHUB_OUTPUT"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "isDebugImage=false" | tee -a "$GITHUB_OUTPUT"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
e2e-test-manual:
|
e2e-test-manual:
|
||||||
runs-on: ${{ inputs.runner }}
|
runs-on: ${{ inputs.runner }}
|
||||||
permissions:
|
permissions:
|
||||||
|
20
.github/workflows/release-cli.yml
vendored
20
.github/workflows/release-cli.yml
vendored
@ -76,9 +76,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ inputs.ref || github.head_ref }}
|
ref: ${{ inputs.ref || github.head_ref }}
|
||||||
|
|
||||||
- name: Upload Terraform module
|
|
||||||
uses: ./.github/actions/upload_terraform_module
|
|
||||||
|
|
||||||
- name: Setup bazel
|
- name: Setup bazel
|
||||||
uses: ./.github/actions/setup_bazel_nix
|
uses: ./.github/actions/setup_bazel_nix
|
||||||
with:
|
with:
|
||||||
@ -112,6 +109,20 @@ jobs:
|
|||||||
build/constellation-${{ matrix.os }}-${{ matrix.arch }}.exe
|
build/constellation-${{ matrix.os }}-${{ matrix.arch }}.exe
|
||||||
build/constellation-${{ matrix.os }}-${{ matrix.arch }}.exe.sig
|
build/constellation-${{ matrix.os }}-${{ matrix.arch }}.exe.sig
|
||||||
|
|
||||||
|
upload-terraform-module:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
id: checkout
|
||||||
|
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.ref || github.head_ref }}
|
||||||
|
|
||||||
|
- name: Upload Terraform module
|
||||||
|
uses: ./.github/actions/upload_terraform_module
|
||||||
|
with:
|
||||||
|
version: ${{ inputs.versionName }}
|
||||||
|
|
||||||
push-containers:
|
push-containers:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
if: inputs.pushContainers
|
if: inputs.pushContainers
|
||||||
@ -148,6 +159,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-cli
|
- build-cli
|
||||||
- signed-sbom
|
- signed-sbom
|
||||||
|
- upload-terraform-module
|
||||||
outputs:
|
outputs:
|
||||||
provenance-subjects: ${{ steps.provenance-subjects.outputs.provenance-subjects }}
|
provenance-subjects: ${{ steps.provenance-subjects.outputs.provenance-subjects }}
|
||||||
steps:
|
steps:
|
||||||
@ -278,6 +290,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-cli
|
- build-cli
|
||||||
- provenance
|
- provenance
|
||||||
|
- upload-terraform-module
|
||||||
steps:
|
steps:
|
||||||
- name: Download CLI binaries darwin-amd64
|
- name: Download CLI binaries darwin-amd64
|
||||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||||
@ -356,6 +369,7 @@ jobs:
|
|||||||
- build-cli
|
- build-cli
|
||||||
- provenance
|
- provenance
|
||||||
- signed-sbom
|
- signed-sbom
|
||||||
|
- upload-terraform-module
|
||||||
steps:
|
steps:
|
||||||
- name: Write cosign public key
|
- name: Write cosign public key
|
||||||
run: echo "$COSIGN_PUBLIC_KEY" > cosign.pub
|
run: echo "$COSIGN_PUBLIC_KEY" > cosign.pub
|
||||||
|
@ -61,6 +61,7 @@ func NewRootCmd() *cobra.Command {
|
|||||||
rootCmd.AddCommand(cmd.NewIAMCmd())
|
rootCmd.AddCommand(cmd.NewIAMCmd())
|
||||||
rootCmd.AddCommand(cmd.NewVersionCmd())
|
rootCmd.AddCommand(cmd.NewVersionCmd())
|
||||||
rootCmd.AddCommand(cmd.NewInitCmd())
|
rootCmd.AddCommand(cmd.NewInitCmd())
|
||||||
|
rootCmd.AddCommand(cmd.NewMaaPatchCmd())
|
||||||
|
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ go_library(
|
|||||||
"iamupgradeapply.go",
|
"iamupgradeapply.go",
|
||||||
"init.go",
|
"init.go",
|
||||||
"log.go",
|
"log.go",
|
||||||
|
"maapatch.go",
|
||||||
"mini.go",
|
"mini.go",
|
||||||
"minidown.go",
|
"minidown.go",
|
||||||
"miniup.go",
|
"miniup.go",
|
||||||
@ -78,6 +79,7 @@ go_library(
|
|||||||
"//internal/kms/uri",
|
"//internal/kms/uri",
|
||||||
"//internal/license",
|
"//internal/license",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
|
"//internal/maa",
|
||||||
"//internal/retry",
|
"//internal/retry",
|
||||||
"//internal/semver",
|
"//internal/semver",
|
||||||
"//internal/sigstore",
|
"//internal/sigstore",
|
||||||
@ -129,6 +131,7 @@ go_test(
|
|||||||
"iamdestroy_test.go",
|
"iamdestroy_test.go",
|
||||||
"iamupgradeapply_test.go",
|
"iamupgradeapply_test.go",
|
||||||
"init_test.go",
|
"init_test.go",
|
||||||
|
"maapatch_test.go",
|
||||||
"recover_test.go",
|
"recover_test.go",
|
||||||
"spinner_test.go",
|
"spinner_test.go",
|
||||||
"status_test.go",
|
"status_test.go",
|
||||||
|
71
cli/internal/cmd/maapatch.go
Normal file
71
cli/internal/cmd/maapatch.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) Edgeless Systems GmbH
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/maa"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewMaaPatchCmd returns a new cobra.Command for the maa-patch command.
|
||||||
|
func NewMaaPatchCmd() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "maa-patch <attestation-url>",
|
||||||
|
Short: "Patch the MAA's attestation policy",
|
||||||
|
Long: "Patch the MAA's attestation policy.",
|
||||||
|
Args: cobra.MatchAll(
|
||||||
|
cobra.ExactArgs(1),
|
||||||
|
func(cmd *cobra.Command, args []string) error {
|
||||||
|
if _, err := url.Parse(args[0]); err != nil {
|
||||||
|
return fmt.Errorf("argument %s is not a valid URL: %w", args[0], err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RunE: runPatchMAA,
|
||||||
|
Hidden: true, // we don't want to show this command to the user directly.
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
type maaPatchCmd struct {
|
||||||
|
log debugLog
|
||||||
|
patcher patcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func runPatchMAA(cmd *cobra.Command, args []string) error {
|
||||||
|
log, err := newCLILogger(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
|
}
|
||||||
|
defer log.Sync()
|
||||||
|
|
||||||
|
p := maa.NewAzurePolicyPatcher()
|
||||||
|
|
||||||
|
c := &maaPatchCmd{log: log, patcher: p}
|
||||||
|
|
||||||
|
return c.patchMAA(cmd, args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *maaPatchCmd) patchMAA(cmd *cobra.Command, attestationURL string) error {
|
||||||
|
c.log.Debugf("Using attestation URL %s", attestationURL)
|
||||||
|
|
||||||
|
if err := c.patcher.Patch(cmd.Context(), attestationURL); err != nil {
|
||||||
|
return fmt.Errorf("patching MAA attestation policy: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type patcher interface {
|
||||||
|
Patch(ctx context.Context, attestationURL string) error
|
||||||
|
}
|
59
cli/internal/cmd/maapatch_test.go
Normal file
59
cli/internal/cmd/maapatch_test.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) Edgeless Systems GmbH
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMAAPatch(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
attestationURL string
|
||||||
|
patcher *stubPolicyPatcher
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
"success": {
|
||||||
|
attestationURL: "https://example.com",
|
||||||
|
patcher: &stubPolicyPatcher{},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
"patch error": {
|
||||||
|
attestationURL: "https://example.com",
|
||||||
|
patcher: &stubPolicyPatcher{patchErr: assert.AnError},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
c := &maaPatchCmd{log: logger.NewTest(t), patcher: tc.patcher}
|
||||||
|
err := c.patchMAA(&cobra.Command{}, tc.attestationURL)
|
||||||
|
if tc.wantErr {
|
||||||
|
require.Error(err)
|
||||||
|
} else {
|
||||||
|
require.NoError(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type stubPolicyPatcher struct {
|
||||||
|
patchErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch implements the patcher interface.
|
||||||
|
func (p *stubPolicyPatcher) Patch(context.Context, string) error {
|
||||||
|
return p.patchErr
|
||||||
|
}
|
@ -30,10 +30,6 @@ Releases should be performed using [the automated release pipeline](https://gith
|
|||||||
git push origin ${working_branch}
|
git push origin ${working_branch}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update CLI version for Terraform module
|
|
||||||
|
|
||||||
Update the `version` inside `terraform/constellation-cluster/install-constellation.sh` to the new release.
|
|
||||||
|
|
||||||
### Patch release
|
### Patch release
|
||||||
|
|
||||||
1. `cherry-pick` (only) the required commits from `main`
|
1. `cherry-pick` (only) the required commits from `main`
|
||||||
|
@ -249,19 +249,21 @@ To self-manage the infrastructure of your cluster, download the Terraform files
|
|||||||
They contain a minimum configuration for the resources necessary to run a Constellation cluster on the corresponding CSP. From this base, you can now add, edit, or substitute resources per your own requirements with the infrastructure
|
They contain a minimum configuration for the resources necessary to run a Constellation cluster on the corresponding CSP. From this base, you can now add, edit, or substitute resources per your own requirements with the infrastructure
|
||||||
management tooling of your choice. You need to keep the essential functionality of the base configuration in order for your cluster to function correctly.
|
management tooling of your choice. You need to keep the essential functionality of the base configuration in order for your cluster to function correctly.
|
||||||
|
|
||||||
|
<!-- vale off -->
|
||||||
|
|
||||||
:::info
|
:::info
|
||||||
|
|
||||||
On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary.
|
On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary.
|
||||||
You can apply the update with the following commands, where `<VERSION>` is the version of Constellation that should be set up. (e.g. `v2.12.0`)
|
You can apply the update with the following command after creating the infrastructure, with `<URL>` being the URL of the MAA provider (i.e., `$(terraform output attestationURL | jq -r)`, when using the minimal Terraform configuration).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone --branch <VERSION> https://github.com/edgelesssys/constellation
|
constellation maa-patch <URL>
|
||||||
cd constellation/hack/maa-patch
|
|
||||||
go run . $(terraform output attestationURL | jq -r)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
<!-- vale on -->
|
||||||
|
|
||||||
Make sure all necessary resources are created, e.g., through checking your CSP's portal and retrieve the necessary values, aligned with the outputs (specified in `outputs.tf`) of the base configuration.
|
Make sure all necessary resources are created, e.g., through checking your CSP's portal and retrieve the necessary values, aligned with the outputs (specified in `outputs.tf`) of the base configuration.
|
||||||
|
|
||||||
Fill these outputs into the corresponding fields of the `constellation-state.yaml` file. For example, fill the IP or DNS name your cluster can be reached at into the `.Infrastructure.ClusterEndpoint` field.
|
Fill these outputs into the corresponding fields of the `constellation-state.yaml` file. For example, fill the IP or DNS name your cluster can be reached at into the `.Infrastructure.ClusterEndpoint` field.
|
||||||
|
@ -28,6 +28,9 @@ func main() {
|
|||||||
cmdList := &bytes.Buffer{}
|
cmdList := &bytes.Buffer{}
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
for _, c := range allSubCommands(rootCmd) {
|
for _, c := range allSubCommands(rootCmd) {
|
||||||
|
if c.Hidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
name := c.Name()
|
name := c.Name()
|
||||||
fullName, level := determineFullNameAndLevel(c)
|
fullName, level := determineFullNameAndLevel(c)
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
|
||||||
load("//bazel/go:go_test.bzl", "go_test")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "maa-patch_lib",
|
|
||||||
srcs = ["main.go"],
|
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/hack/maa-patch",
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
deps = ["//internal/maa"],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_binary(
|
|
||||||
name = "maa-patch",
|
|
||||||
embed = [":maa-patch_lib"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "maa-patch_test",
|
|
||||||
srcs = ["main_test.go"],
|
|
||||||
embed = [":maa-patch_lib"],
|
|
||||||
)
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/maa"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s <attestation-url>\n", os.Args[0])
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
attestationURL := os.Args[1]
|
|
||||||
if _, err := url.Parse(attestationURL); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Invalid attestation URL: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := maa.NewAzurePolicyPatcher()
|
|
||||||
if err := p.Patch(context.Background(), attestationURL); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestNop(t *testing.T) {
|
|
||||||
t.Skip("This is a nop-test to catch build-time errors in this package.")
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ module "aws_iam" {
|
|||||||
resource "null_resource" "ensure_yq" {
|
resource "null_resource" "ensure_yq" {
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
command = <<EOT
|
command = <<EOT
|
||||||
../constellation-cluster/install-yq.sh
|
../common/install-yq.sh
|
||||||
EOT
|
EOT
|
||||||
}
|
}
|
||||||
triggers = {
|
triggers = {
|
||||||
@ -21,7 +21,7 @@ resource "null_resource" "ensure_yq" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module "fetch_image" {
|
module "fetch_image" {
|
||||||
source = "../fetch-image"
|
source = "../common/fetch-image"
|
||||||
csp = "aws"
|
csp = "aws"
|
||||||
attestation_variant = var.enable_snp ? "aws-sev-snp" : "aws-nitro-tpm"
|
attestation_variant = var.enable_snp ? "aws-sev-snp" : "aws-nitro-tpm"
|
||||||
region = local.region
|
region = local.region
|
||||||
@ -47,6 +47,7 @@ module "aws" {
|
|||||||
module "constellation" {
|
module "constellation" {
|
||||||
source = "../constellation-cluster"
|
source = "../constellation-cluster"
|
||||||
csp = "aws"
|
csp = "aws"
|
||||||
|
debug = var.debug
|
||||||
name = var.name
|
name = var.name
|
||||||
image = var.image
|
image = var.image
|
||||||
microservice_version = var.microservice_version
|
microservice_version = var.microservice_version
|
||||||
|
@ -5,7 +5,7 @@ variable "name" {
|
|||||||
|
|
||||||
variable "image" {
|
variable "image" {
|
||||||
type = string
|
type = string
|
||||||
description = "Node image reference or semantical release version. The field is required to resolve the AMI."
|
description = "Node image reference or semantic release version."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "microservice_version" {
|
variable "microservice_version" {
|
||||||
|
143
terraform/azure-constellation/.terraform.lock.hcl
Normal file
143
terraform/azure-constellation/.terraform.lock.hcl
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# This file is maintained automatically by "terraform init".
|
||||||
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
|
provider "registry.terraform.io/hashicorp/azuread" {
|
||||||
|
version = "2.43.0"
|
||||||
|
constraints = "2.43.0"
|
||||||
|
hashes = [
|
||||||
|
"h1:/wPCaaEC7By9zWMxYmPMiLNu+zuYuFUyl5mkhCwwi8w=",
|
||||||
|
"h1:83hGDTWccRJXsKGg1VeYJkBeHwE2cCTRKFCZud4iWQo=",
|
||||||
|
"h1:bp9HeofaEJDiWtyLMwIEYVgxP5yoMs/dQhjCYsbXU34=",
|
||||||
|
"h1:jmvCGhwc+jUip0Hy4PI1ZiO/11vdQ3TTp3YaBTKFGiQ=",
|
||||||
|
"h1:tU/kGFohqNia+uVFT1ujYKZRH2lvEP73LUhQDJtO1w4=",
|
||||||
|
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
|
||||||
|
"zh:2225e2e97ccba4ed1d84f1d430f1ebd837943fe187e57f24f1763172dda61556",
|
||||||
|
"zh:24708cb09411a766ff397e05cae49058ca38edc718db303a7faef9823402737d",
|
||||||
|
"zh:3a61167ff58d585abd56233731a8fd649c7c04272bd5b878f963883496e19192",
|
||||||
|
"zh:433f557634b5e663caaeb68c504c7771c186eba7ecf5d4030437956bc6599ecb",
|
||||||
|
"zh:5e8cc3b3bcc22d217cf588c821ce091c7d40f0815aecc1addde5355c17cb381d",
|
||||||
|
"zh:7b008c376097cd60259d43f58fcb33fee56fe9aebb4a94ed7958868ee501d7d0",
|
||||||
|
"zh:908907fd38537583ea60dccbf73055ae1a2963acc399be4f8e9a6616a9a537db",
|
||||||
|
"zh:966586cfd850606bab7dd2242c5b9e35d3a7178f64eaac0b44dea54c104c8169",
|
||||||
|
"zh:a624286401913d3ec44b4825e2c5ae38ac94fb4950aeed8f4b91d09c898f8cce",
|
||||||
|
"zh:b5171a4463fd0d9b0ce2a08605499b6d99fe93d6fc3f4143e9a26201065cc90a",
|
||||||
|
"zh:cdcfeeb9db4dbdc6f1fb5644453b37dbd0025b4f3127e9ff348f1e62d66b493e",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||||
|
version = "3.74.0"
|
||||||
|
constraints = "3.74.0"
|
||||||
|
hashes = [
|
||||||
|
"h1:4b15khHtc5OkIVEFg0W5QRwf/ov1WVQkXVdSiAcTCS8=",
|
||||||
|
"h1:ETVZfmulZQ435+lgFCkZRpfVOLyAxfDOwbPXFg3aLLQ=",
|
||||||
|
"h1:H3diAufZ5VDQKsQNYykVRaFTOUJ4gjFiT2VLYi574+w=",
|
||||||
|
"h1:LEdK8BxNSNiBQbtcJhQZKMMHDjmPpUsvDpr3Mzs93Tg=",
|
||||||
|
"h1:VfBB00BE0wvFiod7BlL+Cn6r2599MEi94hnAQ277ux8=",
|
||||||
|
"zh:0424c70152f949da1ec52ba96d20e5fd32fd22d9bd9203ce045d5f6aab3d20fc",
|
||||||
|
"zh:16dbf581d10f8e7937185bcdcceb4f91d08c919e452fb8da7580071288c8c397",
|
||||||
|
"zh:3019103bc2c3b4e185f5c65696c349697644c968f5c085af5505fed6d01c4241",
|
||||||
|
"zh:49bb56ebaed6653fdb913c2b2bb74fc8b5399e7258d1e89084f72c44ea1130dd",
|
||||||
|
"zh:85547666517f899d88620bd23a000a8f43c7dc93587c350eb1ea17bcb3e645c7",
|
||||||
|
"zh:8bed8b646ff1822d8764de68b56b71e5dd971a4b77eba80d47f400a530800bea",
|
||||||
|
"zh:8bfa6c70c004ba05ebce47f74f49ce872c28a68a18bb71b281a9681bcbbdbfa1",
|
||||||
|
"zh:a2ae9e38fda0695fb8aa810e4f1ce4b104bfda651a87923b307bb1728680d8b6",
|
||||||
|
"zh:beac1efe32f99072c892095f5ff46e40d6852b66679a03bc3acbe1b90fb1f653",
|
||||||
|
"zh:d8a6ca20e49ebe7ea5688d91233d571e2c2ccc3e41000c39a7d7031df209ea8e",
|
||||||
|
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||||
|
"zh:f937b5fdf49b072c0347408d0a1c5a5d822dae1a23252915930e5a82d1d8ce8b",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "registry.terraform.io/hashicorp/random" {
|
||||||
|
version = "3.5.1"
|
||||||
|
constraints = "3.5.1"
|
||||||
|
hashes = [
|
||||||
|
"h1:3hjTP5tQBspPcFAJlfafnWrNrKnr7J4Cp0qB9jbqf30=",
|
||||||
|
"h1:6FVyQ/aG6tawPam6B+oFjgdidKd83uG9n7dOSQ66HBA=",
|
||||||
|
"h1:IL9mSatmwov+e0+++YX2V6uel+dV6bn+fC/cnGDK3Ck=",
|
||||||
|
"h1:VSnd9ZIPyfKHOObuQCaKfnjIHRtR7qTw19Rz8tJxm+k=",
|
||||||
|
"h1:sZ7MTSD4FLekNN2wSNFGpM+5slfvpm5A/NLVZiB7CO0=",
|
||||||
|
"zh:04e3fbd610cb52c1017d282531364b9c53ef72b6bc533acb2a90671957324a64",
|
||||||
|
"zh:119197103301ebaf7efb91df8f0b6e0dd31e6ff943d231af35ee1831c599188d",
|
||||||
|
"zh:4d2b219d09abf3b1bb4df93d399ed156cadd61f44ad3baf5cf2954df2fba0831",
|
||||||
|
"zh:6130bdde527587bbe2dcaa7150363e96dbc5250ea20154176d82bc69df5d4ce3",
|
||||||
|
"zh:6cc326cd4000f724d3086ee05587e7710f032f94fc9af35e96a386a1c6f2214f",
|
||||||
|
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||||
|
"zh:b6d88e1d28cf2dfa24e9fdcc3efc77adcdc1c3c3b5c7ce503a423efbdd6de57b",
|
||||||
|
"zh:ba74c592622ecbcef9dc2a4d81ed321c4e44cddf7da799faa324da9bf52a22b2",
|
||||||
|
"zh:c7c5cde98fe4ef1143bd1b3ec5dc04baf0d4cc3ca2c5c7d40d17c0e9b2076865",
|
||||||
|
"zh:dac4bad52c940cd0dfc27893507c1e92393846b024c5a9db159a93c534a3da03",
|
||||||
|
"zh:de8febe2a2acd9ac454b844a4106ed295ae9520ef54dc8ed2faf29f12716b602",
|
||||||
|
"zh:eab0d0495e7e711cca367f7d4df6e322e6c562fc52151ec931176115b83ed014",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "registry.terraform.io/hashicorp/tls" {
|
||||||
|
version = "4.0.4"
|
||||||
|
hashes = [
|
||||||
|
"h1:GZcFizg5ZT2VrpwvxGBHQ/hO9r6g0vYdQqx3bFD3anY=",
|
||||||
|
"h1:Wd3RqmQW60k2QWPN4sK5CtjGuO1d+CRNXgC+D4rKtXc=",
|
||||||
|
"h1:bNsvpX5EGuVxgGRXBQVLXlmq40PdoLp8Rfuh1ZmV7yY=",
|
||||||
|
"h1:pe9vq86dZZKCm+8k1RhzARwENslF3SXb9ErHbQfgjXU=",
|
||||||
|
"h1:rKKMyIEBZwR+8j6Tx3PwqBrStuH+J+pxcbCR5XN8WAw=",
|
||||||
|
"zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55",
|
||||||
|
"zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848",
|
||||||
|
"zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be",
|
||||||
|
"zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5",
|
||||||
|
"zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe",
|
||||||
|
"zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e",
|
||||||
|
"zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48",
|
||||||
|
"zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8",
|
||||||
|
"zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60",
|
||||||
|
"zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e",
|
||||||
|
"zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316",
|
||||||
|
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||||
|
]
|
||||||
|
}
|
67
terraform/azure-constellation/main.tf
Normal file
67
terraform/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]
|
||||||
|
}
|
88
terraform/azure-constellation/variables.tf
Normal file
88
terraform/azure-constellation/variables.tf
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
variable "name" {
|
||||||
|
type = string
|
||||||
|
description = "Name of the Constellation cluster."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image" {
|
||||||
|
type = string
|
||||||
|
description = "Node image reference or semantical release 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."
|
||||||
|
}
|
@ -5,9 +5,16 @@ locals {
|
|||||||
fetch_image_command = <<EOT
|
fetch_image_command = <<EOT
|
||||||
curl -s https://cdn.confidential.cloud/constellation/v2/${local.image_ref}/image/info.json | \
|
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"
|
./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
|
EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
resource "null_resource" "fetch_image" {
|
resource "null_resource" "fetch_image" {
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
command = local.fetch_image_command
|
command = local.fetch_image_command
|
43
terraform/common/install-yq.sh
Executable file
43
terraform/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
|
@ -1,29 +1,32 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
if [[ -f ./constellation ]]; then # needed to allow using devbuilds
|
if [[ -f ./constellation ]]; then
|
||||||
echo "constellation CLI is already available."
|
echo "constellation CLI is already available."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
version="v2.13.0"
|
|
||||||
os=$(uname -s)
|
os=$(uname -s)
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
|
version=$1
|
||||||
url=""
|
url=""
|
||||||
|
|
||||||
|
echo "Fetching constellation ${version}"
|
||||||
|
|
||||||
if [[ ${os} == "Darwin" ]]; then
|
if [[ ${os} == "Darwin" ]]; then
|
||||||
if [[ ${arch} == "arm64" ]]; then
|
if [[ ${arch} == "arm64" ]]; then
|
||||||
url="https://github.com/edgelesssys/constellation/releases/download/${version}/constellation-darwin-arm64"
|
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-darwin-arm64"
|
||||||
elif [[ ${arch} == "x86_64" ]]; then
|
elif [[ ${arch} == "x86_64" ]]; then
|
||||||
url="https://github.com/edgelesssys/constellation/releases/download/${version}/constellation-darwin-amd64"
|
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-darwin-amd64"
|
||||||
fi
|
fi
|
||||||
elif [[ ${os} == "Linux" ]]; then
|
elif [[ ${os} == "Linux" ]]; then
|
||||||
if [[ ${arch} == "x86_64" ]]; then
|
if [[ ${arch} == "x86_64" ]]; then
|
||||||
url="https://github.com/edgelesssys/constellation/releases/download/${version}/constellation-linux-amd64"
|
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-linux-amd64"
|
||||||
elif [[ ${arch} == "arm64" ]]; then
|
elif [[ ${arch} == "arm64" ]]; then
|
||||||
url="https://github.com/edgelesssys/constellation/releases/download/${version}/constellation-linux-arm64"
|
url="https://github.com/edgelesssys/constellation/releases/${version}/download/constellation-linux-arm64"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Fetching constellation ${version}"
|
|
||||||
if [[ -z ${url} ]]; then
|
if [[ -z ${url} ]]; then
|
||||||
echo "OS \"${os}\" and/or architecture \"${arch}\" is not supported."
|
echo "os \"${os}\" and/or architecture \"${arch}\" is not supported."
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
curl -o constellation -L "${url}"
|
curl -o constellation -L "${url}"
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
#!/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
|
|
@ -15,7 +15,7 @@ locals {
|
|||||||
resource "null_resource" "ensure_cli" {
|
resource "null_resource" "ensure_cli" {
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
command = <<EOT
|
command = <<EOT
|
||||||
${path.module}/install-constellation.sh
|
${path.module}/install-constellation.sh ${var.constellation_version}
|
||||||
EOT
|
EOT
|
||||||
}
|
}
|
||||||
triggers = {
|
triggers = {
|
||||||
@ -53,14 +53,41 @@ resource "null_resource" "aws_config" {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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" {
|
resource "null_resource" "service_account_file" {
|
||||||
count = var.gcp_config != null ? 1 : 0
|
count = var.gcp_config != null ? 1 : 0
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
command = <<EOT
|
command = <<EOT
|
||||||
echo ${var.gcp_config.serviceAccountKey} | base64 -d > "${local.gcp_sa_file_path}"
|
echo ${var.gcp_config.serviceAccountKey} | base64 -d > "${local.gcp_sa_file_path}"
|
||||||
|
|
||||||
EOT
|
EOT
|
||||||
}
|
}
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
@ -81,7 +108,6 @@ resource "null_resource" "gcp_config" {
|
|||||||
./yq eval '.provider.gcp.region = "${var.gcp_config.region}"' -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.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 '.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.projectID = "${var.gcp_config.project}"' -i constellation-state.yaml
|
||||||
./yq eval '.infrastructure.gcp.ipCidrPod = "${var.gcp_config.ipCidrPod}"' -i constellation-state.yaml
|
./yq eval '.infrastructure.gcp.ipCidrPod = "${var.gcp_config.ipCidrPod}"' -i constellation-state.yaml
|
||||||
EOT
|
EOT
|
||||||
@ -99,21 +125,21 @@ resource "null_resource" "config" {
|
|||||||
command = <<EOT
|
command = <<EOT
|
||||||
./yq eval '.name = "${var.name}"' -i constellation-conf.yaml
|
./yq eval '.name = "${var.name}"' -i constellation-conf.yaml
|
||||||
if [ "${var.image}" != "" ]; then
|
if [ "${var.image}" != "" ]; then
|
||||||
./yq eval '.image = "${var.image}"' -i constellation-conf.yaml
|
./yq eval '.image = "${var.image}"' -i constellation-conf.yaml
|
||||||
fi
|
fi
|
||||||
if [ "${var.kubernetes_version}" != "" ]; then
|
if [ "${var.kubernetes_version}" != "" ]; then
|
||||||
./yq eval '.kubernetesVersion = "${var.kubernetes_version}"' -i constellation-conf.yaml
|
./yq eval '.kubernetesVersion = "${var.kubernetes_version}"' -i constellation-conf.yaml
|
||||||
fi
|
fi
|
||||||
if [ "${var.microservice_version}" != "" ]; then
|
if [ "${var.microservice_version}" != "" ]; then
|
||||||
./yq eval '.microserviceVersion = "${var.microservice_version}"' -i constellation-conf.yaml
|
./yq eval '.microserviceVersion = "${var.microservice_version}"' -i constellation-conf.yaml
|
||||||
fi
|
fi
|
||||||
${local.yq_node_groups}
|
${local.yq_node_groups}
|
||||||
./constellation config fetch-measurements
|
./constellation config fetch-measurements ${var.debug == true ? "--insecure" : ""}
|
||||||
EOT
|
EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
depends_on = [
|
depends_on = [
|
||||||
null_resource.aws_config, null_resource.gcp_config
|
null_resource.aws_config, null_resource.gcp_config, null_resource.azure_config
|
||||||
]
|
]
|
||||||
|
|
||||||
triggers = {
|
triggers = {
|
||||||
|
@ -1,9 +1,21 @@
|
|||||||
|
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."
|
||||||
|
default = "@@CONSTELLATION_VERSION@@"
|
||||||
|
}
|
||||||
|
|
||||||
variable "csp" {
|
variable "csp" {
|
||||||
type = string
|
type = string
|
||||||
description = "The cloud service provider to use."
|
description = "The cloud service provider to use."
|
||||||
validation {
|
validation {
|
||||||
condition = var.csp == "aws" || var.csp == "gcp"
|
condition = var.csp == "aws" || var.csp == "gcp" || var.csp == "azure"
|
||||||
error_message = "The CSP must be one of {aws|gcp}."
|
error_message = "The cloud service provider to use."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,7 +26,8 @@ variable "node_groups" {
|
|||||||
instance_type = string
|
instance_type = string
|
||||||
disk_size = number
|
disk_size = number
|
||||||
disk_type = string
|
disk_type = string
|
||||||
zone = string
|
zone = optional(string, "") # For AWS, GCP
|
||||||
|
zones = optional(list(string), []) # For Azure
|
||||||
}))
|
}))
|
||||||
description = "A map of node group names to node group configurations."
|
description = "A map of node group names to node group configurations."
|
||||||
validation {
|
validation {
|
||||||
@ -58,7 +71,6 @@ variable "apiServerCertSANs" {
|
|||||||
description = "List of additional SANs (Subject Alternative Names) for the Kubernetes API server certificate."
|
description = "List of additional SANs (Subject Alternative Names) for the Kubernetes API server certificate."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
variable "aws_config" {
|
variable "aws_config" {
|
||||||
type = object({
|
type = object({
|
||||||
region = string
|
region = string
|
||||||
@ -70,6 +82,23 @@ variable "aws_config" {
|
|||||||
default = null
|
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" {
|
variable "gcp_config" {
|
||||||
type = object({
|
type = object({
|
||||||
region = string
|
region = string
|
||||||
@ -82,15 +111,6 @@ variable "gcp_config" {
|
|||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "image" {
|
|
||||||
type = string
|
|
||||||
description = "The node image reference or semantical release version."
|
|
||||||
validation {
|
|
||||||
condition = length(var.image) > 0
|
|
||||||
error_message = "The image variable must not be empty."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "kubernetes_version" {
|
variable "kubernetes_version" {
|
||||||
type = string
|
type = string
|
||||||
description = "Kubernetes version."
|
description = "Kubernetes version."
|
||||||
@ -100,3 +120,9 @@ variable "microservice_version" {
|
|||||||
type = string
|
type = string
|
||||||
description = "Microservice version."
|
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."
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ module "gcp_iam" {
|
|||||||
resource "null_resource" "ensure_yq" {
|
resource "null_resource" "ensure_yq" {
|
||||||
provisioner "local-exec" {
|
provisioner "local-exec" {
|
||||||
command = <<EOT
|
command = <<EOT
|
||||||
../constellation-cluster/install-yq.sh
|
../common/install-yq.sh
|
||||||
EOT
|
EOT
|
||||||
}
|
}
|
||||||
triggers = {
|
triggers = {
|
||||||
@ -23,7 +23,7 @@ resource "null_resource" "ensure_yq" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module "fetch_image" {
|
module "fetch_image" {
|
||||||
source = "../fetch-image"
|
source = "../common/fetch-image"
|
||||||
csp = "gcp"
|
csp = "gcp"
|
||||||
attestation_variant = "gcp-sev-es"
|
attestation_variant = "gcp-sev-es"
|
||||||
image = var.image
|
image = var.image
|
||||||
@ -46,6 +46,7 @@ module "gcp" {
|
|||||||
module "constellation" {
|
module "constellation" {
|
||||||
source = "../constellation-cluster"
|
source = "../constellation-cluster"
|
||||||
csp = "gcp"
|
csp = "gcp"
|
||||||
|
debug = var.debug
|
||||||
name = var.name
|
name = var.name
|
||||||
image = var.image
|
image = var.image
|
||||||
microservice_version = var.microservice_version
|
microservice_version = var.microservice_version
|
||||||
|
@ -15,8 +15,8 @@ variable "service_account_id" {
|
|||||||
|
|
||||||
variable "image" {
|
variable "image" {
|
||||||
type = string
|
type = string
|
||||||
description = "Node image reference or semantical release version."
|
description = "Node image reference or semantic release version."
|
||||||
} # is required resolve the AMI
|
}
|
||||||
|
|
||||||
variable "microservice_version" {
|
variable "microservice_version" {
|
||||||
type = string
|
type = string
|
||||||
|
@ -10,3 +10,7 @@ output "uami_id" {
|
|||||||
description = "Outputs the id in the format: /$ID/resourceGroups/$RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$NAME. Not to be confused with the client_id"
|
description = "Outputs the id in the format: /$ID/resourceGroups/$RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$NAME. Not to be confused with the client_id"
|
||||||
value = azurerm_user_assigned_identity.identity_uami.id
|
value = azurerm_user_assigned_identity.identity_uami.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "base_resource_group" {
|
||||||
|
value = azurerm_resource_group.base_resource_group.name
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user