diff --git a/deployment/data/Seeding.postman_collection.json b/deployment/data/Seeding.postman_collection.json new file mode 100644 index 0000000..2cf8fd3 --- /dev/null +++ b/deployment/data/Seeding.postman_collection.json @@ -0,0 +1,650 @@ +{ + "info": { + "_postman_id": "29e34005-d2be-4e9d-a11c-4db521a16896", + "name": "EonaX-Shared-Resource", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Authority", + "item": [ + { + "name": "Public key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcDS3f35yBqbi9q35KaJ4CixIFxvt\\n6afy2Btfi8v+OZjT0RBS98r8ztPujN4o1ECGEgpak2+HpKYOkd5d8kQpjg==\\n-----END PUBLIC KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{authorityName}}/vault/v1/secret/data/{{authorityName}}-pub", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{authorityName}}", + "vault", + "v1", + "secret", + "data", + "{{authorityName}}-pub" + ] + } + }, + "response": [] + }, + { + "name": "Private key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIPDpR1AbQwqpuFozaM3+2Jk1gKF3EpreBBPVYgS39aeAoAoGCCqGSM49\\nAwEHoUQDQgAEcDS3f35yBqbi9q35KaJ4CixIFxvt6afy2Btfi8v+OZjT0RBS98r8\\nztPujN4o1ECGEgpak2+HpKYOkd5d8kQpjg==\\n-----END EC PRIVATE KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{authorityName}}/vault/v1/secret/data/{{authorityName}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{authorityName}}", + "vault", + "v1", + "secret", + "data", + "{{authorityName}}" + ] + } + }, + "response": [] + }, + { + "name": "Create Participant Context (IdentityHub)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"participantId\": \"did:web:{{authorityName}}-identityhub%3A8383:api:did\",\r\n \"did\": \"did:web:{{authorityName}}-identityhub%3A8383:api:did\",\r\n \"active\": true,\r\n \"key\": {\r\n \"keyId\": \"my-key\",\r\n \"privateKeyAlias\": \"{{authorityName}}\",\r\n \"publicKeyPem\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcDS3f35yBqbi9q35KaJ4CixIFxvt\\n6afy2Btfi8v+OZjT0RBS98r8ztPujN4o1ECGEgpak2+HpKYOkd5d8kQpjg==\\n-----END PUBLIC KEY-----\"\r\n },\r\n \"serviceEndpoints\": [\r\n {\r\n \"id\": \"credential-service-url\",\r\n \"type\": \"CredentialService\",\r\n \"serviceEndpoint\": \"http://{{authorityName}}-identityhub:8282/api/resolution/v1/participants/ZGlkOndlYjphdXRob3JpdHktaWRlbnRpdHlodWIlM0E4MzgzOmFwaTpkaWQ\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{authorityName}}/ih/management/v1/participants", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{authorityName}}", + "ih", + "management", + "v1", + "participants" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Consumer", + "item": [ + { + "name": "Public key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOc48T9d92Rr5bXOyUqDs4HFvkRXF\\nDA6wGzrk3+zp8o9Unc/mutDK+ntdDycTDkNXeeJwMVQJWfKE5I9Wgb682w==\\n-----END PUBLIC KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{consumerName}}/vault/v1/secret/data/{{consumerName}}-pub", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{consumerName}}", + "vault", + "v1", + "secret", + "data", + "{{consumerName}}-pub" + ] + } + }, + "response": [] + }, + { + "name": "Private key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEICNv5iWlHoubyqa0xzjiU5q4ZXO7ZZG6iSqrjUWyv1QDoAoGCCqGSM49\\nAwEHoUQDQgAEOc48T9d92Rr5bXOyUqDs4HFvkRXFDA6wGzrk3+zp8o9Unc/mutDK\\n+ntdDycTDkNXeeJwMVQJWfKE5I9Wgb682w==\\n-----END EC PRIVATE KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{consumerName}}/vault/v1/secret/data/{{consumerName}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{consumerName}}", + "vault", + "v1", + "secret", + "data", + "{{consumerName}}" + ] + } + }, + "response": [] + }, + { + "name": "Create Participant Context (IdentityHub)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"participantId\": \"did:web:{{consumerName}}-identityhub%3A8383:api:did\",\r\n \"did\": \"did:web:{{consumerName}}-identityhub%3A8383:api:did\",\r\n \"active\": true,\r\n \"key\": {\r\n \"keyId\": \"my-key\",\r\n \"privateKeyAlias\": \"{{consumerName}}\",\r\n \"publicKeyPem\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOc48T9d92Rr5bXOyUqDs4HFvkRXF\\nDA6wGzrk3+zp8o9Unc/mutDK+ntdDycTDkNXeeJwMVQJWfKE5I9Wgb682w==\\n-----END PUBLIC KEY-----\"\r\n },\r\n \"serviceEndpoints\": [\r\n {\r\n \"id\": \"credential-service-url\",\r\n \"type\": \"CredentialService\",\r\n \"serviceEndpoint\": \"http://{{consumerName}}-identityhub:8282/api/resolution/v1/participants/ZGlkOndlYjpjb25zdW1lci1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZA\"\r\n },\r\n {\r\n \"id\": \"dsp-url\",\r\n \"type\": \"DSPMessaging\",\r\n \"serviceEndpoint\": \"http://{{consumerName}}-connector:8282/api/dsp\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{consumerName}}/ih/management/v1/participants", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{consumerName}}", + "ih", + "management", + "v1", + "participants" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Provider", + "item": [ + { + "name": "Public key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENqKFUb7sxqJOb8TDX2PmRVRaW7R8\\n48S4RlUncssxMWHJXsrRbkv3naFOh9uB4s6++7hezPop50EdidCiK2Nfyw==\\n-----END PUBLIC KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/vault/v1/secret/data/{{providerName}}-pub", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "vault", + "v1", + "secret", + "data", + "{{providerName}}-pub" + ] + } + }, + "response": [] + }, + { + "name": "Private key", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "value", + "value": "{{vaultToken}}", + "type": "string" + }, + { + "key": "key", + "value": "X-Vault-Token", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"content\": \"-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIB2n2AQoTo+pHUBOakicb3UaQf+VeyQTX0RH0axZdEDtoAoGCCqGSM49\\nAwEHoUQDQgAENqKFUb7sxqJOb8TDX2PmRVRaW7R848S4RlUncssxMWHJXsrRbkv3\\nnaFOh9uB4s6++7hezPop50EdidCiK2Nfyw==\\n-----END EC PRIVATE KEY-----\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/vault/v1/secret/data/{{providerName}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "vault", + "v1", + "secret", + "data", + "{{providerName}}" + ] + } + }, + "response": [] + }, + { + "name": "Create asset \"Hello World!\"", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"@context\": {\r\n \"@vocab\": \"https://w3id.org/edc/v0.0.1/ns/\"\r\n },\r\n \"@id\": \"hello-world\",\r\n \"properties\": {\r\n \"name\": \"Hello World asset\",\r\n \"contenttype\": \"application/json\",\r\n \"version\": \"1.0\",\r\n \"description\": \"An asset that says Hello World!\"\r\n },\r\n \"dataAddress\": {\r\n \"type\": \"HttpData\",\r\n \"baseUrl\": \"http://provider-backend:8080/api/provider/data\"\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/cp/management/v3/assets", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "cp", + "management", + "v3", + "assets" + ] + } + }, + "response": [] + }, + { + "name": "Create policy Eona-X Membership", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"@context\": {\r\n \"@vocab\": \"https://w3id.org/edc/v0.0.1/ns/\"\r\n },\r\n \"@type\": \"PolicyDefinitionDto\",\r\n \"@id\": \"eonax-member-only\",\r\n \"policy\": {\r\n \"@context\": \"http://www.w3.org/ns/odrl.jsonld\",\r\n \"@type\": \"http://www.w3.org/ns/odrl/2/Set\",\r\n \"permission\": [\r\n {\r\n \"action\": \"use\",\r\n \"constraint\": {\r\n \"@type\": \"Constraint\",\r\n \"leftOperand\": \"MembershipCredential\",\r\n \"operator\": \"odrl:eq\",\r\n \"rightOperand\": \"active\"\r\n }\r\n }\r\n ]\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/cp/management/v2/policydefinitions", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "cp", + "management", + "v2", + "policydefinitions" + ] + } + }, + "response": [] + }, + { + "name": "Create contract def \"Hello World\"", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"@id\": \"6b8f1075-e48b-4c02-9c0b-14f2e3b9bde9\",\r\n \"@type\": \"https://w3id.org/edc/v0.0.1/ns/ContractDefinition\",\r\n \"https://w3id.org/edc/v0.0.1/ns/accessPolicyId\": \"eonax-member-only\",\r\n \"https://w3id.org/edc/v0.0.1/ns/contractPolicyId\": \"eonax-member-only\",\r\n \"https://w3id.org/edc/v0.0.1/ns/assetsSelector\": [\r\n {\r\n \"@type\": \"https://w3id.org/edc/v0.0.1/ns/Criterion\",\r\n \"https://w3id.org/edc/v0.0.1/ns/operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\r\n \"https://w3id.org/edc/v0.0.1/ns/operator\": \"=\",\r\n \"https://w3id.org/edc/v0.0.1/ns/operandRight\": \"hello-world\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/cp/management/v2/contractdefinitions", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "cp", + "management", + "v2", + "contractdefinitions" + ] + } + }, + "response": [] + }, + { + "name": "Create Participant Context (IdentityHub)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"participantId\": \"did:web:{{providerName}}-identityhub%3A8383:api:did\",\r\n \"did\": \"did:web:{{providerName}}-identityhub%3A8383:api:did\",\r\n \"active\": true,\r\n \"key\": {\r\n \"keyId\": \"my-key\",\r\n \"privateKeyAlias\": \"{{providerName}}\",\r\n \"publicKeyPem\": \"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENqKFUb7sxqJOb8TDX2PmRVRaW7R8\\n48S4RlUncssxMWHJXsrRbkv3naFOh9uB4s6++7hezPop50EdidCiK2Nfyw==\\n-----END PUBLIC KEY-----\"\r\n },\r\n \"serviceEndpoints\": [\r\n {\r\n \"id\": \"credential-service-url\",\r\n \"type\": \"CredentialService\",\r\n \"serviceEndpoint\": \"http://{{providerName}}-identityhub:8282/api/resolution/v1/participants/ZGlkOndlYjpwcm92aWRlci1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZA\"\r\n },\r\n {\r\n \"id\": \"dsp-url\",\r\n \"type\": \"DSPMessaging\",\r\n \"serviceEndpoint\": \"http://{{providerName}}-connector:8282/api/dsp\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:80/{{providerName}}/ih/management/v1/participants", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "80", + "path": [ + "{{providerName}}", + "ih", + "management", + "v1", + "participants" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Status code is 200 or 204\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([204, 200])", + "});" + ] + } + } + ], + "variable": [ + { + "key": "vaultToken", + "value": "root" + }, + { + "key": "authorityName", + "value": "authority" + }, + { + "key": "providerName", + "value": "provider" + }, + { + "key": "consumerName", + "value": "consumer" + } + ] +} \ No newline at end of file diff --git a/deployment/main.tf b/deployment/main.tf index 23b77cc..c93423f 100644 --- a/deployment/main.tf +++ b/deployment/main.tf @@ -5,9 +5,7 @@ locals { base64Token = base64encode("${var.container_registry_username}:${var.container_registry_token}") secretJson = "{\"auths\":{\"ghcr.io\":{\"auth\":\"${local.base64Token}\"}}}" - registration_service_mock_name = "registration-service-mock" - registration_service_mock_port = 8080 - registration_service_mock_host = "${local.registration_service_mock_name}:${local.registration_service_mock_port}" + participants = [var.data_provider, var.data_consumer] } ################### @@ -17,7 +15,8 @@ locals { module "db" { source = "./modules/db" - participant_names = [for p in var.participants : p.name] + authority_name = var.authority.name + participant_names = [for p in local.participants : p.name] } #################################### @@ -53,32 +52,65 @@ resource "kubernetes_secret_v1" "docker-image-pull-secret" { type = "kubernetes.io/dockerconfigjson" } -######################### -## EONA-X PARTICIPANTS ## -######################### +################## +## PARTICIPANTS ## +################## module "participant" { source = "./modules/participant" - for_each = { for p in var.participants : p.name => p } - participant = each.value + for_each = { for p in local.participants : p.name => p } + participant = each.value + + # POSTGRES postgres_host = module.db.postgres_host - registration_service_url = "http://${local.registration_service_mock_host}" postgres_credentials_secret_name = kubernetes_secret.postgresql-db-secret.metadata.0.name - docker_image_pull_secret_name = local.docker_image_pull_secret_name - connector_docker_image_repo = var.connector_docker_image_repo - connector_helm_chart_repo = var.connector_helm_chart_repo - connector_version = var.connector_version + + # DOCKER + docker_image_pull_secret_name = kubernetes_secret_v1.docker-image-pull-secret.metadata.0.name + helm_chart_repo = var.helm_chart_repo + + # CONNECTOR + connector_repo = var.connector_repo + connector_chart_name = var.connector_chart_name + connector_version = var.connector_version + + # IDENTITY HUB + identityhub_repo = var.identityhub_repo + identityhub_chart_name = var.identityhub_chart_name + identityhub_version = var.identityhub_version } -############################### -## REGISTRATION SERVICE MOCK ## -############################### +######################### +## DATASPACE AUTHORITY ## +######################### + +module "authority" { + source = "./modules/authority" + + authority = var.authority + + participants = [ + for p in local.participants : merge(p, { + did : module.participant[p.name].did_url + }) + ] + + # POSTGRES + postgres_host = module.db.postgres_host + postgres_credentials_secret_name = kubernetes_secret.postgresql-db-secret.metadata.0.name + + # DOCKER + docker_image_pull_secret_name = kubernetes_secret_v1.docker-image-pull-secret.metadata.0.name + helm_chart_repo = var.helm_chart_repo -module "registration-service-mock" { - source = "./modules/registration-service-mock" + # FEDERATED CATALOG + federatedcatalog_chart_name = var.federatedcatalog_chart_name + federatedcatalog_repo = var.federatedcatalog_repo + federatedcatalog_version = var.federatedcatalog_version - participants_did = [for p in module.participant : p.did_url] - name = local.registration_service_mock_name - server_port = local.registration_service_mock_port + # IDENTITY HUB + identityhub_chart_name = var.identityhub_chart_name + identityhub_version = var.identityhub_version + identityhub_repo = var.identityhub_repo } \ No newline at end of file diff --git a/deployment/modules/authority/catalog.tf b/deployment/modules/authority/catalog.tf new file mode 100644 index 0000000..8c1efc3 --- /dev/null +++ b/deployment/modules/authority/catalog.tf @@ -0,0 +1,83 @@ +locals { + catalog_release_name = "${var.authority.name}-federatedcatalog" + + crawler_initial_delay = 10 + crawler_execution_period = 10 +} + +resource "helm_release" "federated-catalog" { + name = local.catalog_release_name + cleanup_on_fail = true + dependency_update = true + recreate_pods = true + repository = var.helm_chart_repo + chart = var.federatedcatalog_chart_name + version = var.federatedcatalog_version + + values = [ + yamlencode({ + + "imagePullSecrets" : [ + { + "name" : var.docker_image_pull_secret_name + } + ], + + "federatedcatalog" : { + "image" : { + "repository" : var.federatedcatalog_repo + "tag" : var.federatedcatalog_version + }, + "did" : { + "web" : { + "url" : local.did_url, + "useHttps" : false + } + }, + "crawler" : { + "participantsRegistry" : { + "url" : "http://${local.participants_registry_name}:8080/participants.json" + }, + "cache" : { + "executionPeriodSeconds" : local.crawler_execution_period + "executionDelaySeconds" : local.crawler_initial_delay + } + }, + "trustedIssuers" : { + "authority" : { + "did" : local.did_url + } + }, + "keys" : { + "sts" : { + "privateKeyVaultAlias" : local.privatekey_alias, + "publicKeyDid" : local.did_url + } + }, + "ingress" : { + "enabled" : true + "className" : "nginx" + "annotations" : { + "nginx.ingress.kubernetes.io/ssl-redirect" : "false" + "nginx.ingress.kubernetes.io/use-regex" : "true" + "nginx.ingress.kubernetes.io/rewrite-target" : "/api/$1$2" + }, + "endpoints" : [ + { + "port" : 8181, + "path" : "/${var.authority.name}/catalog/(management)(.*)" + } + ] + }, + "vault" : { + "hashicorp" : { + "url" : module.vault.vault_url + "token" : module.vault.vault_token + } + } + } + }) + ] + + depends_on = [kubernetes_service.registry-service, module.vault] +} \ No newline at end of file diff --git a/deployment/modules/authority/identityhub.tf b/deployment/modules/authority/identityhub.tf new file mode 100644 index 0000000..e111e01 --- /dev/null +++ b/deployment/modules/authority/identityhub.tf @@ -0,0 +1,97 @@ +locals { + identityhub_release_name = "${var.authority.name}-identityhub" + + credential_service_url = "http://${local.identityhub_release_name}:8282/api/resolution" + did_url = "did:web:${local.identityhub_release_name}%3A8383:api:did" +} + +############################ +## VERIFIABLE CREDENTIALS ## +############################ + +resource "kubernetes_config_map" "verifiable-credentials" { + + metadata { + name = "${local.identityhub_release_name}-credentials" + } + + data = { + "credentials.json" = jsonencode(var.authority.vc) + } +} + +################## +## IDENTITY HUB ## +################## + +resource "helm_release" "identity-hub" { + name = local.identityhub_release_name + cleanup_on_fail = true + dependency_update = true + recreate_pods = true + repository = var.helm_chart_repo + chart = var.identityhub_chart_name + version = var.identityhub_version + + values = [ + yamlencode({ + + "imagePullSecrets" : [ + { + "name" : var.docker_image_pull_secret_name + } + ], + + "identityhub" : { + "image" : { + "repository" : var.identityhub_repo + "tag" : var.identityhub_version + }, + "keys" : { + "sts" : { + "publicKeyVaultAlias" : local.publickey_alias + } + }, + "did" : { + "web" : { + "url" : local.did_url, + "useHttps" : false + } + }, + "postgresql" : { + "jdbcUrl" : "jdbc:postgresql://${var.postgres_host}/${var.authority.name}", + "secret" : { + "name" : var.postgres_credentials_secret_name + } + }, + "ingress" : { + "enabled" : true + "className" : "nginx" + "annotations" : { + "nginx.ingress.kubernetes.io/ssl-redirect" : "false" + "nginx.ingress.kubernetes.io/use-regex" : "true" + "nginx.ingress.kubernetes.io/rewrite-target" : "/api/$1$2" + }, + "endpoints" : [ + { + "port" : 8181, + "path" : "/${var.authority.name}/ih/(management)(.*)" + }, + { + "port" : 8282, + "path" : "/${var.authority.name}/ih/(resolution)(.*)" + } + ] + }, + "vault" : { + "hashicorp" : { + "url" : module.vault.vault_url + "token" : module.vault.vault_token + } + } + } + }) + ] + + depends_on = [module.vault] +} \ No newline at end of file diff --git a/deployment/modules/authority/main.tf b/deployment/modules/authority/main.tf new file mode 100644 index 0000000..a28f18f --- /dev/null +++ b/deployment/modules/authority/main.tf @@ -0,0 +1,10 @@ +locals { + privatekey_alias = var.authority.name + publickey_alias = "${local.privatekey_alias}-pub" +} + +module "vault" { + source = "../vault" + + participant_name = var.authority.name +} \ No newline at end of file diff --git a/deployment/modules/authority/providers.tf b/deployment/modules/authority/providers.tf new file mode 100644 index 0000000..9bc2649 --- /dev/null +++ b/deployment/modules/authority/providers.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + helm = { + source = "hashicorp/helm" + } + } +} \ No newline at end of file diff --git a/deployment/modules/authority/registry.tf b/deployment/modules/authority/registry.tf new file mode 100644 index 0000000..6890311 --- /dev/null +++ b/deployment/modules/authority/registry.tf @@ -0,0 +1,111 @@ +locals { + server_image = "nginxinc/nginx-unprivileged:1.25.3" + participants_registry_name = "registry" + server_port = 8080 +} + +resource "kubernetes_deployment" "registry" { + metadata { + name = local.participants_registry_name + labels = { + app = local.participants_registry_name + } + } + + spec { + replicas = 1 + selector { + match_labels = { + app = local.participants_registry_name + } + } + template { + metadata { + labels = { + app = local.participants_registry_name + } + } + spec { + container { + image = local.server_image + name = local.participants_registry_name + + env_from { + config_map_ref { + name = kubernetes_config_map.registry-config.metadata[0].name + } + } + port { + container_port = local.server_port + name = "registry-port" + } + + volume_mount { + mount_path = "/usr/share/nginx/html" + name = "registry-config" + } + } + volume { + name = "registry-config" + config_map { + name = kubernetes_config_map.registry-config.metadata.0.name + } + } + } + } + } +} + +resource "kubernetes_config_map" "registry-config" { + metadata { + name = "participants-registry-config" + } + + data = { + "participants.json" : jsonencode(var.participants) + } +} + +resource "kubernetes_service" "registry-service" { + metadata { + name = local.participants_registry_name + } + spec { + selector = { + app = kubernetes_deployment.registry.spec.0.template.0.metadata[0].labels.app + } + port { + name = "registry-port" + port = local.server_port + target_port = local.server_port + } + } +} + +resource "kubernetes_ingress_v1" "registry-ingress" { + metadata { + name = "participants-registry-ingress" + annotations = { + "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" + "nginx.ingress.kubernetes.io/use-regex" = "true" + } + } + spec { + ingress_class_name = "nginx" + rule { + http { + path { + path = "/${var.authority.name}/${local.participants_registry_name}(/|$)(.*)" + backend { + service { + name = kubernetes_service.registry-service.metadata.0.name + port { + number = local.server_port + } + } + } + } + } + } + } +} diff --git a/deployment/modules/authority/variables.tf b/deployment/modules/authority/variables.tf new file mode 100644 index 0000000..bb5dc58 --- /dev/null +++ b/deployment/modules/authority/variables.tf @@ -0,0 +1,34 @@ +variable "authority" { + type = object({ + name = string, + vc = list(any) + }) +} + +variable "participants" { + type = list(object({ + name = string + did = string + })) +} + +# POSTGRES +variable "postgres_host" {} +variable "postgres_credentials_secret_name" {} + +# FEDERATED CATALOG +variable "federatedcatalog_repo" {} +variable "federatedcatalog_chart_name" {} +variable "federatedcatalog_version" {} + +# IDENTITY HUB +variable "identityhub_repo" {} +variable "identityhub_chart_name" {} +variable "identityhub_version" {} + +# DOCKER PULL +variable "helm_chart_repo" {} +variable "docker_image_pull_secret_name" {} + + + diff --git a/deployment/modules/db/main.tf b/deployment/modules/db/main.tf index ff320a9..8495ecd 100644 --- a/deployment/modules/db/main.tf +++ b/deployment/modules/db/main.tf @@ -91,11 +91,10 @@ resource "kubernetes_config_map" "postgres-config" { name = "pg-initdb-config" } - data = { "db_bootstrap_script.sql" = local.db_bootstrap_script "init.sh" = templatefile("${path.module}/init.sh", { - participants : join(" ", var.participant_names) + participants : join(" ", concat([var.authority_name], var.participant_names)) }) } } diff --git a/deployment/modules/db/sql/contract-definition.sql b/deployment/modules/db/sql/contract-definition.sql index 98a30b7..ad29cfe 100644 --- a/deployment/modules/db/sql/contract-definition.sql +++ b/deployment/modules/db/sql/contract-definition.sql @@ -24,4 +24,4 @@ CREATE TABLE IF NOT EXISTS edc_contract_definitions assets_selector JSON NOT NULL, private_properties JSON, PRIMARY KEY (contract_definition_id) -); +); \ No newline at end of file diff --git a/deployment/modules/db/sql/contract-negotiation.sql b/deployment/modules/db/sql/contract-negotiation.sql index f8920c1..2413c18 100644 --- a/deployment/modules/db/sql/contract-negotiation.sql +++ b/deployment/modules/db/sql/contract-negotiation.sql @@ -58,11 +58,11 @@ CREATE TABLE IF NOT EXISTS edc_contract_negotiation callback_addresses JSON, trace_context JSON, pending BOOLEAN DEFAULT FALSE, + protocol_messages JSON, lease_id VARCHAR CONSTRAINT contract_negotiation_lease_lease_id_fk REFERENCES edc_lease - ON DELETE SET NULL, - CONSTRAINT provider_correlation_id CHECK (type = '0' OR correlation_id IS NOT NULL) + ON DELETE SET NULL ); COMMENT ON COLUMN edc_contract_negotiation.agreement_id IS 'ContractAgreement serialized as JSON'; diff --git a/deployment/modules/db/sql/credentials.sql b/deployment/modules/db/sql/credentials.sql new file mode 100644 index 0000000..ed4fca1 --- /dev/null +++ b/deployment/modules/db/sql/credentials.sql @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Metaform Systems, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Metaform Systems, Inc. - initial API and implementation + * + */ + +-- only intended for and tested with Postgres! +CREATE TABLE credential_resource +( + id VARCHAR PRIMARY KEY NOT NULL, -- ID of the VC, duplicated here for indexing purposes + create_timestamp BIGINT NOT NULL, -- POSIX timestamp of the creation of the VC + issuer_id VARCHAR NOT NULL, + holder_id VARCHAR NOT NULL, + vc_state INTEGER NOT NULL, + issuance_policy JSON, + reissuance_policy JSON, + raw_vc VARCHAR NOT NULL, -- Representation of the VC exactly as it was received by the issuer. Can be JWT or JSON(-LD) + vc_format INTEGER NOT NULL, -- 0 = JSON-LD, 1 = JWT + verifiable_credential JSON NOT NULL, -- JSON-representation of the verifiable credential + participant_id VARCHAR -- ID of the ParticipantContext that owns this credentisl +); +CREATE UNIQUE INDEX credential_resource_credential_id_uindex ON credential_resource USING btree (id); +COMMENT ON COLUMN credential_resource.id IS 'ID of the VC, duplicated here for indexing purposes'; +COMMENT ON COLUMN credential_resource.raw_vc IS 'Representation of the VC exactly as it was received by the issuer. Can be JWT or JSON(-LD) '; +COMMENT ON COLUMN credential_resource.vc_format IS '0 = JSON-LD, 1 = JWT'; +COMMENT ON COLUMN credential_resource.verifiable_credential is 'JSON-representation of the VerifiableCredential'; + diff --git a/deployment/modules/db/sql/did.sql b/deployment/modules/db/sql/did.sql new file mode 100644 index 0000000..d4c3b68 --- /dev/null +++ b/deployment/modules/db/sql/did.sql @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Metaform Systems, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Metaform Systems, Inc. - initial API and implementation + * + */ + +-- only intended for and tested with Postgres! +CREATE TABLE IF NOT EXISTS did_resources +( + did VARCHAR NOT NULL, + create_timestamp BIGINT NOT NULL, + state_timestamp BIGINT NOT NULL, + state INT NOT NULL, + did_document JSON NOT NULL, + participant_id VARCHAR, + PRIMARY KEY (did) +); diff --git a/deployment/modules/db/sql/keypair.sql b/deployment/modules/db/sql/keypair.sql new file mode 100644 index 0000000..f4a14a4 --- /dev/null +++ b/deployment/modules/db/sql/keypair.sql @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Metaform Systems, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Metaform Systems, Inc. - initial API and implementation + * + */ + +-- only intended for and tested with Postgres! +CREATE TABLE keypair_resource +( + id VARCHAR PRIMARY KEY NOT NULL, -- primary key + participant_id VARCHAR, -- ID of the owning ParticipantContext. this is a loose business key, not a FK! + timestamp BIGINT NOT NULL, -- creation timestamp + key_id VARCHAR NOT NULL, -- name/key-id of this key pair. for use in JWTs etc. + group_name VARCHAR, + is_default_pair BOOLEAN DEFAULT FALSE, -- whether this keypair is the default one for a participant context + use_duration BIGINT, -- maximum time this keypair can be active before it gets rotated + rotation_duration BIGINT, -- duration during which this keypair is in a transitional state (rotated, not yet deactivated) + serialized_public_key VARCHAR NOT NULL, -- serialized public key (PEM, JWK,...) + private_key_alias VARCHAR NOT NULL, -- alias under which the private key is stored in the HSM/Vault + state INT NOT NULL DEFAULT 100 -- KeyPairState +); + diff --git a/deployment/modules/db/sql/participant.sql b/deployment/modules/db/sql/participant.sql deleted file mode 100644 index bb7574f..0000000 --- a/deployment/modules/db/sql/participant.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE IF NOT EXISTS edc_participant -( - id VARCHAR NOT NULL PRIMARY KEY, - did VARCHAR NOT NULL UNIQUE, - state INTEGER DEFAULT 0 NOT NULL, - state_count INTEGER DEFAULT 0 NOT NULL, - state_timestamp BIGINT, - error_detail VARCHAR, - trace_context JSON, - created_at BIGINT NOT NULL, - updated_at BIGINT NOT NULL -); diff --git a/deployment/modules/db/sql/participantcontext.sql b/deployment/modules/db/sql/participantcontext.sql new file mode 100644 index 0000000..431d47b --- /dev/null +++ b/deployment/modules/db/sql/participantcontext.sql @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Metaform Systems, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Metaform Systems, Inc. - initial API and implementation + * + */ + +-- only intended for and tested with Postgres! +CREATE TABLE participant_context +( + participant_id VARCHAR PRIMARY KEY NOT NULL, -- ID of the ParticipantContext + created_date BIGINT NOT NULL, -- POSIX timestamp of the creation of the PC + last_modified_date BIGINT, -- POSIX timestamp of the last modified date + state INTEGER NOT NULL, -- 0 = CREATED, 1 = ACTIVE, 2 = DEACTIVATED + api_token_alias VARCHAR NOT NULL, -- alias under which this PC's api token is stored in the vault + did VARCHAR, -- the DID with which this participant is identified + roles JSON -- JSON array containing all the roles a user has. may be empty +); +CREATE UNIQUE INDEX participant_context_participant_id_uindex ON participant_context USING btree (participant_id); + diff --git a/deployment/modules/db/sql/transfer-process.sql b/deployment/modules/db/sql/transfer-process.sql index 8e3ba65..44baf17 100644 --- a/deployment/modules/db/sql/transfer-process.sql +++ b/deployment/modules/db/sql/transfer-process.sql @@ -31,9 +31,11 @@ CREATE TABLE IF NOT EXISTS edc_transfer_process provisioned_resource_set JSON, content_data_address JSON, deprovisioned_resources JSON, - private_properties JSON, + private_properties JSON, callback_addresses JSON, pending BOOLEAN DEFAULT FALSE, + transfer_type VARCHAR, + protocol_messages JSON, lease_id VARCHAR CONSTRAINT transfer_process_lease_lease_id_fk REFERENCES edc_lease @@ -62,7 +64,6 @@ CREATE TABLE IF NOT EXISTS edc_data_request process_id VARCHAR NOT NULL, connector_address VARCHAR NOT NULL, protocol VARCHAR NOT NULL, - connector_id VARCHAR, asset_id VARCHAR NOT NULL, contract_id VARCHAR NOT NULL, data_destination JSON NOT NULL, diff --git a/deployment/modules/db/variables.tf b/deployment/modules/db/variables.tf index 3d80acc..4513cc3 100644 --- a/deployment/modules/db/variables.tf +++ b/deployment/modules/db/variables.tf @@ -2,6 +2,8 @@ variable "postgres_port" { default = 5432 } +variable "authority_name" {} + variable "participant_names" { type = list(string) } \ No newline at end of file diff --git a/deployment/modules/participant/backend-api.tf b/deployment/modules/participant/backend-api.tf new file mode 100644 index 0000000..f6adbd1 --- /dev/null +++ b/deployment/modules/participant/backend-api.tf @@ -0,0 +1,111 @@ +locals { + server_image = "nginxinc/nginx-unprivileged:1.25.3" + backend-api-name = "${var.participant.name}-api" + server_port = 8080 +} + +resource "kubernetes_deployment" "backend-api" { + metadata { + name = local.backend-api-name + labels = { + app = local.backend-api-name + } + } + + spec { + replicas = 1 + selector { + match_labels = { + app = local.backend-api-name + } + } + template { + metadata { + labels = { + app = local.backend-api-name + } + } + spec { + container { + image = local.server_image + name = local.backend-api-name + + env_from { + config_map_ref { + name = kubernetes_config_map.backend-api-config.metadata[0].name + } + } + port { + container_port = local.server_port + name = "api-port" + } + + volume_mount { + mount_path = "/usr/share/nginx/html" + name = "api-config" + } + } + volume { + name = "api-config" + config_map { + name = kubernetes_config_map.backend-api-config.metadata.0.name + } + } + } + } + } +} + +resource "kubernetes_config_map" "backend-api-config" { + metadata { + name = local.backend-api-name + } + + data = { + "data.json" : jsonencode({ message = "Hello World!" }) + } +} + +resource "kubernetes_service" "backend-api-service" { + metadata { + name = local.backend-api-name + } + spec { + selector = { + app = kubernetes_deployment.backend-api.spec.0.template.0.metadata[0].labels.app + } + port { + name = "api-port" + port = local.server_port + target_port = local.server_port + } + } +} + +resource "kubernetes_ingress_v1" "backend-api-ingress" { + metadata { + name = local.backend-api-name + annotations = { + "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" + "nginx.ingress.kubernetes.io/use-regex" = "true" + } + } + spec { + ingress_class_name = "nginx" + rule { + http { + path { + path = "/${var.participant.name}/${local.backend-api-name}(/|$)(.*)" + backend { + service { + name = kubernetes_service.backend-api-service.metadata.0.name + port { + number = local.server_port + } + } + } + } + } + } + } +} diff --git a/deployment/modules/participant/connector.tf b/deployment/modules/participant/connector.tf new file mode 100644 index 0000000..e7655b1 --- /dev/null +++ b/deployment/modules/participant/connector.tf @@ -0,0 +1,109 @@ +locals { + connector_release_name = "${var.participant.name}-connector" + + ################## + ## IMPORT NOTE! ## + ############################################################################################ + # These URLs must be the external routes exposed by the participant over the public internet + # which, are typically exposed through an API gateway, an external Load Balancer... + # In the case of this MVD we use internal routes for simplicity, but this should not + # reproduce in prod-grade deployment as all connectors of a dataspace will not be deployed + # in the same Kubernetes cluster in the real life + ############################################################################################ + protocol_url = "http://${local.connector_release_name}:8282/api/dsp" + public_url = "http://${local.connector_release_name}:8484/api/public" +} + +resource "helm_release" "connector" { + name = local.connector_release_name + cleanup_on_fail = true + dependency_update = true + recreate_pods = true + repository = var.helm_chart_repo + chart = var.connector_chart_name + version = var.connector_version + + values = [ + yamlencode({ + + "imagePullSecrets" : [ + { + "name" : var.docker_image_pull_secret_name + } + ], + + "connector" : { + "image" : { + "repository" : var.connector_repo + "tag" : var.connector_version + }, + "keys" : { + // use the same key pair for simplicity + "dataplane" : { + "privateKeyVaultAlias" : local.privatekey_alias, + "publicKeyVaultAlias" : local.publickey_alias + }, + "sts" : { + "privateKeyVaultAlias" : local.privatekey_alias, + "publicKeyDid" : local.did_url + } + }, + "did" : { + "web" : { + "url" : local.did_url + "useHttps" : false + } + }, + "trustedIssuers" : { + "authority" : { + "did" : "did:web:authority-identityhub%3A8383:api:did" + } + }, + "ingress" : { + "enabled" : true + "className" : "nginx" + "annotations" : { + "nginx.ingress.kubernetes.io/ssl-redirect" : "false" + "nginx.ingress.kubernetes.io/use-regex" : "true" + "nginx.ingress.kubernetes.io/rewrite-target" : "/api/$1$2" + }, + "endpoints" : [ + { + "port" : 8181, + "path" : "/${var.participant.name}/cp/(management)(.*)" + }, + { + "port" : 8282, + "path" : "/${var.participant.name}/cp/(dsp)(.*)" + }, + { + "port" : 8484, + "path" : "/${var.participant.name}/dp/(public)(.*)" + }, + { + "port" : 8585, + "path" : "/${var.participant.name}/dp/(data)(.*)" + } + ] + }, + "url" : { + "public" : local.public_url + }, + "postgresql" : { + "jdbcUrl" : "jdbc:postgresql://${var.postgres_host}/${var.participant.name}", + "secret" : { + "name" : var.postgres_credentials_secret_name + } + }, + "vault" : { + "hashicorp" : { + "url" : module.vault.vault_url + "token" : module.vault.vault_token + } + } + } + }) + ] + + depends_on = [module.vault] +} \ No newline at end of file diff --git a/deployment/modules/participant/identityhub.tf b/deployment/modules/participant/identityhub.tf new file mode 100644 index 0000000..79f559d --- /dev/null +++ b/deployment/modules/participant/identityhub.tf @@ -0,0 +1,103 @@ +locals { + identityhub_release_name = "${var.participant.name}-identityhub" + + ################## + ## IMPORT NOTE! ## + ############################################################################################ + # These URLs must be the external routes exposed by the participant over the public internet + # which, are typically exposed through an API gateway, an external Load Balancer... + # In the case of this MVD we use internal routes for simplicity, but this should not + # reproduce in prod-grade deployment as all connectors of a dataspace will not be deployed + # in the same Kubernetes cluster in the real life + ############################################################################################ + did_url = "did:web:${local.identityhub_release_name}%3A8383:api:did" +} + +############################ +## VERIFIABLE CREDENTIALS ## +############################ + +resource "kubernetes_config_map" "verifiable-credentials" { + + metadata { + name = "${local.identityhub_release_name}-credentials" + } + + data = { + "credentials.json" = jsonencode(var.participant.vc) + + } +} + +resource "helm_release" "identity-hub" { + name = local.identityhub_release_name + cleanup_on_fail = true + dependency_update = true + recreate_pods = true + repository = var.helm_chart_repo + chart = var.identityhub_chart_name + version = var.identityhub_version + + values = [ + yamlencode({ + + "imagePullSecrets" : [ + { + "name" : var.docker_image_pull_secret_name + } + ], + + "identityhub" : { + "image" : { + "repository" : var.identityhub_repo + "tag" : var.identityhub_version + }, + "keys" : { + "sts" : { + "publicKeyVaultAlias" : local.publickey_alias + } + }, + "did" : { + "web" : { + "url" : local.did_url, + "useHttps" : false + } + }, + "postgresql" : { + "jdbcUrl" : "jdbc:postgresql://${var.postgres_host}/${var.participant.name}", + "secret" : { + "name" : var.postgres_credentials_secret_name + } + }, + "ingress" : { + "enabled" : true + "className" : "nginx" + "annotations" : { + "nginx.ingress.kubernetes.io/ssl-redirect" : "false" + "nginx.ingress.kubernetes.io/use-regex" : "true" + "nginx.ingress.kubernetes.io/rewrite-target" : "/api/$1$2" + }, + "endpoints" : [ + { + "port" : 8181, + "path" : "/${var.participant.name}/ih/(management)(.*)" + }, + { + "port" : 8282, + "path" : "/${var.participant.name}/ih/(resolution)(.*)" + } + ] + }, + "vault" : { + "hashicorp" : { + "url" : module.vault.vault_url + "token" : module.vault.vault_token + } + } + } + + }) + ] + + depends_on = [module.vault] +} \ No newline at end of file diff --git a/deployment/modules/participant/main.tf b/deployment/modules/participant/main.tf index f1861e9..fd9037d 100644 --- a/deployment/modules/participant/main.tf +++ b/deployment/modules/participant/main.tf @@ -1,306 +1,10 @@ locals { - release_name = var.participant.name - privatekey_alias = var.participant.name publickey_alias = "${local.privatekey_alias}-pub" - - default_token_validity = 3600 - crawler_inital_delay = 30 - crawler_execution_period = 30 - - ################## - ## IMPORT NOTE! ## - ############################################################################################ - # These URLs must be the external routes exposed by the participant over the public internet - # which, are typically exposed through an API gateway, an external Load Balancer... - # In the case of this MVD we use internal routes for simplicity, but this should not - # reproduce in prod-grade deployment as all connectors of a dataspace will not be deployed - # in the same Kubernetes cluster in the real life - ############################################################################################ - protocol_url = "http://${local.release_name}-connector:8282/api/dsp" - public_url = "http://${local.release_name}-connector:8484/api/public" - identity_url = "http://${local.release_name}-connector:8686/api/identity" - did_url = "did:web:${local.release_name}-didserver%3A8080:webdid" # see https://w3c-ccg.github.io/did-method-web/ - - newman_image = "postman/newman:ubuntu" - vault_token = "root" - vault_port = 8200 -} - -####################### -## GENERATE KEY PAIR ## -####################### -resource "tls_private_key" "private-key" { - algorithm = "ECDSA" - ecdsa_curve = "P256" -} - -data "tls_public_key" "public-key" { - private_key_pem = tls_private_key.private-key.private_key_pem -} - -data "jwks_from_key" "public-key-jwk" { - key = data.tls_public_key.public-key.public_key_pem - kid = var.participant.name -} - -######################################## -## HASHICORP VAULT + KEY PAIR SEEDING ## -######################################## -resource "helm_release" "vault" { - repository = "https://helm.releases.hashicorp.com" - chart = "vault" - name = "${var.participant.name}-vault" - wait_for_jobs = true - - values = [ - yamlencode({ - "injector" : { - "enabled" : false - } - "server" : { - "dev" : { - "enabled" : true, - "devRootToken" : local.vault_token - }, - "readinessProbe" : { - "path" : "/v1/sys/health" - } - } - }) - ] -} - -resource "kubernetes_config_map" "vault-seeding-config" { - - depends_on = [helm_release.vault] - - metadata { - name = "${var.participant.name}-vault-seeder-config" - } - - data = { - "secrets_seeding.postman_collection.json" = file("${path.module}/vault_seeding.json") - } } -resource "kubernetes_job" "vault-seeding-job" { - - depends_on = [helm_release.vault] - - metadata { - name = "${var.participant.name}-vault-seeding-job" - } - - spec { - template { - metadata {} - spec { - container { - name = "${var.participant.name}-newman" - image = local.newman_image - - args = [ - "run", - "secrets_seeding.postman_collection.json", - "--env-var", - "vaultUrl=http://${var.participant.name}-vault:8200/v1/secret/data", - "--env-var", - "vaultToken=root", - "--env-var", - "publicKeyAlias=${local.publickey_alias}", - "--env-var", - "publicKey=${replace(data.tls_public_key.public-key.public_key_pem, "\n", "\\n")}", - "--env-var", - "privateKeyAlias=${local.privatekey_alias}", - "--env-var", - "privateKey=${replace(tls_private_key.private-key.private_key_pem, "\n", "\\n")}" - ] - - working_dir = "/vault" - - volume_mount { - mount_path = "/vault" - name = "postman" - } - } - - volume { - name = "postman" - config_map { - name = kubernetes_config_map.vault-seeding-config.metadata.0.name - } - } - } - } - } -} - -################### -## VAULT INGRESS ## -################### -resource "kubernetes_ingress_v1" "vault-ingress" { - metadata { - name = "${var.participant.name}-vault-ingress" - annotations = { - "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" - "nginx.ingress.kubernetes.io/use-regex" = "true" - } - } - spec { - ingress_class_name = "nginx" - rule { - http { - path { - path = "/${var.participant.name}/vault(/|$)(.*)" - backend { - service { - name = helm_release.vault.metadata.0.name - port { - number = local.vault_port - } - } - } - } - } - } - } -} - -########################### -## PARTICIPANT CONNECTOR ## -########################### - -resource "helm_release" "connector" { - name = local.release_name - cleanup_on_fail = true - dependency_update = true - recreate_pods = true - repository = var.connector_helm_chart_repo - chart = "connector" - version = var.connector_version - - values = [ - yamlencode({ - "fullnameOverride" : var.participant.name, - - "imagePullSecrets" : [ - { - "name" : var.docker_image_pull_secret_name - } - ], - - "participant" : { - "name" : var.participant.name - "legalName" : var.participant.legalName - "countryCode" : var.participant.headquarterCountryCode - "countrySubdivisionCode" : var.participant.headquarterCountrySubdivisionCode - }, - - "connector" : { - "image" : { - "repository" : var.connector_docker_image_repo - "tag" : var.connector_version - }, - "security" : { - "privatekey" : local.privatekey_alias - "publickey" : local.publickey_alias - }, - "transfer" : { - "token" : { - "validity" : local.default_token_validity - } - }, - "ingress" : { - "enabled" : true - "className" : "nginx" - "annotations" : { - "nginx.ingress.kubernetes.io/ssl-redirect" : "false" - "nginx.ingress.kubernetes.io/use-regex" : "true" - "nginx.ingress.kubernetes.io/rewrite-target" : "/api/$1$2" - }, - "endpoints" : [ - { - "port" : 8181, - "path" : "/${var.participant.name}/(management)(.*)" - }, - { - "port" : 8282, - "path" : "/${var.participant.name}/(dsp)(.*)" - }, - { - "port" : 8484, - "path" : "/${var.participant.name}/(public)(.*)" - }, - { - "port" : 8585, - "path" : "/${var.participant.name}/(data)(.*)" - }, - { - "port" : 8686, - "path" : "/${var.participant.name}/(identity)(.*)" - } - ] - }, - "crawler" : { - "registrationServiceUrl" : var.registration_service_url, - "cache" : { - "executionPeriodSeconds" : local.crawler_execution_period - "executionDelaySeconds" : local.crawler_inital_delay - } - }, - "url" : { - "protocol" : local.protocol_url - "identity" : local.identity_url - "public" : local.public_url - }, - "postgresql" : { - "jdbcUrl" : "jdbc:postgresql://${var.postgres_host}/${var.participant.name}", - "secret" : { - "name" : var.postgres_credentials_secret_name - } - }, - "vault" : { - "hashicorp" : { - "url" : "http://${var.participant.name}-vault:${local.vault_port}" - "token" : local.vault_token - } - } - }, - - "didserver" : { - "ingress" : { - "enabled" : true, - "className" : "nginx", - "annotations" : { - "nginx.ingress.kubernetes.io/ssl-redirect" : "false" - "nginx.ingress.kubernetes.io/use-regex" : "true" - "nginx.ingress.kubernetes.io/rewrite-target" : "/$2" - }, - "endpoints" : [ - { - "port" : 8080, - "path" : "/${var.participant.name}/didserver(/|$)(.*)" - } - ] - } - }, - - "ssi" : { - "did" : { - "web" : { - "url" : local.did_url, - "useHttps" : false - }, - "document" : { - "publickey" : { - "jwk" : data.jwks_from_key.public-key-jwk.jwks - } - } - } - } - }) - ] +module "vault" { + source = "../vault" - depends_on = [kubernetes_job.vault-seeding-job] + participant_name = var.participant.name } \ No newline at end of file diff --git a/deployment/modules/participant/providers.tf b/deployment/modules/participant/providers.tf index e70c849..9bc2649 100644 --- a/deployment/modules/participant/providers.tf +++ b/deployment/modules/participant/providers.tf @@ -3,13 +3,5 @@ terraform { helm = { source = "hashicorp/helm" } - - tls = { - source = "hashicorp/tls" - } - - jwks = { - source = "iwarapter/jwks" - } } } \ No newline at end of file diff --git a/deployment/modules/participant/variables.tf b/deployment/modules/participant/variables.tf index 6e797b1..62e2366 100644 --- a/deployment/modules/participant/variables.tf +++ b/deployment/modules/participant/variables.tf @@ -1,22 +1,24 @@ variable "participant" { type = object({ - name = string, - legalName = string, - headquarterCountryCode = string - headquarterCountrySubdivisionCode = string + name = string, + vc = list(any) }) } -variable "connector_docker_image_repo" {} - -variable "connector_helm_chart_repo" {} +# POSTGRES +variable "postgres_host" {} +variable "postgres_credentials_secret_name" {} +# FEDERATED CATALOG +variable "connector_repo" {} +variable "connector_chart_name" {} variable "connector_version" {} -variable "registration_service_url" {} - -variable "postgres_host" {} - -variable "postgres_credentials_secret_name" {} +# IDENTITY HUB +variable "identityhub_repo" {} +variable "identityhub_chart_name" {} +variable "identityhub_version" {} +# DOCKER PULL +variable "helm_chart_repo" {} variable "docker_image_pull_secret_name" {} \ No newline at end of file diff --git a/deployment/modules/participant/vault_seeding.json b/deployment/modules/participant/vault_seeding.json deleted file mode 100644 index 099378f..0000000 --- a/deployment/modules/participant/vault_seeding.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "info": { - "_postman_id": "255ea7b9-c9a7-43cb-a622-80aa621459e6", - "name": "Participant secret seeding", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "Public key", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"data\": {\r\n \"content\": \"{{publicKey}}\"\r\n }\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{vaultUrl}}/{{publicKeyAlias}}", - "host": [ - "{{vaultUrl}}" - ], - "path": [ - "{{publicKeyAlias}}" - ] - } - }, - "response": [] - }, - { - "name": "Private key", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"data\": {\r\n \"content\": \"{{privateKey}}\"\r\n }\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{vaultUrl}}/{{privateKeyAlias}}", - "host": [ - "{{vaultUrl}}" - ], - "path": [ - "{{privateKeyAlias}}" - ] - } - }, - "response": [] - } - ], - "auth": { - "type": "apikey", - "apikey": [ - { - "key": "value", - "value": "{{vaultToken}}", - "type": "string" - }, - { - "key": "key", - "value": "X-Vault-Token", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "pm.test(\"Status code is 200 or 204\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([204, 200])", - "});" - ] - } - } - ], - "variable": [ - { - "key": "vaultUrl", - "value": "" - }, - { - "key": "vaultToken", - "value": "" - }, - { - "key": "publicKeyAlias", - "value": "" - }, - { - "key": "publicKey", - "value": "" - }, - { - "key": "privateKeyAlias", - "value": "" - }, - { - "key": "privateKey", - "value": "" - } - ] -} \ No newline at end of file diff --git a/deployment/modules/registration-service-mock/main.tf b/deployment/modules/registration-service-mock/main.tf deleted file mode 100644 index affbd53..0000000 --- a/deployment/modules/registration-service-mock/main.tf +++ /dev/null @@ -1,135 +0,0 @@ -locals { - server_image = "nginxinc/nginx-unprivileged:1.25.3" -} - -resource "kubernetes_deployment" "rs-mock" { - metadata { - name = var.name - labels = { - app = var.name - } - } - - spec { - replicas = 1 - selector { - match_labels = { - app = var.name - } - } - template { - metadata { - labels = { - app = var.name - } - } - spec { - container { - image = local.server_image - name = var.name - - env_from { - config_map_ref { - name = kubernetes_config_map.rs-mock-config.metadata[0].name - } - } - port { - container_port = var.server_port - name = "rs-mock-port" - } - - volume_mount { - mount_path = "/usr/share/nginx/html/registry" - name = "participants-config" - } - - # Uncomment this to assign (more) resources - # resources { - # limits = { - # cpu = "2" - # memory = "512Mi" - # } - # requests = { - # cpu = "250m" - # memory = "50Mi" - # } - # } - # liveness_probe { - # http_get { - # path = "/" - # port = "8080" - # } - # failure_threshold = 10 - # period_seconds = 5 - # timeout_seconds = 30 - # } - } - volume { - name = "participants-config" - config_map { - name = kubernetes_config_map.rs-mock-config.metadata.0.name - } - } - } - } - } -} - -resource "kubernetes_config_map" "rs-mock-config" { - metadata { - name = "rs-mock-config" - } - - data = { - "participants" : jsonencode([ - for p in var.participants_did : { - did : p, - status : "ONBOARDED" - } - ]) - } -} - -resource "kubernetes_service" "rs-mock-service" { - metadata { - name = var.name - } - spec { - selector = { - app = kubernetes_deployment.rs-mock.spec.0.template.0.metadata[0].labels.app - } - port { - name = "rs-mock-port" - port = var.server_port - target_port = var.server_port - } - } -} - -resource "kubernetes_ingress_v1" "rs-mock-ingress" { - metadata { - name = "rs-mock-ingress" - annotations = { - "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" - "nginx.ingress.kubernetes.io/use-regex" = "true" - } - } - spec { - ingress_class_name = "nginx" - rule { - http { - path { - path = "/${var.name}(/|$)(.*)" - backend { - service { - name = kubernetes_service.rs-mock-service.metadata.0.name - port { - number = var.server_port - } - } - } - } - } - } - } -} diff --git a/deployment/modules/registration-service-mock/output.tf b/deployment/modules/registration-service-mock/output.tf deleted file mode 100644 index 80f1224..0000000 --- a/deployment/modules/registration-service-mock/output.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "registration_service_host" { - value = "${kubernetes_service.rs-mock-service.metadata.0.name}:${var.server_port}" -} \ No newline at end of file diff --git a/deployment/modules/registration-service-mock/providers.tf b/deployment/modules/registration-service-mock/providers.tf deleted file mode 100644 index 50c6991..0000000 --- a/deployment/modules/registration-service-mock/providers.tf +++ /dev/null @@ -1,7 +0,0 @@ -terraform { - required_providers { - kubernetes = { - source = "hashicorp/kubernetes" - } - } -} \ No newline at end of file diff --git a/deployment/modules/registration-service-mock/variables.tf b/deployment/modules/registration-service-mock/variables.tf deleted file mode 100644 index f4b0c08..0000000 --- a/deployment/modules/registration-service-mock/variables.tf +++ /dev/null @@ -1,7 +0,0 @@ -variable "participants_did" { - type = list(string) -} - -variable "name" {} - -variable "server_port" {} \ No newline at end of file diff --git a/deployment/modules/vault/main.tf b/deployment/modules/vault/main.tf new file mode 100644 index 0000000..171dbfe --- /dev/null +++ b/deployment/modules/vault/main.tf @@ -0,0 +1,62 @@ +locals { + vault_token = "root" + vault_port = 8200 +} + +######################################## +## HASHICORP VAULT + KEY PAIR SEEDING ## +######################################## +resource "helm_release" "vault" { + repository = "https://helm.releases.hashicorp.com" + chart = "vault" + name = "${var.participant_name}-vault" + wait_for_jobs = true + + values = [ + yamlencode({ + "injector" : { + "enabled" : false + } + "server" : { + "dev" : { + "enabled" : true, + "devRootToken" : local.vault_token + }, + "readinessProbe" : { + "path" : "/v1/sys/health" + } + } + }) + ] +} + +#################### +### VAULT INGRESS ## +#################### +resource "kubernetes_ingress_v1" "vault-ingress" { + metadata { + name = "${var.participant_name}-vault-ingress" + annotations = { + "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" + "nginx.ingress.kubernetes.io/use-regex" = "true" + } + } + spec { + ingress_class_name = "nginx" + rule { + http { + path { + path = "/${var.participant_name}/vault(/|$)(.*)" + backend { + service { + name = helm_release.vault.metadata.0.name + port { + number = local.vault_port + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/deployment/modules/vault/output.tf b/deployment/modules/vault/output.tf new file mode 100644 index 0000000..f54a71f --- /dev/null +++ b/deployment/modules/vault/output.tf @@ -0,0 +1,7 @@ +output "vault_url" { + value = "http://${var.participant_name}-vault:${local.vault_port}" +} + +output "vault_token" { + value = local.vault_token +} \ No newline at end of file diff --git a/deployment/modules/vault/providers.tf b/deployment/modules/vault/providers.tf new file mode 100644 index 0000000..154e7de --- /dev/null +++ b/deployment/modules/vault/providers.tf @@ -0,0 +1,4 @@ +terraform { + required_providers { + } +} \ No newline at end of file diff --git a/deployment/modules/vault/variables.tf b/deployment/modules/vault/variables.tf new file mode 100644 index 0000000..7ddefa3 --- /dev/null +++ b/deployment/modules/vault/variables.tf @@ -0,0 +1,9 @@ +variable "participant_name" {} + +#variable "publickey_alias" {} +# +#variable "publickey" {} +# +#variable "privatekey_alias" {} +# +#variable "privatekey" {} \ No newline at end of file diff --git a/deployment/providers.tf b/deployment/providers.tf index a400a44..1590a9a 100644 --- a/deployment/providers.tf +++ b/deployment/providers.tf @@ -7,14 +7,6 @@ terraform { helm = { source = "hashicorp/helm" } - - tls = { - source = "hashicorp/tls" - } - - jwks = { - source = "iwarapter/jwks" - } } } @@ -29,7 +21,7 @@ provider "helm" { } registry { - url = var.connector_helm_chart_repo + url = var.helm_chart_repo username = var.container_registry_username password = var.container_registry_token } diff --git a/deployment/readme.md b/deployment/readme.md index 24bca12..e77c6f9 100644 --- a/deployment/readme.md +++ b/deployment/readme.md @@ -33,7 +33,7 @@ You need a token to pull the Docker image of the Eona-X connector. This token is Once you obtained your token, you'll have _inject_ in the Terraform script. Simply run the following command: ```bash -echo 'docker_image_pull_token = ""' > terraform.tfvars +echo 'container_registry_token = ""' > terraform.tfvars ``` ## Deploy the dataspace diff --git a/deployment/variables.tf b/deployment/variables.tf index d5f7ae3..92b9a7d 100644 --- a/deployment/variables.tf +++ b/deployment/variables.tf @@ -1,34 +1,142 @@ -############################# -## PARTICIPANTS PARAMETERS ## -############################# - -variable "participants" { - type = list(object({ - name = string, - legalName = string, - headquarterCountryCode = string - headquarterCountrySubdivisionCode = string - })) - - default = [ - { - name : "company1", - legalName : "Company 1", - headquarterCountryCode : "FR", - headquarterCountrySubdivisionCode : "IDF" - }, - { - name : "company2", - legalName : "Company 2", - headquarterCountryCode : "FR", - headquarterCountrySubdivisionCode : "IDF" - } - ] -} - -########################## -## CONNECTOR PARAMETERS ## -########################## +############### +## DATASPACE ## +############### + +variable "data_provider" { + type = object({ + name = string, + vc = list(any) + }) + + default = { + name : "provider", + vc : [ + { + "rawVc" : "eyJraWQiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsInN1YiI6ImRpZDp3ZWI6cHJvdmlkZXItaWRlbnRpdHlodWIlM0E4MzgzOmFwaTpkaWQiLCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6W3siaWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBODM4MzphcGk6ZGlkIiwibWVtYmVyc2hpcCI6eyJtZW1iZXJzaGlwVHlwZSI6IkZ1bGxNZW1iZXIiLCJ3ZWJzaXRlIjoid3d3LnNvbWUtb3RoZXItd2Vic2l0ZS5jb20iLCJjb250YWN0IjoiYmFyLmJhekBjb21wYW55LmNvbSIsInNpbmNlIjoiMjAyMy0wMS0wMVQwMDowMDowMFoifX1dLCJpZCI6IjkwNGEzMzFkLTJmNzQtNGU5Zi05Mzk5LTYzNGY0NjBiZWNlNyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJNZW1iZXJzaGlwQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOnsiaWQiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjp7fX0sImlzc3VhbmNlRGF0ZSI6IjIwMjQtMDItMjBUMTY6Mjc6MTZaIiwiZXhwaXJhdGlvbkRhdGUiOm51bGwsImNyZWRlbnRpYWxTdGF0dXMiOm51bGwsImRlc2NyaXB0aW9uIjpudWxsLCJuYW1lIjpudWxsfSwiaWF0IjoxNzA4NDQ2NDM2fQ.tok0NQZJqy8TUOlGNvPf0qus39n2HVjX80zAMDqC19wwr25hSTGVQ5331GC2vDR7ldgc6eoyFFz6o2UkpN0qKA", + "format" : "JWT", + "credential" : { + "credentialSubject" : [ + { + "id" : "did:web:provider-identityhub%3A8383:api:did", + "membership" : { + "membershipType" : "FullMember", + "website" : "www.some-other-website.com", + "contact" : "bar.baz@company.com", + "since" : "2023-01-01T00:00:00Z" + } + } + ], + "id" : "904a331d-2f74-4e9f-9399-634f460bece7", + "type" : [ + "VerifiableCredential", + "MembershipCredential" + ], + "issuer" : { + "id" : "did:web:authority-identityhub%3A8383:api:did", + "additionalProperties" : {} + }, + "issuanceDate" : "2024-02-20T16:27:16Z", + "expirationDate" : null, + "credentialStatus" : null, + "description" : null, + "name" : null + } + } + ] + } +} + +variable "data_consumer" { + type = object({ + name = string, + vc = list(any) + }) + + default = { + name : "consumer", + vc : [ + { + "rawVc" : "eyJraWQiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsInN1YiI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E4MzgzOmFwaTpkaWQiLCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6W3siaWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkZW50aXR5aHViJTNBODM4MzphcGk6ZGlkIiwibWVtYmVyc2hpcCI6eyJtZW1iZXJzaGlwVHlwZSI6IkZ1bGxNZW1iZXIiLCJ3ZWJzaXRlIjoid3d3LnNvbWUtb3RoZXItd2Vic2l0ZS5jb20iLCJjb250YWN0IjoiYmFyLmJhekBjb21wYW55LmNvbSIsInNpbmNlIjoiMjAyMy0wMS0wMVQwMDowMDowMFoifX1dLCJpZCI6IjIxODZjYjk3LWIzYzAtNDYxYy1hMmNiLWYzMDM1NDMzMWE4MCIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJNZW1iZXJzaGlwQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOnsiaWQiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjp7fX0sImlzc3VhbmNlRGF0ZSI6IjIwMjQtMDItMjBUMTU6NTI6MDNaIiwiZXhwaXJhdGlvbkRhdGUiOm51bGwsImNyZWRlbnRpYWxTdGF0dXMiOm51bGwsImRlc2NyaXB0aW9uIjpudWxsLCJuYW1lIjpudWxsfSwiaWF0IjoxNzA4NDQ0MzIzfQ.w4kVX-PuDsGdTXtjVT6QeaAwaVFlpEandOblVvoVy0C7VtqQnAEe3g0vyyhIhdyJnCyKdmAbkbBKHox-P6Ly1g", + "format" : "JWT", + "credential" : { + "credentialSubject" : [ + { + "id" : "did:web:consumer-identityhub%3A8383:api:did", + "membership" : { + "membershipType" : "FullMember", + "website" : "www.some-other-website.com", + "contact" : "bar.baz@company.com", + "since" : "2023-01-01T00:00:00Z" + } + } + ], + "id" : "2186cb97-b3c0-461c-a2cb-f30354331a80", + "type" : [ + "VerifiableCredential", + "MembershipCredential" + ], + "issuer" : { + "id" : "did:web:authority-identityhub%3A8383:api:did", + "additionalProperties" : {} + }, + "issuanceDate" : "2024-02-20T15:52:03Z", + "expirationDate" : null, + "credentialStatus" : null, + "description" : null, + "name" : null + } + } + ] + } +} + +variable "authority" { + type = object({ + name = string, + vc = list(any) + }) + + default = { + name : "authority", + vc : [ + { + "rawVc" : "eyJraWQiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJkaWQ6d2ViOmF1dGhvcml0eS1pZGVudGl0eWh1YiUzQTgzODM6YXBpOmRpZCIsInN1YiI6ImRpZDp3ZWI6YXV0aG9yaXR5LWlkZW50aXR5aHViJTNBODM4MzphcGk6ZGlkIiwidmMiOnsiY3JlZGVudGlhbFN1YmplY3QiOlt7ImlkIjoiZGlkOndlYjphdXRob3JpdHktaWRlbnRpdHlodWIlM0E4MzgzOmFwaTpkaWQiLCJtZW1iZXJzaGlwIjp7Im1lbWJlcnNoaXBUeXBlIjoiRnVsbE1lbWJlciIsIndlYnNpdGUiOiJ3d3cuc29tZS1vdGhlci13ZWJzaXRlLmNvbSIsImNvbnRhY3QiOiJiYXIuYmF6QGNvbXBhbnkuY29tIiwic2luY2UiOiIyMDIzLTAxLTAxVDAwOjAwOjAwWiJ9fV0sImlkIjoiYzRhYjdjZjMtOGM0Yi00MTA0LWI5MjgtZjlmYzAxMjk5NWU1IiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIk1lbWJlcnNoaXBDcmVkZW50aWFsIl0sImlzc3VlciI6eyJpZCI6ImRpZDp3ZWI6YXV0aG9yaXR5LWlkZW50aXR5aHViJTNBODM4MzphcGk6ZGlkIiwiYWRkaXRpb25hbFByb3BlcnRpZXMiOnt9fSwiaXNzdWFuY2VEYXRlIjoiMjAyNC0wMi0yMFQxMzoyNTowOVoiLCJleHBpcmF0aW9uRGF0ZSI6bnVsbCwiY3JlZGVudGlhbFN0YXR1cyI6bnVsbCwiZGVzY3JpcHRpb24iOm51bGwsIm5hbWUiOm51bGx9LCJpYXQiOjE3MDg0MzU1MDl9.2ibvWS6QBYHLJLk4lVIqiq6Bivo-mEOK9HAXroEtylPEepPnr29-ZIWOxOFsbOVBS0W7o38mQEXWpfvo3f2Ujg", + "format" : "JWT", + "credential" : { + "credentialSubject" : [ + { + "id" : "did:web:authority-identityhub%3A8383:api:did", + "membership" : { + "membershipType" : "FullMember", + "website" : "www.some-other-website.com", + "contact" : "bar.baz@company.com", + "since" : "2023-01-01T00:00:00Z" + } + } + ], + "id" : "c4ab7cf3-8c4b-4104-b928-f9fc012995e5", + "type" : [ + "VerifiableCredential", + "MembershipCredential" + ], + "issuer" : { + "id" : "did:web:authority-identityhub%3A8383:api:did", + "additionalProperties" : {} + }, + "issuanceDate" : "2024-02-20T13:25:09Z", + "expirationDate" : null, + "credentialStatus" : null, + "description" : null, + "name" : null + } + } + ] + } +} + +################# +## DOCKER REPO ## +################# variable "container_registry_username" { default = "amadeusitgroup" @@ -40,14 +148,54 @@ variable "container_registry_token" { description = "(Required) Token for authenticating to the Docker registry" } -variable "connector_docker_image_repo" { +variable "helm_chart_repo" { + default = "oci://ghcr.io/amadeusitgroup/dataspace_ecosystem/helm" +} + +###################### +## EONA-X CONNECTOR ## +###################### + +variable "connector_repo" { default = "ghcr.io/amadeusitgroup/dataspace_ecosystem/eonax-connector-postgresql-hashicorpvault" } -variable "connector_helm_chart_repo" { - default = "oci://ghcr.io/amadeusitgroup/dataspace_ecosystem/helm" +variable "connector_chart_name" { + default = "connector" } variable "connector_version" { - default = "v0.4.1-fix.3" + default = "v0.5.2" +} + +######################### +## EONA-X IDENTITY HUB ## +######################### + +variable "identityhub_repo" { + default = "ghcr.io/amadeusitgroup/dataspace_ecosystem/eonax-identity-hub-postgresql-hashicorpvault" +} + +variable "identityhub_chart_name" { + default = "identityhub" +} + +variable "identityhub_version" { + default = "v0.5.2" +} + +############################## +## EONA-X FEDERATED CATALOG ## +############################## + +variable "federatedcatalog_repo" { + default = "ghcr.io/amadeusitgroup/dataspace_ecosystem/eonax-federated-catalog-hashicorpvault" } + +variable "federatedcatalog_chart_name" { + default = "federatedcatalog" +} + +variable "federatedcatalog_version" { + default = "v0.5.2" +} \ No newline at end of file