diff --git a/.github/actions/generate-key/action.yml b/.github/actions/generate-key/action.yml new file mode 100644 index 00000000..69d94258 --- /dev/null +++ b/.github/actions/generate-key/action.yml @@ -0,0 +1,22 @@ +name: "Generate keys" +description: "Generate openssl public and private keys" + +inputs: + keyFileNamePrefix: + description: 'Prefix of the key file name.' + required: true + directory: + description: 'Path to a directory where the key should be saved.' + default: deployment/terraform/dataspace + required: false + +runs: + using: "composite" + steps: + - name: 'Generate key' + run: | + openssl ecparam -name prime256v1 -genkey -noout -out ${{ inputs.keyFileNamePrefix }}.pem + openssl ec -in ${{ inputs.keyFileNamePrefix }}.pem -pubout -out ${{ inputs.keyFileNamePrefix }}.public.pem + docker run -i danedmunds/pem-to-jwk:1.2.1 --public --pretty < ${{ inputs.keyFileNamePrefix }}.public.pem > ${{ inputs.keyFileNamePrefix }}.public.jwk + shell: bash + working-directory: ${{ inputs.directory }} \ No newline at end of file diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 619f8935..042891de 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -2,7 +2,6 @@ name: CD on: pull_request: - branches: [ main ] paths-ignore: - 'docs/**' diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index eafb796d..36b1815e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -140,11 +140,15 @@ jobs: steps: - uses: actions/checkout@v2 - - name: 'Generate key' - run: | - openssl ecparam -name prime256v1 -genkey -noout -out key.pem - openssl ec -in key.pem -pubout -out key.public.pem - docker run -i danedmunds/pem-to-jwk:1.2.1 --public --pretty < key.public.pem > key.public.jwk + - name: 'Generate GAIA-X Authority key' + uses: ./.github/actions/generate-key + with: + keyFileNamePrefix: gaiaxkey + + - name: 'Generate Dataspace Authority key' + uses: ./.github/actions/generate-key + with: + keyFileNamePrefix: authoritykey - name: 'Create tfvars file' run: | @@ -153,7 +157,7 @@ jobs: acr_name = "${{ secrets.ACR_NAME }}" prefix = "${{ env.RESOURCES_PREFIX }}" resource_group = "rg-${{ env.RESOURCES_PREFIX }}" - registry_runtime_image = "mvd/registration-service:${{ env.RESOURCES_PREFIX }}" + registrationservice_runtime_image = "mvd/registration-service:${{ env.RESOURCES_PREFIX }}" application_sp_object_id = "${{ secrets.APP_OBJECT_ID }}" EOF @@ -183,8 +187,10 @@ jobs: echo "::set-output name=app_insights_connection_string::${app_insights_connection_string}" registration_service_url=$(terraform output -raw registration_service_url) echo "::set-output name=registration_service_url::${registration_service_url}" - did_host=$(terraform output -raw did_host) - echo "::set-output name=did_host::${did_host}" + authority_did_host=$(terraform output -raw authority_did_host) + echo "::set-output name=authority_did_host::${authority_did_host}" + gaiax_did_host=$(terraform output -raw gaiax_did_host) + echo "::set-output name=gaiax_did_host::${gaiax_did_host}" env: # Authentication settings for Terraform AzureRM provider @@ -194,11 +200,15 @@ jobs: ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }} # Terraform variables not included in terraform.tfvars. - TF_VAR_key_file: "key.pem" - TF_VAR_public_key_jwk_file: "key.public.jwk" + TF_VAR_key_file_authority: "authoritykey.pem" + TF_VAR_public_key_jwk_file_authority: "authoritykey.public.jwk" + TF_VAR_public_key_jwk_file_gaiax: "gaiaxkey.public.jwk" - - name: 'Verify did endpoint is available' - run: curl https://${{ steps.runterraform.outputs.did_host }}/.well-known/did.json | jq '.id' + - name: 'Verify GAIA-X Authority did endpoint is available' + run: curl https://${{ steps.runterraform.outputs.gaiax_did_host }}/.well-known/did.json | jq '.id' + + - name: 'Verify Dataspace Authority did endpoint is available' + run: curl https://${{ steps.runterraform.outputs.authority_did_host }}/.well-known/did.json | jq '.id' - name: 'Verify deployed Registry Service is healthy' run: curl --retry 6 --fail ${{ steps.runterraform.outputs.registration_service_url }}/api/check/health @@ -241,11 +251,11 @@ jobs: steps: - uses: actions/checkout@v2 - - name: 'Generate key' - run: | - openssl ecparam -name prime256v1 -genkey -noout -out key.pem - openssl ec -in key.pem -pubout -out key.public.pem - docker run -i danedmunds/pem-to-jwk:1.2.1 --public --pretty < key.public.pem > key.public.jwk + - name: 'Generate Participant key' + uses: ./.github/actions/generate-key + with: + keyFileNamePrefix: key + directory: deployment/terraform/participant - name: 'Create tfvars file' run: | diff --git a/deployment/terraform/dataspace/main.tf b/deployment/terraform/dataspace/main.tf index 92058637..bc188235 100644 --- a/deployment/terraform/dataspace/main.tf +++ b/deployment/terraform/dataspace/main.tf @@ -27,7 +27,7 @@ data "azurerm_subscription" "current_subscription" { data "azurerm_client_config" "current_client" { } -data "azurerm_container_registry" "registry" { +data "azurerm_container_registry" "registrationservice" { name = var.acr_name resource_group_name = var.acr_resource_group } @@ -40,7 +40,8 @@ locals { registration_service_dns_label = "${var.prefix}-registration-mvd" edc_default_port = 8181 - did_url = "did:web:${azurerm_storage_account.did.primary_web_host}" + authority_did_url = "did:web:${azurerm_storage_account.authority_did.primary_web_host}" + gaiax_did_url = "did:web:${azurerm_storage_account.gaiax_did.primary_web_host}" } resource "azurerm_resource_group" "dataspace" { @@ -64,14 +65,14 @@ resource "azurerm_container_group" "registration-service" { os_type = "Linux" image_registry_credential { - username = data.azurerm_container_registry.registry.admin_username - password = data.azurerm_container_registry.registry.admin_password - server = data.azurerm_container_registry.registry.login_server + username = data.azurerm_container_registry.registrationservice.admin_username + password = data.azurerm_container_registry.registrationservice.admin_password + server = data.azurerm_container_registry.registrationservice.login_server } container { name = "registration-service" - image = "${data.azurerm_container_registry.registry.login_server}/${var.registry_runtime_image}" + image = "${data.azurerm_container_registry.registrationservice.login_server}/${var.registrationservice_runtime_image}" cpu = var.container_cpu memory = var.container_memory @@ -93,9 +94,9 @@ resource "azurerm_container_group" "registration-service" { } } -resource "azurerm_key_vault" "registry" { +resource "azurerm_key_vault" "registrationservice" { // added `kv` prefix because the keyvault name needs to begin with a letter - name = "kv${var.prefix}-registry" + name = "kv${var.prefix}registration" location = var.location resource_group_name = azurerm_resource_group.dataspace.name enabled_for_disk_encryption = false @@ -107,21 +108,22 @@ resource "azurerm_key_vault" "registry" { } # Role assignment so that the application may access the vault -resource "azurerm_role_assignment" "registry_keyvault" { - scope = azurerm_key_vault.registry.id +resource "azurerm_role_assignment" "registrationservice_keyvault" { + scope = azurerm_key_vault.registrationservice.id role_definition_name = "Key Vault Secrets Officer" principal_id = var.application_sp_object_id } # Role assignment so that the currently logged in user may add secrets to the vault resource "azurerm_role_assignment" "current-user-secretsofficer" { - scope = azurerm_key_vault.registry.id + scope = azurerm_key_vault.registrationservice.id role_definition_name = "Key Vault Secrets Officer" principal_id = data.azurerm_client_config.current_client.object_id } -resource "azurerm_storage_account" "did" { - name = "${var.prefix}did" +# Registration Service resources +resource "azurerm_storage_account" "authority_did" { + name = "${var.prefix}authoritydid" resource_group_name = azurerm_resource_group.dataspace.name location = var.location account_tier = "Standard" @@ -130,42 +132,82 @@ resource "azurerm_storage_account" "did" { static_website {} } -resource "azurerm_key_vault_secret" "did_key" { +resource "azurerm_key_vault_secret" "authority_did_key" { name = local.connector_name # Create did_key secret only if key_file value is provided. Default key_file value is null. - count = var.key_file == null ? 0 : 1 - value = file(var.key_file) - key_vault_id = azurerm_key_vault.registry.id + count = var.key_file_authority == null ? 0 : 1 + value = file(var.key_file_authority) + key_vault_id = azurerm_key_vault.registrationservice.id depends_on = [ azurerm_role_assignment.current-user-secretsofficer ] } -resource "azurerm_storage_blob" "did" { +resource "azurerm_storage_blob" "authority_did" { name = ".well-known/did.json" # `.well-known` path is defined by did:web specification - storage_account_name = azurerm_storage_account.did.name + storage_account_name = azurerm_storage_account.authority_did.name # Create did blob only if public_key_jwk_file is provided. Default public_key_jwk_file value is null. - count = var.public_key_jwk_file == null ? 0 : 1 + count = var.public_key_jwk_file_authority == null ? 0 : 1 storage_container_name = "$web" # container used to serve static files (see static_website property on storage account) type = "Block" source_content = jsonencode({ - id = local.did_url + id = local.authority_did_url "@context" = [ "https://www.w3.org/ns/did/v1", { - "@base" = local.did_url + "@base" = local.authority_did_url } ], "verificationMethod" = [ { - "id" = "#identity-key-1" + "id" = "#identity-key-authority" "controller" = "" "type" = "JsonWebKey2020" - "publicKeyJwk" = jsondecode(file(var.public_key_jwk_file)) + "publicKeyJwk" = jsondecode(file(var.public_key_jwk_file_authority)) } ], "authentication" : [ - "#identity-key-1" + "#identity-key-authority" + ] }) + content_type = "application/json" +} + +# GAIA-X Authority resources +resource "azurerm_storage_account" "gaiax_did" { + name = "${var.prefix}gaiaxdid" + resource_group_name = azurerm_resource_group.dataspace.name + location = var.location + account_tier = "Standard" + account_replication_type = "LRS" + account_kind = "StorageV2" + static_website {} +} + +resource "azurerm_storage_blob" "gaiax_did" { + name = ".well-known/did.json" # `.well-known` path is defined by did:web specification + storage_account_name = azurerm_storage_account.gaiax_did.name + # Create did blob only if public_key_jwk_file is provided. Default public_key_jwk_file value is null. + count = var.public_key_jwk_file_gaiax == null ? 0 : 1 + storage_container_name = "$web" # container used to serve static files (see static_website property on storage account) + type = "Block" + source_content = jsonencode({ + id = local.gaiax_did_url + "@context" = [ + "https://www.w3.org/ns/did/v1", + { + "@base" = local.gaiax_did_url + } + ], + "verificationMethod" = [ + { + "id" = "#identity-key-gaiax" + "controller" = "" + "type" = "JsonWebKey2020" + "publicKeyJwk" = jsondecode(file(var.public_key_jwk_file_gaiax)) + } + ], + "authentication" : [ + "#identity-key-gaiax" ] }) content_type = "application/json" } diff --git a/deployment/terraform/dataspace/outputs.tf b/deployment/terraform/dataspace/outputs.tf index 010216d1..c40ba9bd 100644 --- a/deployment/terraform/dataspace/outputs.tf +++ b/deployment/terraform/dataspace/outputs.tf @@ -7,6 +7,10 @@ output "registration_service_url" { value = "http://${azurerm_container_group.registration-service.fqdn}:${local.edc_default_port}" } -output "did_host" { - value = length(azurerm_storage_blob.did) > 0 ? azurerm_storage_account.did.primary_web_host : null +output "authority_did_host" { + value = length(azurerm_storage_blob.authority_did) > 0 ? azurerm_storage_account.authority_did.primary_web_host : null +} + +output "gaiax_did_host" { + value = length(azurerm_storage_blob.gaiax_did) > 0 ? azurerm_storage_account.gaiax_did.primary_web_host : null } diff --git a/deployment/terraform/dataspace/variables.tf b/deployment/terraform/dataspace/variables.tf index 4d2e9ff4..3debe561 100644 --- a/deployment/terraform/dataspace/variables.tf +++ b/deployment/terraform/dataspace/variables.tf @@ -11,8 +11,8 @@ variable "resource_group" { default = "test-dataspace" } -variable "registry_runtime_image" { - description = "Image name of the Registry Service to deploy." +variable "registrationservice_runtime_image" { + description = "Image name of the Registration Service to deploy." } variable "acr_name" { @@ -35,12 +35,17 @@ variable "application_sp_object_id" { description = "object id of application's service principal object" } -variable "key_file" { - description = "name of a file containing the private key in PEM format" +variable "key_file_authority" { + description = "name of a file containing the Registration Service private key in PEM format" default = null } -variable "public_key_jwk_file" { - description = "name of a file containing the public key in JWK format" +variable "public_key_jwk_file_authority" { + description = "name of a file containing the Registration Service public key in JWK format" + default = null +} + +variable "public_key_jwk_file_gaiax" { + description = "name of a file containing the GAIA-X public key in JWK format" default = null }