diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index bf3043719..6aa711831 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -44,79 +44,62 @@ jobs: - name: "Setup Helm" uses: azure/setup-helm@v4 - with: - version: v3.8.1 - name: "Setup Kubectl" uses: azure/setup-kubectl@v4 - - - name: "Set up OpenTofu" - uses: opentofu/setup-opentofu@v2 - - uses: actions/checkout@v6 - - uses: eclipse-edc/.github/.github/actions/setup-build@main - name: "Build runtime images" working-directory: ./ run: | - ./gradlew -Ppersistence=true dockerize - + ./gradlew dockerize - name: "Create k8s Kind Cluster" uses: helm/kind-action@v1.14.0 with: - config: deployment/kind.config.yaml cluster_name: dcp-demo - name: "Load runtime images into KinD" - run: kind load docker-image controlplane:latest dataplane:latest identity-hub:latest catalog-server:latest issuerservice:latest -n dcp-demo - - - name: "Install nginx ingress controller" + run: | + kind load docker-image -n dcp-demo \ + ghcr.io/eclipse-edc/mvd/controlplane:latest \ + ghcr.io/eclipse-edc/mvd/dataplane:latest \ + ghcr.io/eclipse-edc/mvd/identity-hub:latest \ + ghcr.io/eclipse-edc/mvd/issuerservice:latest + + - name: "Install Traefik Gateway controller" run: |- - echo "::notice title=nginx ingress on KinD::For details how to run nginx ingress on KinD check https://kind.sigs.k8s.io/docs/user/ingress/#ingress-nginx" - kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml - kubectl wait --namespace ingress-nginx \ - --for=condition=ready pod \ - --selector=app.kubernetes.io/component=controller \ - --timeout=90s + helm repo add traefik https://traefik.github.io/charts + helm repo update + helm upgrade --install --namespace traefik traefik traefik/traefik --create-namespace -f values.yaml + # Wait for traefik to be ready + kubectl rollout status deployment/traefik -n traefik --timeout=120s + # forward port 80 -> 8080 + kubectl -n traefik port-forward svc/traefik 8080:80 & - - name: "Tofu init" - working-directory: ./deployment - run: |- - tofu init -reconfigure - - name: "Tofu plan" - working-directory: ./deployment - run: |- - tofu plan -out=$GITHUB_SHA.out + # install Gateway API CRDs + kubectl apply --server-side --force-conflicts -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/experimental-install.yaml + + sleep 5 # to be safe` - - name: "Tofu apply" - working-directory: ./deployment + - name: "Deploy MVD" run: |- - tofu apply "$GITHUB_SHA.out" + kubectl apply -k k8s/ - - name: "Seed dataspace" + - name: "Wait for MVD to be ready" run: |- - chmod +x seed-k8s.sh - ./seed-k8s.sh + kubectl wait -A \ + --selector=type=edc-job \ + --for=condition=complete job --all \ + --timeout=180s - name: "Run E2E Test" run: |- ./gradlew -DincludeTags="EndToEndTest" test -DverboseTest=true - - name: "Run Newman" - continue-on-error: true - working-directory: ./deployment/postman - run: |- - newman run "MVD.postman_collection.json" -e "MVD K8S.postman_environment.json" --folder "ControlPlane Management" --delay-request 5000 --verbose - - - name: "Print log if test failed" - if: failure() - run: |- - kubectl logs deployment/provider-qna-controlplane -n mvd - - name: "Destroy the KinD cluster" run: >- kind delete cluster -n dcp-demo diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 61707ba9d..401863222 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -62,13 +62,3 @@ jobs: - uses: eclipse-edc/.github/.github/actions/setup-build@main - name: Run Checkstyle run: ./gradlew checkstyleMain checkstyleTest - - validate-terraform: - runs-on: ubuntu-latest - steps: - - uses: hashicorp/setup-terraform@v4 - - uses: actions/checkout@v6 - - name: Check Terraform files are properly formatted (run "terraform fmt -recursive" to fix) - run: | - terraform fmt -recursive - git diff --exit-code \ No newline at end of file diff --git a/.run/Connector Consumer Corp.run.xml b/.run/Connector Consumer Corp.run.xml deleted file mode 100644 index 8267531f0..000000000 --- a/.run/Connector Consumer Corp.run.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/Connector _provider-manufacturing_.run.xml b/.run/Connector _provider-manufacturing_.run.xml deleted file mode 100644 index 6f6e95af6..000000000 --- a/.run/Connector _provider-manufacturing_.run.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/Connector _provider-qna_.run.xml b/.run/Connector _provider-qna_.run.xml deleted file mode 100644 index e0884a6dd..000000000 --- a/.run/Connector _provider-qna_.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/IdentityHub Consumer Corp.run.xml b/.run/IdentityHub Consumer Corp.run.xml deleted file mode 100644 index 86896c70b..000000000 --- a/.run/IdentityHub Consumer Corp.run.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/IdentityHub Provider Corp.run.xml b/.run/IdentityHub Provider Corp.run.xml deleted file mode 100644 index 2fd35b8b5..000000000 --- a/.run/IdentityHub Provider Corp.run.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/IssuerService.run.xml b/.run/IssuerService.run.xml deleted file mode 100644 index ec950ca19..000000000 --- a/.run/IssuerService.run.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/Provider Catalog Server.run.xml b/.run/Provider Catalog Server.run.xml deleted file mode 100644 index 0a8ea2688..000000000 --- a/.run/Provider Catalog Server.run.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/dataspace.run.xml b/.run/dataspace.run.xml deleted file mode 100644 index 07a8593da..000000000 --- a/.run/dataspace.run.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.run/remote/Catalog Server PROVIDER.run.xml b/.run/remote/Catalog Server PROVIDER.run.xml deleted file mode 100644 index 42ec8dd1b..000000000 --- a/.run/remote/Catalog Server PROVIDER.run.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/remote/Connector .run.xml b/.run/remote/Connector .run.xml deleted file mode 100644 index 08726f829..000000000 --- a/.run/remote/Connector .run.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/remote/IdentityHub CONSUMER.run.xml b/.run/remote/IdentityHub CONSUMER.run.xml deleted file mode 100644 index 22be6d2c7..000000000 --- a/.run/remote/IdentityHub CONSUMER.run.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/.run/remote/IdentityHub PROVIDER.run.xml b/.run/remote/IdentityHub PROVIDER.run.xml deleted file mode 100644 index 3fbbad1b3..000000000 --- a/.run/remote/IdentityHub PROVIDER.run.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/README.md b/README.md index b0d71a4df..efa4cacb3 100644 --- a/README.md +++ b/README.md @@ -741,7 +741,7 @@ a token in the Authorization header, which authorizes the verifier to obtain the consumer's IdentityHub. We achieve this by intercepting the DSP request and adding the correct scope - here: -`"org.eclipse.edc.vc.type:MembershipCredential:read"` - to the request builder. Technically, this is achieved by +`"org.eclipse.dspace.dcp.vc.type:MembershipCredential:read"` - to the request builder. Technically, this is achieved by registering a `postValidator` function for the relevant policy scopes, check out the [DcpPatchExtension.java](extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DcpPatchExtension.java) class. @@ -769,7 +769,7 @@ relevant scope string to the access token upon DSP egress. A policy, that requir The [DataAccessCredentialScopeExtractor.java](extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DataAccessCredentialScopeExtractor.java) -class would convert this into a scope string `org.eclipse.edc.vc.type:DataProcessorCredential:read` and add it to the +class would convert this into a scope string `org.eclipse.dspace.dcp.vc.type:DataProcessorCredential:read` and add it to the consumer's access token. ### 8.4 Policy evaluation functions @@ -934,7 +934,7 @@ deliver a credential of type `DemoCredential` to the consumer's IdentityHub. ### 10.4 Default scope-to-criterion transformer When IdentityHub receives a Presentation query, that carries an access token, it must be able to convert a scope string -into a filter expression, for example `org.eclipse.edc.vc.type:DataProcessorCredential:read` is converted into +into a filter expression, for example `org.eclipse.dspace.dcp.vc.type:DataProcessorCredential:read` is converted into `verifiableCredential.credential.type = DataProcessorCredential`. This filter expression is then used by IdentityHub to query for `DataProcessorCredentials` in the database. diff --git a/build.gradle.kts b/build.gradle.kts index ae06123f4..eb529ac92 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,8 +39,8 @@ subprojects { tasks.register("dockerize", DockerBuildImage::class) { val dockerContextDir = project.projectDir dockerFile.set(file("$dockerContextDir/src/main/docker/Dockerfile")) - images.add("${project.name}:${project.version}") - images.add("${project.name}:latest") + images.add("ghcr.io/eclipse-edc/mvd/${project.name}:${project.version}") + images.add("ghcr.io/eclipse-edc/mvd/${project.name}:latest") // specify platform with the -Dplatform flag: if (System.getProperty("platform") != null) platform.set(System.getProperty("platform")) diff --git a/deployment/assets/consumer_private.pem b/deployment/assets/consumer_private.pem deleted file mode 100644 index 81c28bac2..000000000 --- a/deployment/assets/consumer_private.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIARDUGJgKy1yzxkueIJ1k3MPUWQ/tbQWQNqW6TjyHpdcoAoGCCqGSM49 -AwEHoUQDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5roYnkAXuqCYfNK3ex+hMWFuiX -GUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== ------END EC PRIVATE KEY----- \ No newline at end of file diff --git a/deployment/assets/consumer_public.pem b/deployment/assets/consumer_public.pem deleted file mode 100644 index 977a19576..000000000 --- a/deployment/assets/consumer_public.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5r -oYnkAXuqCYfNK3ex+hMWFuiXGUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== ------END PUBLIC KEY----- \ No newline at end of file diff --git a/deployment/assets/credentials/k8s/consumer/dataprocessor-credential.json b/deployment/assets/credentials/k8s/consumer/dataprocessor-credential.json deleted file mode 100644 index f7c8f50dc..000000000 --- a/deployment/assets/credentials/k8s/consumer/dataprocessor-credential.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b15", - "participantContextId": "did:web:consumer-identityhub%3A7083:consumer", - "timestamp": 1700659822500, - "issuerId": "did:web:dataspace-issuer", - "holderId": "did:web:consumer-identityhub%3A7083:consumer", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "format": "VC1_0_JWT", - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkZW50aXR5aHViJTNBNzA4MzphbGljZSIsInN1YiI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E3MDgzOmFsaWNlIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L3N1aXRlcy9qd3MtMjAyMC92MSIsImh0dHBzOi8vd3d3LnczLm9yZy9ucy9kaWQvdjEiLHsibXZkLWNyZWRlbnRpYWxzIjoiaHR0cHM6Ly93M2lkLm9yZy9tdmQvY3JlZGVudGlhbHMvIiwiY29udHJhY3RWZXJzaW9uIjoibXZkLWNyZWRlbnRpYWxzOmNvbnRyYWN0VmVyc2lvbiIsImxldmVsIjoibXZkLWNyZWRlbnRpYWxzOmxldmVsIn1dLCJpZCI6Imh0dHA6Ly9vcmcueW91cmRhdGFzcGFjZS5jb20vY3JlZGVudGlhbHMvMjM0NyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJEYXRhUHJvY2Vzc29yQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA4LTE4VDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOndlYjpjb25zdW1lci1pZGVudGl0eWh1YiUzQTcwODM6Y29uc3VtZXIiLCJjb250cmFjdFZlcnNpb24iOiIxLjAuMCIsImxldmVsIjoicHJvY2Vzc2luZyJ9fSwiaWF0IjoxNzQ4ODQ0OTE5fQ.Asd_5HEu-UaV3bSZ3DlkIlI5yiAik18JcAtKwK6HVx3MAW5uR907lEJfgdO29eHfTR9_qiHG5OitXYCpL_sxBQ", - "credential": { - "credentialSubject": [ - { - "claims": { - "id": "did:web:consumer-identityhub%3A7083:consumer", - "contractVersion": "1.0.0", - "level": "processing" - } - } - ], - "id": "http://org.yourdataspace.com/credentials/1235", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": { - "id": "did:web:dataspace-issuer", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/k8s/consumer/dataprocessor_vc.json b/deployment/assets/credentials/k8s/consumer/dataprocessor_vc.json deleted file mode 100644 index fb5154731..000000000 --- a/deployment/assets/credentials/k8s/consumer/dataprocessor_vc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "contractVersion": "mvd-credentials:contractVersion", - "level": "mvd-credentials:level" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": "did:web:dataspace-issuer", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:consumer-identityhub%3A7083:consumer", - "contractVersion": "1.0.0", - "level": "processing" - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/k8s/consumer/membership-credential.json b/deployment/assets/credentials/k8s/consumer/membership-credential.json deleted file mode 100644 index c8d45368d..000000000 --- a/deployment/assets/credentials/k8s/consumer/membership-credential.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b14", - "participantContextId": "did:web:consumer-identityhub%3A7083:consumer", - "timestamp": 1700659822500, - "issuerId": "did:web:dataspace-issuer", - "holderId": "did:web:consumer-identityhub%3A7083:consumer", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkZW50aXR5aHViJTNBNzA4MzphbGljZSIsInN1YiI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E3MDgzOmFsaWNlIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L3N1aXRlcy9qd3MtMjAyMC92MSIsImh0dHBzOi8vd3d3LnczLm9yZy9ucy9kaWQvdjEiLHsibXZkLWNyZWRlbnRpYWxzIjoiaHR0cHM6Ly93M2lkLm9yZy9tdmQvY3JlZGVudGlhbHMvIiwibWVtYmVyc2hpcCI6Im12ZC1jcmVkZW50aWFsczptZW1iZXJzaGlwIiwibWVtYmVyc2hpcFR5cGUiOiJtdmQtY3JlZGVudGlhbHM6bWVtYmVyc2hpcFR5cGUiLCJ3ZWJzaXRlIjoibXZkLWNyZWRlbnRpYWxzOndlYnNpdGUiLCJjb250YWN0IjoibXZkLWNyZWRlbnRpYWxzOmNvbnRhY3QiLCJzaW5jZSI6Im12ZC1jcmVkZW50aWFsczpzaW5jZSJ9XSwiaWQiOiJodHRwOi8vb3JnLnlvdXJkYXRhc3BhY2UuY29tL2NyZWRlbnRpYWxzLzIzNDciLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiTWVtYmVyc2hpcENyZWRlbnRpYWwiXSwiaXNzdWVyIjoiZGlkOndlYjpkYXRhc3BhY2UtaXNzdWVyIiwiaXNzdWFuY2VEYXRlIjoiMjAyMy0wOC0xOFQwMDowMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E3MDgzOmNvbnN1bWVyIiwibWVtYmVyc2hpcCI6eyJtZW1iZXJzaGlwVHlwZSI6IkZ1bGxNZW1iZXIiLCJ3ZWJzaXRlIjoid3d3LndoYXRldmVyLmNvbSIsImNvbnRhY3QiOiJmaXp6LmJ1enpAd2hhdGV2ZXIuY29tIiwic2luY2UiOiIyMDIzLTAxLTAxVDAwOjAwOjAwWiJ9fX0sImlhdCI6MTc0ODg0NDkxOX0.xcb9qKJ_BGGj_KvSM9lZIdJW01FSdDjALXxhmH8CehkOPy2nXGnWKIbjHJZmW60NtU7kqRC23THU7OWFs28EDw", - "format": "VC1_0_JWT", - "credential": { - "credentialSubject": [ - { - "claims": { - "membershipType": "FullMember", - "website": "www.some-other-website.com", - "contact": "bar.baz@company.com", - "since": "2023-01-01T00:00:00Z" - }, - "id": "did:web:consumer-identityhub%3A7083:consumer" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": { - "id": "did:web:dataspace-issuer", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/k8s/consumer/membership_vc.json b/deployment/assets/credentials/k8s/consumer/membership_vc.json deleted file mode 100644 index d3f4ae745..000000000 --- a/deployment/assets/credentials/k8s/consumer/membership_vc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "membership": "mvd-credentials:membership", - "membershipType": "mvd-credentials:membershipType", - "website": "mvd-credentials:website", - "contact": "mvd-credentials:contact", - "since": "mvd-credentials:since" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": "did:web:dataspace-issuer", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:consumer-identityhub%3A7083:consumer", - "membership": { - "membershipType": "FullMember", - "website": "www.whatever.com", - "contact": "fizz.buzz@whatever.com", - "since": "2023-01-01T00:00:00Z" - } - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/k8s/provider/dataprocessor-credential.json b/deployment/assets/credentials/k8s/provider/dataprocessor-credential.json deleted file mode 100644 index 7ed5bee2c..000000000 --- a/deployment/assets/credentials/k8s/provider/dataprocessor-credential.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1ca7", - "participantContextId": "did:web:provider-identityhub%3A7083:provider", - "timestamp": 1700659822500, - "issuerId": "did:web:dataspace-issuer", - "holderId": "did:web:provider-identityhub%3A7083:provider", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "format": "VC1_0_JWT", - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJhdWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vdzNpZC5vcmcvc2VjdXJpdHkvc3VpdGVzL2p3cy0yMDIwL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnL25zL2RpZC92MSIseyJtdmQtY3JlZGVudGlhbHMiOiJodHRwczovL3czaWQub3JnL212ZC9jcmVkZW50aWFscy8iLCJjb250cmFjdFZlcnNpb24iOiJtdmQtY3JlZGVudGlhbHM6Y29udHJhY3RWZXJzaW9uIiwibGV2ZWwiOiJtdmQtY3JlZGVudGlhbHM6bGV2ZWwifV0sImlkIjoiaHR0cDovL29yZy55b3VyZGF0YXNwYWNlLmNvbS9jcmVkZW50aWFscy8yMzQ3IiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkRhdGFQcm9jZXNzb3JDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDp3ZWI6ZGF0YXNwYWNlLWlzc3VlciIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDgtMThUMDA6MDA6MDBaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpwcm92aWRlciIsImxldmVsIjoicHJvY2Vzc2luZyIsImNvbnRyYWN0VmVyc2lvbiI6IjEuMC4wIn19LCJpYXQiOjE3NDg4NDQ5MTl9.lgSIzaPA9mm1LTEssDlfG2bcKUyhjWfjl85yEMHcKxAjl3kyFw1lBSokCR85f2bm-ZBHiAfCh9M9W1jixjPTCg", - "credential": { - "credentialSubject": [ - { - "claims": { - "id": "did:web:provider-identityhub%3A7083:provider", - "contractVersion": "1.0.0", - "level": "processing" - } - } - ], - "id": "http://org.yourdataspace.com/credentials/1265", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": { - "id": "did:web:dataspace-issuer", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/k8s/provider/dataprocessor_vc.json b/deployment/assets/credentials/k8s/provider/dataprocessor_vc.json deleted file mode 100644 index ff3160ebb..000000000 --- a/deployment/assets/credentials/k8s/provider/dataprocessor_vc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "contractVersion": "mvd-credentials:contractVersion", - "level": "mvd-credentials:level" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": "did:web:dataspace-issuer", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:provider-identityhub%3A7083:provider", - "level": "processing", - "contractVersion": "1.0.0" - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/k8s/provider/membership-credential.json b/deployment/assets/credentials/k8s/provider/membership-credential.json deleted file mode 100644 index 076ef60e0..000000000 --- a/deployment/assets/credentials/k8s/provider/membership-credential.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b14", - "participantContextId": "did:web:provider-identityhub%3A7083:provider", - "timestamp": 1700659822500, - "issuerId": "did:web:dataspace-issuer", - "holderId": "did:web:provider-identityhub%3A7083:provider", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJhdWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vdzNpZC5vcmcvc2VjdXJpdHkvc3VpdGVzL2p3cy0yMDIwL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnL25zL2RpZC92MSIseyJtdmQtY3JlZGVudGlhbHMiOiJodHRwczovL3czaWQub3JnL212ZC9jcmVkZW50aWFscy8iLCJtZW1iZXJzaGlwIjoibXZkLWNyZWRlbnRpYWxzOm1lbWJlcnNoaXAiLCJtZW1iZXJzaGlwVHlwZSI6Im12ZC1jcmVkZW50aWFsczptZW1iZXJzaGlwVHlwZSIsIndlYnNpdGUiOiJtdmQtY3JlZGVudGlhbHM6d2Vic2l0ZSIsImNvbnRhY3QiOiJtdmQtY3JlZGVudGlhbHM6Y29udGFjdCIsInNpbmNlIjoibXZkLWNyZWRlbnRpYWxzOnNpbmNlIn1dLCJpZCI6Imh0dHA6Ly9vcmcueW91cmRhdGFzcGFjZS5jb20vY3JlZGVudGlhbHMvMjM0NyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJNZW1iZXJzaGlwQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6d2ViOmRhdGFzcGFjZS1pc3N1ZXIiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA4LTE4VDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOndlYjpwcm92aWRlci1pZGVudGl0eWh1YiUzQTcwODM6cHJvdmlkZXIiLCJtZW1iZXJzaGlwIjp7Im1lbWJlcnNoaXBUeXBlIjoiRnVsbE1lbWJlciIsIndlYnNpdGUiOiJ3d3cud2hhdGV2ZXIuY29tIiwiY29udGFjdCI6Im1peC5tYXhAd2hhdGV2ZXIuY29tIiwic2luY2UiOiIyMDIzLTAxLTAxVDAwOjAwOjAwWiJ9fX0sImlhdCI6MTc0ODg0NDkxOH0.iX84wIF6unwmOWPtyRHAYv-YaoDSTzHl1ioZcfa-Y6aMGzbgD4EDhjKY9syR5mdYYIvqs__cAN-d3MOKbMgjDA", - "format": "VC1_0_JWT", - "credential": { - "credentialSubject": [ - { - "claims": { - "membership": { - "membershipType": "FullMember", - "website": "www.company-website.com", - "contact": "max.mustermann@company.com", - "since": "2023-05-08T00:00:00Z" - } - }, - "id": "did:web:provider-identityhub%3A7083:provider" - } - ], - "id": "http://org.yourdataspace.com/credentials/1234", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": { - "id": "did:web:dataspace-issuer", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/k8s/provider/membership_vc.json b/deployment/assets/credentials/k8s/provider/membership_vc.json deleted file mode 100644 index 4cf4ec500..000000000 --- a/deployment/assets/credentials/k8s/provider/membership_vc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "membership": "mvd-credentials:membership", - "membershipType": "mvd-credentials:membershipType", - "website": "mvd-credentials:website", - "contact": "mvd-credentials:contact", - "since": "mvd-credentials:since" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": "did:web:dataspace-issuer", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:provider-identityhub%3A7083:provider", - "membership": { - "membershipType": "FullMember", - "website": "www.whatever.com", - "contact": "mix.max@whatever.com", - "since": "2023-01-01T00:00:00Z" - } - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/local/consumer/dataprocessor-credential.json b/deployment/assets/credentials/local/consumer/dataprocessor-credential.json deleted file mode 100644 index 934f2d850..000000000 --- a/deployment/assets/credentials/local/consumer/dataprocessor-credential.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b15", - "participantContextId": "did:web:localhost%3A7083", - "timestamp": 1700659822500, - "issuerId": "did:web:localhost%3A9876", - "holderId": "did:web:localhost%3A7093", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "format": "VC1_0_JWT", - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkZW50aXR5aHViJTNBNzA4MzphbGljZSIsInN1YiI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E3MDgzOmFsaWNlIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L3N1aXRlcy9qd3MtMjAyMC92MSIsImh0dHBzOi8vd3d3LnczLm9yZy9ucy9kaWQvdjEiLHsibXZkLWNyZWRlbnRpYWxzIjoiaHR0cHM6Ly93M2lkLm9yZy9tdmQvY3JlZGVudGlhbHMvIiwiY29udHJhY3RWZXJzaW9uIjoibXZkLWNyZWRlbnRpYWxzOmNvbnRyYWN0VmVyc2lvbiIsImxldmVsIjoibXZkLWNyZWRlbnRpYWxzOmxldmVsIn1dLCJpZCI6Imh0dHA6Ly9vcmcueW91cmRhdGFzcGFjZS5jb20vY3JlZGVudGlhbHMvMjM0NyIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJEYXRhUHJvY2Vzc29yQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA4LTE4VDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgzIiwiY29udHJhY3RWZXJzaW9uIjoiMS4wLjAiLCJsZXZlbCI6InByb2Nlc3NpbmcifX0sImlhdCI6MTc0ODg0NDkxOX0.B3ZjHNsiOhuiv78uv4hu08LyA9gZrciMhKOHsC9CV99_KesoWQAjrsg2bJd2b3QQguLoR0C3S3u-9tcYvmB1Cg", - "credential": { - "credentialSubject": [ - { - "claims": { - "id": "did:web:localhost%3A7083", - "contractVersion": "1.0.0", - "level": "processing" - } - } - ], - "id": "http://org.yourdataspace.com/credentials/1235", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": { - "id": "did:web:localhost%3A9876", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/local/consumer/membership-credential.json b/deployment/assets/credentials/local/consumer/membership-credential.json deleted file mode 100644 index 95ce92cd9..000000000 --- a/deployment/assets/credentials/local/consumer/membership-credential.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b14", - "participantContextId": "did:web:localhost%3A7083", - "timestamp": 1700659822500, - "issuerId": "did:web:localhost%3A9876", - "holderId": "did:web:localhost%3A7083", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkZW50aXR5aHViJTNBNzA4MzphbGljZSIsInN1YiI6ImRpZDp3ZWI6Y29uc3VtZXItaWRlbnRpdHlodWIlM0E3MDgzOmFsaWNlIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L3N1aXRlcy9qd3MtMjAyMC92MSIsImh0dHBzOi8vd3d3LnczLm9yZy9ucy9kaWQvdjEiLHsibXZkLWNyZWRlbnRpYWxzIjoiaHR0cHM6Ly93M2lkLm9yZy9tdmQvY3JlZGVudGlhbHMvIiwibWVtYmVyc2hpcCI6Im12ZC1jcmVkZW50aWFsczptZW1iZXJzaGlwIiwibWVtYmVyc2hpcFR5cGUiOiJtdmQtY3JlZGVudGlhbHM6bWVtYmVyc2hpcFR5cGUiLCJ3ZWJzaXRlIjoibXZkLWNyZWRlbnRpYWxzOndlYnNpdGUiLCJjb250YWN0IjoibXZkLWNyZWRlbnRpYWxzOmNvbnRhY3QiLCJzaW5jZSI6Im12ZC1jcmVkZW50aWFsczpzaW5jZSJ9XSwiaWQiOiJodHRwOi8vb3JnLnlvdXJkYXRhc3BhY2UuY29tL2NyZWRlbnRpYWxzLzIzNDciLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiTWVtYmVyc2hpcENyZWRlbnRpYWwiXSwiaXNzdWVyIjoiZGlkOndlYjpsb2NhbGhvc3QlM0E5ODc2IiwiaXNzdWFuY2VEYXRlIjoiMjAyMy0wOC0xOFQwMDowMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6bG9jYWxob3N0JTNBNzA4MyIsIm1lbWJlcnNoaXAiOnsibWVtYmVyc2hpcFR5cGUiOiJGdWxsTWVtYmVyIiwid2Vic2l0ZSI6Ind3dy53aGF0ZXZlci5jb20iLCJjb250YWN0IjoibWl4Lm1heEB3aGF0ZXZlci5jb20iLCJzaW5jZSI6IjIwMjMtMDEtMDFUMDA6MDA6MDBaIn19fSwiaWF0IjoxNzQ4ODQ0OTE5fQ.xnb1qnjEUpSAzFlJT9krVkW8y7MffVJL7xhfimLEV2ADYtRw_94LvcYuv-eFwMcOEMtNzfWj4MRoM2IslI5rBw", - "format": "VC1_0_JWT", - "credential": { - "credentialSubject": [ - { - "claims": { - "membershipType": "FullMember", - "website": "www.some-other-website.com", - "contact": "bar.baz@company.com", - "since": "2023-01-01T00:00:00Z" - }, - "id": "did:web:localhost%3A7083" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": { - "id": "did:web:localhost%3A9876", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/local/consumer/unsigned/dataprocessor_vc.json b/deployment/assets/credentials/local/consumer/unsigned/dataprocessor_vc.json deleted file mode 100644 index e65876bf7..000000000 --- a/deployment/assets/credentials/local/consumer/unsigned/dataprocessor_vc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "contractVersion": "mvd-credentials:contractVersion", - "level": "mvd-credentials:level" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": "did:web:localhost%3A9876", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:localhost%3A7083", - "contractVersion": "1.0.0", - "level": "processing" - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/local/consumer/unsigned/membership_vc.json b/deployment/assets/credentials/local/consumer/unsigned/membership_vc.json deleted file mode 100644 index 65b1b56da..000000000 --- a/deployment/assets/credentials/local/consumer/unsigned/membership_vc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "membership": "mvd-credentials:membership", - "membershipType": "mvd-credentials:membershipType", - "website": "mvd-credentials:website", - "contact": "mvd-credentials:contact", - "since": "mvd-credentials:since" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": "did:web:localhost%3A9876", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:localhost%3A7083", - "membership": { - "membershipType": "FullMember", - "website": "www.whatever.com", - "contact": "mix.max@whatever.com", - "since": "2023-01-01T00:00:00Z" - } - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/local/provider/dataprocessor-credential.json b/deployment/assets/credentials/local/provider/dataprocessor-credential.json deleted file mode 100644 index aadbef8fe..000000000 --- a/deployment/assets/credentials/local/provider/dataprocessor-credential.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1ca7", - "participantContextId": "did:web:localhost%3A7093", - "timestamp": 1700659822500, - "issuerId": "did:web:localhost%3A9876", - "holderId": "did:web:localhost%3A7093", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "format": "VC1_0_JWT", - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJhdWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vdzNpZC5vcmcvc2VjdXJpdHkvc3VpdGVzL2p3cy0yMDIwL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnL25zL2RpZC92MSIseyJtdmQtY3JlZGVudGlhbHMiOiJodHRwczovL3czaWQub3JnL212ZC9jcmVkZW50aWFscy8iLCJjb250cmFjdFZlcnNpb24iOiJtdmQtY3JlZGVudGlhbHM6Y29udHJhY3RWZXJzaW9uIiwibGV2ZWwiOiJtdmQtY3JlZGVudGlhbHM6bGV2ZWwifV0sImlkIjoiaHR0cDovL29yZy55b3VyZGF0YXNwYWNlLmNvbS9jcmVkZW50aWFscy8yMzQ3IiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkRhdGFQcm9jZXNzb3JDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDp3ZWI6bG9jYWxob3N0JTNBOTg3NiIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDgtMThUMDA6MDA6MDBaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTcwOTMiLCJsZXZlbCI6InByb2Nlc3NpbmciLCJjb250cmFjdFZlcnNpb24iOiIxLjAuMCJ9fSwiaWF0IjoxNzQ4ODQ0OTE5fQ.aeb2uwwwEbaa3236XJhNOpJ_KxUIIefYeheAiw7OPtk_rXjmFOQ_aa7F09kEEgGK1NB3sijfVIEo5E96vMfZCQ", - "credential": { - "credentialSubject": [ - { - "claims": { - "id": "did:web:localhost%3A7093", - "contractVersion": "1.0.0", - "level": "processing" - } - } - ], - "id": "http://org.yourdataspace.com/credentials/1265", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": { - "id": "did:web:localhost%3A9876", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/local/provider/membership-credential.json b/deployment/assets/credentials/local/provider/membership-credential.json deleted file mode 100644 index 419beea63..000000000 --- a/deployment/assets/credentials/local/provider/membership-credential.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "40e24588-b510-41ca-966c-c1e0f57d1b14", - "participantContextId": "did:web:localhost%3A7093", - "timestamp": 1700659822500, - "issuerId": "did:web:localhost%3A9876", - "holderId": "did:web:localhost%3A7093", - "state": 500, - "issuancePolicy": null, - "reissuancePolicy": null, - "verifiableCredential": { - "rawVc": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYja2V5LTEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJhdWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkZW50aXR5aHViJTNBNzA4Mzpib2IiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vdzNpZC5vcmcvc2VjdXJpdHkvc3VpdGVzL2p3cy0yMDIwL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnL25zL2RpZC92MSIseyJtdmQtY3JlZGVudGlhbHMiOiJodHRwczovL3czaWQub3JnL212ZC9jcmVkZW50aWFscy8iLCJtZW1iZXJzaGlwIjoibXZkLWNyZWRlbnRpYWxzOm1lbWJlcnNoaXAiLCJtZW1iZXJzaGlwVHlwZSI6Im12ZC1jcmVkZW50aWFsczptZW1iZXJzaGlwVHlwZSIsIndlYnNpdGUiOiJtdmQtY3JlZGVudGlhbHM6d2Vic2l0ZSIsImNvbnRhY3QiOiJtdmQtY3JlZGVudGlhbHM6Y29udGFjdCIsInNpbmNlIjoibXZkLWNyZWRlbnRpYWxzOnNpbmNlIn1dLCJpZCI6Imh0dHA6Ly9vcmcueW91cmRhdGFzcGFjZS5jb20vY3JlZGVudGlhbHMvMTIzNCIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJNZW1iZXJzaGlwQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6d2ViOmxvY2FsaG9zdCUzQTk4NzYiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA4LTE4VDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOndlYjpsb2NhbGhvc3QlM0E3MDkzIiwibWVtYmVyc2hpcCI6eyJtZW1iZXJzaGlwVHlwZSI6IlByb3NwZWN0TWVtYmVyIiwid2Vic2l0ZSI6Ind3dy5xdWl6enF1YXp6LmNvbSIsImNvbnRhY3QiOiJmb28uYmFyQHF1aXp6cXVhenouY29tIiwic2luY2UiOiIyMDIzLTAxLTAxVDAwOjAwOjAwWiJ9fX0sImlhdCI6MTc0ODg0NDkxOX0.HmC6-GC6GalGL6n8UQ2BNDOAS1qNJ0B6A7gObM_p0psOkZqCvtSQ-gwMTX8qd5gK7eihGuAEiMQ7Z_gCvgKKAw", - "format": "VC1_0_JWT", - "credential": { - "credentialSubject": [ - { - "claims": { - "membership": { - "contact": "fizz.buzz@quizzquazz.com", - "membershipType": "PartialMember", - "since": "2023-01-01T00:00:00Z", - "website": "www.quizzquazz.com" - } - }, - "id": "did:web:localhost%3A7093" - } - ], - "id": "http://org.yourdataspace.com/credentials/1234", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": { - "id": "did:web:localhost%3A9876", - "additionalProperties": {} - }, - "issuanceDate": 1702339200.000000000, - "expirationDate": null, - "credentialStatus": null, - "description": null, - "name": null - } - } -} diff --git a/deployment/assets/credentials/local/provider/unsigned/dataprocessor_vc.json b/deployment/assets/credentials/local/provider/unsigned/dataprocessor_vc.json deleted file mode 100644 index 3152b5f13..000000000 --- a/deployment/assets/credentials/local/provider/unsigned/dataprocessor_vc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "contractVersion": "mvd-credentials:contractVersion", - "level": "mvd-credentials:level" - } - ], - "id": "http://org.yourdataspace.com/credentials/2347", - "type": [ - "VerifiableCredential", - "DataProcessorCredential" - ], - "issuer": "did:web:localhost%3A9876", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:localhost%3A7093", - "level": "processing", - "contractVersion": "1.0.0" - } -} \ No newline at end of file diff --git a/deployment/assets/credentials/local/provider/unsigned/membership_vc.json b/deployment/assets/credentials/local/provider/unsigned/membership_vc.json deleted file mode 100644 index a2b9efe35..000000000 --- a/deployment/assets/credentials/local/provider/unsigned/membership_vc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/security/suites/jws-2020/v1", - "https://www.w3.org/ns/did/v1", - { - "mvd-credentials": "https://w3id.org/mvd/credentials/", - "membership": "mvd-credentials:membership", - "membershipType": "mvd-credentials:membershipType", - "website": "mvd-credentials:website", - "contact": "mvd-credentials:contact", - "since": "mvd-credentials:since" - } - ], - "id": "http://org.yourdataspace.com/credentials/1234", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": "did:web:localhost%3A9876", - "issuanceDate": "2023-08-18T00:00:00Z", - "credentialSubject": { - "id": "did:web:localhost%3A7093", - "membership": { - "membershipType": "ProspectMember", - "website": "www.quizzquazz.com", - "contact": "foo.bar@quizzquazz.com", - "since": "2023-01-01T00:00:00Z" - } - } -} \ No newline at end of file diff --git a/deployment/assets/env/consumer_connector.env b/deployment/assets/env/consumer_connector.env deleted file mode 100644 index 78c803bf1..000000000 --- a/deployment/assets/env/consumer_connector.env +++ /dev/null @@ -1,38 +0,0 @@ -# control plane specific config -edc.iam.issuer.id=did:web:localhost%3A7083 -web.http.port=8080 -web.http.path=/api -web.http.management.port=8081 -web.http.management.path=/api/management/ -web.http.management.auth.type=tokenbased -web.http.management.auth.key=password -web.http.protocol.port=8082 -web.http.protocol.path=/api/dsp -web.http.control.port=8083 -web.http.control.path=/api/control -web.http.catalog.port=8084 -web.http.catalog.path=/api/catalog -web.http.catalog_auth.type=tokenbased -web.http.catalog_auth.key=password -web.http.version.port=8085 -web.http.version.path=/api/version -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=did:web:localhost%3A7083-alias -edc.iam.sts.publickey.id=did:web:localhost%3A7083#key-1 -edc.dsp.callback.address=http://localhost:8082/api/dsp -edc.participant.id=did:web:localhost%3A7083 -edc.catalog.cache.execution.delay.seconds=5 -edc.catalog.cache.execution.period.seconds=10 -edc.mvd.participants.list.file=deployment/assets/participants/participants.local.json -edc.management.context.enabled=true -edc.iam.sts.oauth.client.secret.alias=did:web:localhost%3A7083-sts-client-secret -edc.iam.sts.oauth.client.id=did:web:localhost%3A7083 -edc.iam.sts.oauth.token.url=http://localhost:7086/api/sts/token - -# dataplane specific config -edc.runtime.id=consumer-embedded-runtime -edc.transfer.proxy.token.verifier.publickey.alias=did:web:localhost%3A7083#key-1 -edc.transfer.proxy.token.signer.privatekey.alias=did:web:localhost%3A7083-alias -edc.dpf.selector.url=http://localhost:8083/api/control/v1/dataplanes -web.http.public.port=11001 -web.http.public.path=/api/public diff --git a/deployment/assets/env/consumer_identityhub.env b/deployment/assets/env/consumer_identityhub.env deleted file mode 100644 index 368423112..000000000 --- a/deployment/assets/env/consumer_identityhub.env +++ /dev/null @@ -1,19 +0,0 @@ -web.http.port=7080 -web.http.path=/api -web.http.credentials.port=7081 -web.http.credentials.path=/api/credentials -web.http.identity.port=7082 -web.http.identity.path=/api/identity -web.http.did.port=7083 -web.http.did.path=/ -web.http.version.port=7085 -web.http.version.path=/api/version -web.http.sts.port=7086 -web.http.sts.path=/api/sts -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=key-1 -edc.iam.sts.publickey.id=did:web:localhost%3A7083#key-1 -edc.ih.iam.publickey.path=./deployment/assets/consumer_public.pem -edc.ih.iam.id=did:web:localhost%3A7083 -edc.ih.api.superuser.key=c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo= -edc.mvd.credentials.path=deployment/assets/credentials/local/consumer/ \ No newline at end of file diff --git a/deployment/assets/env/issuerservice.env b/deployment/assets/env/issuerservice.env deleted file mode 100644 index e2aa1130d..000000000 --- a/deployment/assets/env/issuerservice.env +++ /dev/null @@ -1,15 +0,0 @@ -edc.issuer.statuslist.signing.key.alias=signing-key-alias -web.http.port=10010 -web.http.path=/api -web.http.sts.port=10011 -web.http.sts.path=/api/sts -web.http.issuance.port=10012 -web.http.issuance.path=/api/issuance -web.http.issueradmin.port=10013 -web.http.issueradmin.path=/api/admin -web.http.version.port=10014 -web.http.version.path=/.well-known/api -web.http.identity.port=10015 -web.http.identity.path=/api/identity -edc.iam.did.web.use.https=false -edc.ih.api.superuser.key=c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo= \ No newline at end of file diff --git a/deployment/assets/env/provider_catalogserver.env b/deployment/assets/env/provider_catalogserver.env deleted file mode 100644 index 7b9706ee6..000000000 --- a/deployment/assets/env/provider_catalogserver.env +++ /dev/null @@ -1,20 +0,0 @@ -edc.iam.issuer.id=did:web:localhost%3A7093 -web.http.port=8090 -web.http.path=/api -web.http.management.port=8091 -web.http.management.path=/api/management -web.http.management.auth.type=tokenbased -web.http.management.auth.key=password -web.http.protocol.port=8092 -web.http.protocol.path=/api/dsp -web.http.control.port=8093 -web.http.control.path=/api/control -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=did:web:localhost%3A7093-alias -edc.iam.sts.publickey.id=did:web:localhost%3A7093#key-1 -edc.dsp.callback.address=http://localhost:8092/api/dsp -edc.participant.id=did:web:localhost%3A7093 -edc.management.context.enabled=true -edc.iam.sts.oauth.client.secret.alias=did:web:localhost%3A7093-sts-client-secret -edc.iam.sts.oauth.client.id=did:web:localhost%3A7093 -edc.iam.sts.oauth.token.url=http://localhost:7096/api/sts/token \ No newline at end of file diff --git a/deployment/assets/env/provider_connector_manufacturing.env b/deployment/assets/env/provider_connector_manufacturing.env deleted file mode 100644 index e041c8fb0..000000000 --- a/deployment/assets/env/provider_connector_manufacturing.env +++ /dev/null @@ -1,38 +0,0 @@ -# control plane specific config -edc.iam.issuer.id=did:web:localhost%3A7093 -web.http.port=8290 -web.http.path=/api -web.http.management.port=8291 -web.http.management.path=/api/management/ -web.http.management.auth.type=tokenbased -web.http.management.auth.key=password -web.http.protocol.port=8292 -web.http.protocol.path=/api/dsp -web.http.control.port=8293 -web.http.control.path=/api/control -web.http.catalog.port=8294 -web.http.catalog.path=/api/catalog -web.http.catalog_auth.type=tokenbased -web.http.catalog_auth.key=password -web.http.version.port=8295 -web.http.version.path=/api/version -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=did:web:localhost%3A7093-alias -edc.iam.sts.publickey.id=did:web:localhost%3A7093#key-1 -edc.dsp.callback.address=http://localhost:8292/api/dsp -edc.participant.id=did:web:localhost%3A7093 -edc.catalog.cache.execution.delay.seconds=5 -edc.catalog.cache.execution.period.seconds=10 -edc.mvd.participants.list.file=deployment/assets/participants/participants.local.json -edc.management.context.enabled=true -edc.iam.sts.oauth.client.secret.alias=did:web:localhost%3A7093-sts-client-secret -edc.iam.sts.oauth.client.id=did:web:localhost%3A7093 -edc.iam.sts.oauth.token.url=http://localhost:7096/api/sts/token - -# dataplane specific config -edc.runtime.id=provider-manufacturing-embedded-runtime -edc.transfer.proxy.token.verifier.publickey.alias=did:web:localhost%3A7093#key-1 -edc.transfer.proxy.token.signer.privatekey.alias=did:web:localhost%3A7093-alias -edc.dpf.selector.url=http://localhost:8293/api/control/v1/dataplanes -web.http.public.port=12002 -web.http.public.path=/api/public diff --git a/deployment/assets/env/provider_connector_qna.env b/deployment/assets/env/provider_connector_qna.env deleted file mode 100644 index 353585982..000000000 --- a/deployment/assets/env/provider_connector_qna.env +++ /dev/null @@ -1,38 +0,0 @@ -# control plane specific config -edc.iam.issuer.id=did:web:localhost%3A7093 -web.http.port=8190 -web.http.path=/api -web.http.management.port=8191 -web.http.management.path=/api/management/ -web.http.management.auth.type=tokenbased -web.http.management.auth.key=password -web.http.protocol.port=8192 -web.http.protocol.path=/api/dsp -web.http.control.port=8193 -web.http.control.path=/api/control -web.http.catalog.port=8194 -web.http.catalog.path=/api/catalog -web.http.catalog_auth.type=tokenbased -web.http.catalog_auth.key=password -web.http.version.port=8195 -web.http.version.path=/api/version -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=did:web:localhost%3A7093-alias -edc.iam.sts.publickey.id=did:web:localhost%3A7093#key-1 -edc.dsp.callback.address=http://localhost:8192/api/dsp -edc.participant.id=did:web:localhost%3A7093 -edc.catalog.cache.execution.delay.seconds=5 -edc.catalog.cache.execution.period.seconds=10 -edc.mvd.participants.list.file=deployment/assets/participants/participants.local.json -edc.management.context.enabled=true -edc.iam.sts.oauth.client.secret.alias=did:web:localhost%3A7093-sts-client-secret -edc.iam.sts.oauth.client.id=did:web:localhost%3A7093 -edc.iam.sts.oauth.token.url=http://localhost:7096/api/sts/token - -# dataplane specific config -edc.runtime.id=provider-qna-embedded-runtime -edc.transfer.proxy.token.verifier.publickey.alias=did:web:localhost%3A7093#key-1 -edc.transfer.proxy.token.signer.privatekey.alias=did:web:localhost%3A7093-alias -edc.dpf.selector.url=http://localhost:8193/api/control/v1/dataplanes -web.http.public.port=12001 -web.http.public.path=/api/public diff --git a/deployment/assets/env/provider_identityhub.env b/deployment/assets/env/provider_identityhub.env deleted file mode 100644 index 7f2febbe9..000000000 --- a/deployment/assets/env/provider_identityhub.env +++ /dev/null @@ -1,19 +0,0 @@ -web.http.port=7090 -web.http.path=/api -web.http.credentials.port=7091 -web.http.credentials.path=/api/credentials/ -web.http.identity.port=7092 -web.http.identity.path=/api/identity -web.http.did.port=7093 -web.http.did.path=/ -web.http.version.port=7095 -web.http.version.path=/api/version -web.http.sts.port=7096 -web.http.sts.path=/api/sts -edc.iam.did.web.use.https=false -edc.iam.sts.privatekey.alias=key-1 -edc.iam.sts.publickey.id=did:web:localhost%3A7093#key-1 -edc.ih.iam.publickey.path=./deployment/assets/provider_public.pem -edc.ih.iam.id=did:web:localhost%3A7093 -edc.ih.api.superuser.key=c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo= -edc.mvd.credentials.path=deployment/assets/credentials/local/provider/ \ No newline at end of file diff --git a/deployment/assets/issuer/did.docker.json b/deployment/assets/issuer/did.docker.json deleted file mode 100644 index 1c819d142..000000000 --- a/deployment/assets/issuer/did.docker.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "service": [], - "verificationMethod": [ - { - "id": "did:web:localhost%3A9876#key-1", - "type": "JsonWebKey2020", - "controller": "did:web:localhost%3A9876", - "publicKeyMultibase": null, - "publicKeyJwk": { - "kty": "OKP", - "crv": "Ed25519", - "x": "Hsq2QXPbbsU7j6JwXstbpxGSgliI04g_fU3z2nwkuVc" - } - } - ], - "authentication": [ - "key-1" - ], - "id": "did:web:localhost%3A9876", - "@context": [ - "https://www.w3.org/ns/did/v1", - { - "@base": "did:web:localhost%3A9876" - } - ] -} \ No newline at end of file diff --git a/deployment/assets/issuer/did.k8s.json b/deployment/assets/issuer/did.k8s.json deleted file mode 100644 index b6b0d01dc..000000000 --- a/deployment/assets/issuer/did.k8s.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "service": [], - "verificationMethod": [ - { - "id": "did:web:dataspace-issuer#key-1", - "type": "JsonWebKey2020", - "controller": "did:web:dataspace-issuer", - "publicKeyMultibase": null, - "publicKeyJwk": { - "kty": "OKP", - "crv": "Ed25519", - "x": "Hsq2QXPbbsU7j6JwXstbpxGSgliI04g_fU3z2nwkuVc" - } - } - ], - "authentication": [ - "key-1" - ], - "id": "did:web:dataspace-issuer", - "@context": [ - "https://www.w3.org/ns/did/v1", - { - "@base": "did:web:dataspace-issuer" - } - ] -} \ No newline at end of file diff --git a/deployment/assets/issuer/nginx.conf b/deployment/assets/issuer/nginx.conf deleted file mode 100644 index fa45fbed2..000000000 --- a/deployment/assets/issuer/nginx.conf +++ /dev/null @@ -1,9 +0,0 @@ -events { worker_connections 1024; } - -http { - server { - listen 80; - root /var/www/; - index index.html; - } - } \ No newline at end of file diff --git a/deployment/assets/issuer_private.pem b/deployment/assets/issuer_private.pem deleted file mode 100644 index 8a63542f7..000000000 --- a/deployment/assets/issuer_private.pem +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PRIVATE KEY----- -MC4CAQAwBQYDK2VwBCIEID1gMsekH7JN9Q/L2UMCBkAPET10NE0T2BB4c2rRSBzg ------END PRIVATE KEY----- diff --git a/deployment/assets/issuer_public.pem b/deployment/assets/issuer_public.pem deleted file mode 100644 index 51b250241..000000000 --- a/deployment/assets/issuer_public.pem +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN PUBLIC KEY----- -MCowBQYDK2VwAyEAHsq2QXPbbsU7j6JwXstbpxGSgliI04g/fU3z2nwkuVc= ------END PUBLIC KEY----- diff --git a/deployment/assets/participants/participants.k8s.json b/deployment/assets/participants/participants.k8s.json deleted file mode 100644 index 993eeacee..000000000 --- a/deployment/assets/participants/participants.k8s.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "consumer-corp": "did:web:consumer-identityhub%3A7083:consumer", - "provider-corp": "did:web:provider-identityhub%3A7083:provider" -} \ No newline at end of file diff --git a/deployment/assets/participants/participants.local.json b/deployment/assets/participants/participants.local.json deleted file mode 100644 index ae3849cf4..000000000 --- a/deployment/assets/participants/participants.local.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "consumer-corp": "did:web:localhost%3A7083", - "provider-corp": "did:web:localhost%3A7093" -} \ No newline at end of file diff --git a/deployment/assets/provider_private.pem b/deployment/assets/provider_private.pem deleted file mode 100644 index 81c28bac2..000000000 --- a/deployment/assets/provider_private.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIARDUGJgKy1yzxkueIJ1k3MPUWQ/tbQWQNqW6TjyHpdcoAoGCCqGSM49 -AwEHoUQDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5roYnkAXuqCYfNK3ex+hMWFuiX -GUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== ------END EC PRIVATE KEY----- \ No newline at end of file diff --git a/deployment/assets/provider_public.pem b/deployment/assets/provider_public.pem deleted file mode 100644 index 977a19576..000000000 --- a/deployment/assets/provider_public.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5r -oYnkAXuqCYfNK3ex+hMWFuiXGUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== ------END PUBLIC KEY----- \ No newline at end of file diff --git a/deployment/consumer.tf b/deployment/consumer.tf deleted file mode 100644 index 2e194b89d..000000000 --- a/deployment/consumer.tf +++ /dev/null @@ -1,83 +0,0 @@ -# -# 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 -# - -# This file deploys all the components needed for the consumer side of the scenario, -# i.e. the connector, an identityhub and a vault. - -# consumer connector -module "consumer-connector" { - source = "./modules/connector" - humanReadableName = "consumer" - participantId = var.consumer-did - database = { - user = "consumer" - password = "consumer" - url = "jdbc:postgresql://${module.consumer-postgres.database-url}/consumer" - } - vault-url = "http://consumer-vault:8200" - namespace = kubernetes_namespace.ns.metadata.0.name - sts-token-url = "${module.consumer-identityhub.sts-token-url}/token" - useSVE = var.useSVE -} - -# consumer identity hub -module "consumer-identityhub" { - depends_on = [module.consumer-vault] - source = "./modules/identity-hub" - credentials-dir = dirname("./assets/credentials/k8s/consumer/") - humanReadableName = "consumer-identityhub" - participantId = var.consumer-did - vault-url = "http://consumer-vault:8200" - service-name = "consumer" - database = { - user = "consumer" - password = "consumer" - url = "jdbc:postgresql://${module.consumer-postgres.database-url}/consumer" - } - namespace = kubernetes_namespace.ns.metadata.0.name - useSVE = var.useSVE -} - - -# consumer vault -module "consumer-vault" { - source = "./modules/vault" - humanReadableName = "consumer-vault" - namespace = kubernetes_namespace.ns.metadata.0.name -} - -# Postgres database for the consumer -module "consumer-postgres" { - depends_on = [kubernetes_config_map.postgres-initdb-config-consumer] - source = "./modules/postgres" - instance-name = "consumer" - init-sql-configs = ["consumer-initdb-config"] - namespace = kubernetes_namespace.ns.metadata.0.name -} - -# DB initialization for the EDC database -resource "kubernetes_config_map" "postgres-initdb-config-consumer" { - metadata { - name = "consumer-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "consumer-initdb-config.sql" = <<-EOT - CREATE USER consumer WITH ENCRYPTED PASSWORD 'consumer' SUPERUSER; - CREATE DATABASE consumer; - \c consumer consumer - - - EOT - } -} \ No newline at end of file diff --git a/deployment/issuer.tf b/deployment/issuer.tf deleted file mode 100644 index c49f658f3..000000000 --- a/deployment/issuer.tf +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright (c) 2025 Cofinity-X -# -# 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: -# Cofinity-X - initial API and implementation -# - -module "dataspace-issuer" { - source = "./modules/issuer" - humanReadableName = "dataspace-issuer-service" - participantId = var.consumer-did - database = { - user = "issuer" - password = "issuer" - url = "jdbc:postgresql://${module.dataspace-issuer-postgres.database-url}/issuer" - } - vault-url = "http://consumer-vault:8200" - namespace = kubernetes_namespace.ns.metadata.0.name - useSVE = var.useSVE -} - -# Postgres database for the consumer -module "dataspace-issuer-postgres" { - depends_on = [kubernetes_config_map.issuer-initdb-config] - source = "./modules/postgres" - instance-name = "issuer" - init-sql-configs = ["issuer-initdb-config"] - namespace = kubernetes_namespace.ns.metadata.0.name -} - -# DB initialization for the EDC database -resource "kubernetes_config_map" "issuer-initdb-config" { - metadata { - name = "issuer-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "issuer-initdb-config.sql" = <<-EOT - CREATE USER issuer WITH ENCRYPTED PASSWORD 'issuer' SUPERUSER; - CREATE DATABASE issuer; - \c issuer issuer - - create table if not exists membership_attestations - ( - membership_type integer default 0, - holder_id varchar not null, - membership_start_date timestamp default now() not null, - id varchar default gen_random_uuid() not null - constraint attestations_pk - primary key - ); - - create unique index if not exists membership_attestation_holder_id_uindex - on membership_attestations (holder_id); - - -- seed the consumer and provider into the attestations DB, so that they can request FoobarCredentials sourcing - -- information from the database - INSERT INTO membership_attestations (membership_type, holder_id) VALUES (1, 'did:web:consumer-identityhub%3A7083:consumer'); - INSERT INTO membership_attestations (membership_type, holder_id) VALUES (2, 'did:web:provider-identityhub%3A7083:provider'); - EOT - } -} \ No newline at end of file diff --git a/deployment/issuer_nginx.tf b/deployment/issuer_nginx.tf deleted file mode 100644 index 3d6070a69..000000000 --- a/deployment/issuer_nginx.tf +++ /dev/null @@ -1,110 +0,0 @@ -# -# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - - -resource "kubernetes_deployment" "dataspace-issuer-did-server" { - metadata { - name = "dataspace-issuer-server" - namespace = kubernetes_namespace.ns.metadata.0.name - labels = { - App = "dataspace-issuer-server" - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = "dataspace-issuer-server" - } - } - - template { - metadata { - labels = { - App = "dataspace-issuer-server" - } - } - - spec { - - container { - image_pull_policy = "IfNotPresent" - image = "nginx:latest" - name = "nginx" - - port { - container_port = "80" - name = "web" - } - # maps the nginx.conf file - volume_mount { - mount_path = "/etc/nginx/nginx.conf" - sub_path = "nginx.conf" - name = "nginx-config" - } - - # this maps the did.json file such that it becomes available at htp:///dataspace-issuer/did.json - volume_mount { - mount_path = "/var/www/.well-known/did.json" - sub_path = "did.json" - name = "nginx-config" - } - } - - volume { - name = "nginx-config" - config_map { - name = "nginx-conf" - } - } - } - } - } -} - -resource "kubernetes_service" "dataspace-issuer-did-server-service" { - metadata { - name = "dataspace-issuer" # this must correlate with the Issuer's DID: did:web:dataspace-issuer -> http://dataspace-issuer/.well-known/did.json - namespace = kubernetes_namespace.ns.metadata.0.name - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.dataspace-issuer-did-server.spec.0.template.0.metadata[0].labels.App - } - # we need a stable IP, otherwise there will be a cycle with the issuer - port { - name = "web" - port = 80 - } - } -} - -resource "kubernetes_config_map" "nginx-map" { - metadata { - name = "nginx-conf" - namespace = kubernetes_namespace.ns.metadata.0.name - } - - data = { - "nginx.conf" = file("${path.root}/assets/issuer/nginx.conf") - "did.json" = file("${path.root}/assets/issuer/did.k8s.json") - } -} \ No newline at end of file diff --git a/deployment/kind.config.yaml b/deployment/kind.config.yaml deleted file mode 100644 index 9d918bb2d..000000000 --- a/deployment/kind.config.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - ---- -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - extraPortMappings: - - containerPort: 80 - hostPort: 80 - protocol: TCP - - containerPort: 443 - hostPort: 443 - protocol: TCP \ No newline at end of file diff --git a/deployment/main.tf b/deployment/main.tf deleted file mode 100644 index 2a96bac99..000000000 --- a/deployment/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -terraform { - required_providers { - // for generating passwords, clientsecrets etc. - random = { - source = "hashicorp/random" - } - - kubernetes = { - source = "hashicorp/kubernetes" - } - helm = { - // used for Hashicorp Vault - source = "hashicorp/helm" - } - } -} - -provider "kubernetes" { - config_path = "~/.kube/config" -} - -provider "helm" { - kubernetes = { - config_path = "~/.kube/config" - } -} - -resource "kubernetes_namespace" "ns" { - metadata { - name = "mvd" - } -} diff --git a/deployment/modules/catalog-server/catalog-server.tf b/deployment/modules/catalog-server/catalog-server.tf deleted file mode 100644 index aad588755..000000000 --- a/deployment/modules/catalog-server/catalog-server.tf +++ /dev/null @@ -1,155 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_deployment" "connector" { - metadata { - name = lower(var.humanReadableName) - namespace = var.namespace - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = lower(var.humanReadableName) - } - } - - template { - metadata { - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - container { - name = lower(var.humanReadableName) - image = "catalog-server:latest" - image_pull_policy = "Never" - - env_from { - config_map_ref { - name = kubernetes_config_map.catalog-server-config.metadata[0].name - } - } - - port { - container_port = var.ports.management - name = "management-port" - } - port { - container_port = var.ports.web - name = "default-port" - } - port { - container_port = var.ports.debug - name = "debug-port" - } - - liveness_probe { - http_get { - path = "/api/check/liveness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - readiness_probe { - http_get { - path = "/api/check/readiness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - startup_probe { - http_get { - path = "/api/check/startup" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - volume_mount { - mount_path = "/etc/registry" - name = "registry-volume" - } - } - - volume { - name = "registry-volume" - config_map { - name = kubernetes_config_map.catalog-server-config.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_config_map" "catalog-server-config" { - metadata { - name = "${lower(var.humanReadableName)}-connector-config" - namespace = var.namespace - } - - ## Create databases for keycloak and MIW, create users and assign privileges - data = { - EDC_IAM_ISSUER_ID = var.participantId - EDC_IAM_DID_WEB_USE_HTTPS = false - WEB_HTTP_PORT = var.ports.web - WEB_HTTP_PATH = "/api" - WEB_HTTP_MANAGEMENT_PORT = var.ports.management - WEB_HTTP_MANAGEMENT_PATH = "/api/management" - WEB_HTTP_MANAGEMENT_AUTH_TYPE = "tokenbased" - WEB_HTTP_MANAGEMENT_AUTH_KEY = "password" - WEB_HTTP_CONTROL_PORT = var.ports.control - WEB_HTTP_CONTROL_PATH = "/api/control" - WEB_HTTP_PROTOCOL_PORT = var.ports.protocol - WEB_HTTP_PROTOCOL_PATH = "/api/dsp" - EDC_DSP_CALLBACK_ADDRESS = "http://${local.controlplane-service-name}:${var.ports.protocol}/api/dsp" - EDC_IAM_STS_PRIVATEKEY_ALIAS = "${var.participantId}#${var.aliases.sts-private-key}" - EDC_IAM_STS_PUBLICKEY_ID = "${var.participantId}#${var.aliases.sts-public-key-id}" - JAVA_TOOL_OPTIONS = "${var.useSVE ? "-XX:UseSVE=0 " : ""}-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${var.ports.debug}" - EDC_IH_AUDIENCE_REGISTRY_PATH = "/etc/registry/registry.json" - EDC_PARTICIPANT_ID = var.participantId - EDC_VAULT_HASHICORP_URL = var.vault-url - EDC_VAULT_HASHICORP_TOKEN = var.vault-token - EDC_MVD_PARTICIPANTS_LIST_FILE = "/etc/participants/participants.json" - EDC_DATASOURCE_DEFAULT_URL = var.database.url - EDC_DATASOURCE_DEFAULT_USER = var.database.user - EDC_DATASOURCE_DEFAULT_PASSWORD = var.database.password - EDC_SQL_SCHEMA_AUTOCREATE = true - - # remote STS configuration - EDC_IAM_STS_OAUTH_TOKEN_URL = var.sts-token-url - EDC_IAM_STS_OAUTH_CLIENT_ID = var.participantId - EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS = "${var.participantId}-sts-client-secret" - } -} diff --git a/deployment/modules/catalog-server/ingress.tf b/deployment/modules/catalog-server/ingress.tf deleted file mode 100644 index ce34f33d1..000000000 --- a/deployment/modules/catalog-server/ingress.tf +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_ingress_v1" "api-ingress" { - metadata { - name = "${var.humanReadableName}-ingress" - namespace = var.namespace - 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.humanReadableName}/health(/|$)(.*)" - backend { - service { - name = kubernetes_service.controlplane-service.metadata.0.name - port { - number = var.ports.web - } - } - } - } - - path { - path = "/${var.humanReadableName}/cp(/|$)(.*)" - backend { - service { - name = kubernetes_service.controlplane-service.metadata.0.name - port { - number = var.ports.management - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/deployment/modules/catalog-server/outputs.tf b/deployment/modules/catalog-server/outputs.tf deleted file mode 100644 index 0d47109a4..000000000 --- a/deployment/modules/catalog-server/outputs.tf +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -output "connector-node-ip" { - value = kubernetes_service.controlplane-service.spec.0.cluster_ip -} - -output "ports" { - value = var.ports -} - -output "audience-mapping" { - value = { - # dspAudience = "http://${local.connector-cluster-ip}:${var.ports.protocol}/api/dsp" - dcpAudience = var.participantId - } -} - -output "ih-superuser-apikey" { - value = var.ih_superuser_apikey -} \ No newline at end of file diff --git a/deployment/modules/catalog-server/services.tf b/deployment/modules/catalog-server/services.tf deleted file mode 100644 index 781de4182..000000000 --- a/deployment/modules/catalog-server/services.tf +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_service" "controlplane-service" { - metadata { - name = local.controlplane-service-name - namespace = var.namespace - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.connector.spec.0.template.0.metadata[0].labels.App - } - port { - name = "health" - port = var.ports.web - } - port { - name = "management" - port = var.ports.management - } - port { - name = "protocol" - port = var.ports.protocol - } - port { - name = "debug" - port = var.ports.debug - } - } -} \ No newline at end of file diff --git a/deployment/modules/catalog-server/variables.tf b/deployment/modules/catalog-server/variables.tf deleted file mode 100644 index 02119125d..000000000 --- a/deployment/modules/catalog-server/variables.tf +++ /dev/null @@ -1,117 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -## Normally, you shouldn't need to change any values here. If you do, please be sure to also change them in the seed script (seed-k8s.sh). -## Neglecting to do that will render the connectors and identity hubs inoperable! - - -variable "image-pull-policy" { - default = "Always" - type = string - description = "Kubernetes ImagePullPolicy for all images" -} - -variable "humanReadableName" { - type = string - description = "Human readable name of the connector, NOT the ID!!. Required." -} - -variable "participantId" { - type = string - description = "DID:WEB identifier of the participant" -} - -variable "namespace" { - type = string -} - -variable "ports" { - type = object({ - web = number - management = number - protocol = number - control = number - debug = number - }) - default = { - web = 8080 - management = 8081 - protocol = 8082 - control = 8083 - debug = 1044 - } -} - -variable "database" { - type = object({ - url = string - user = string - password = string - }) -} - -variable "participant-list-file" { - type = string - default = "./assets/participants/participants.k8s.json" -} - -variable "ih_superuser_apikey" { - default = "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=" - description = "Management API Key for the Super-User. Defaults to 'base64(super-user).base64(super-secret-key)" - type = string -} - -variable "vault-token" { - default = "root" - description = "This is the authentication token for the vault. DO NOT USE THIS IN PRODUCTION!" - type = string -} - -variable "vault-url" { - description = "URL of the Hashicorp Vault" - type = string -} - -variable "sts-token-url" { - description = "Full URL of the STS token endpoint" - type = string -} - -variable "aliases" { - type = object({ - sts-private-key = string - sts-public-key-id = string - }) - default = { - sts-private-key = "key-1" - sts-public-key-id = "key-1" - } -} - -variable "useSVE" { - type = bool - description = "If true, the -XX:UseSVE=0 switch (Scalable Vector Extensions) will be appended to the JAVA_TOOL_OPTIONS. Can help on macOs on Apple Silicon processors" - default = false -} - -locals { - name = lower(var.humanReadableName) - controlplane-service-name = "${var.humanReadableName}-controlplane" - ih-service-name = "${var.humanReadableName}-identityhub" -} diff --git a/deployment/modules/connector/controlplane.tf b/deployment/modules/connector/controlplane.tf deleted file mode 100644 index 86b7722b2..000000000 --- a/deployment/modules/connector/controlplane.tf +++ /dev/null @@ -1,185 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_deployment" "controlplane" { - metadata { - name = "${lower(var.humanReadableName)}-controlplane" - namespace = var.namespace - labels = { - App = "${lower(var.humanReadableName)}-controlplane" - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = "${lower(var.humanReadableName)}-controlplane" - } - } - - template { - metadata { - labels = { - App = "${lower(var.humanReadableName)}-controlplane" - } - } - - spec { - container { - name = "connector-${lower(var.humanReadableName)}" - image = "controlplane:latest" - image_pull_policy = "Never" - - env_from { - config_map_ref { - name = kubernetes_config_map.connector-config.metadata[0].name - } - } - - port { - container_port = var.ports.management - name = "management-port" - } - port { - container_port = var.ports.web - name = "default-port" - } - port { - container_port = var.ports.debug - name = "debug-port" - } - - liveness_probe { - http_get { - path = "/api/check/liveness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - readiness_probe { - http_get { - path = "/api/check/readiness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - startup_probe { - http_get { - path = "/api/check/startup" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - volume_mount { - mount_path = "/etc/registry" - name = "registry-volume" - } - - volume_mount { - mount_path = "/etc/participants" - name = "participants-volume" - } - } - - volume { - name = "registry-volume" - config_map { - name = kubernetes_config_map.connector-config.metadata[0].name - } - } - - volume { - name = "participants-volume" - config_map { - name = kubernetes_config_map.participants-map.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_config_map" "participants-map" { - metadata { - name = "${var.humanReadableName}-participants" - namespace = var.namespace - } - - data = { - "participants.json" = file(var.participant-list-file) - } - -} - -resource "kubernetes_config_map" "connector-config" { - metadata { - name = "${lower(var.humanReadableName)}-controlplane-config" - namespace = var.namespace - } - - ## Create databases for keycloak and MIW, create users and assign privileges - data = { - EDC_PARTICIPANT_ID = var.participantId - EDC_IAM_ISSUER_ID = var.participantId - EDC_IAM_DID_WEB_USE_HTTPS = false - WEB_HTTP_PORT = var.ports.web - WEB_HTTP_PATH = "/api" - WEB_HTTP_MANAGEMENT_PORT = var.ports.management - WEB_HTTP_MANAGEMENT_PATH = "/api/management" - WEB_HTTP_MANAGEMENT_AUTH_TYPE = "tokenbased" - WEB_HTTP_MANAGEMENT_AUTH_KEY = "password" - WEB_HTTP_CONTROL_PORT = var.ports.control - WEB_HTTP_CONTROL_PATH = "/api/control" - WEB_HTTP_PROTOCOL_PORT = var.ports.protocol - WEB_HTTP_PROTOCOL_PATH = "/api/dsp" - WEB_HTTP_CATALOG_PORT = var.ports.catalog - WEB_HTTP_CATALOG_PATH = "/api/catalog" - WEB_HTTP_CATALOG_AUTH_TYPE = "tokenbased" - WEB_HTTP_CATALOG_AUTH_KEY = "password" - EDC_DSP_CALLBACK_ADDRESS = "http://${local.controlplane-service-name}:${var.ports.protocol}/api/dsp" - EDC_IAM_STS_PRIVATEKEY_ALIAS = "${var.participantId}#${var.aliases.sts-private-key}" - EDC_IAM_STS_PUBLICKEY_ID = "${var.participantId}#${var.aliases.sts-public-key-id}" - JAVA_TOOL_OPTIONS = "${var.useSVE ? "-XX:UseSVE=0 " : ""}-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${var.ports.debug}" - EDC_IH_AUDIENCE_REGISTRY_PATH = "/etc/registry/registry.json" - EDC_VAULT_HASHICORP_URL = var.vault-url - EDC_VAULT_HASHICORP_TOKEN = var.vault-token - EDC_MVD_PARTICIPANTS_LIST_FILE = "/etc/participants/participants.json" - EDC_CATALOG_CACHE_EXECUTION_DELAY_SECONDS = 10 - EDC_CATALOG_CACHE_EXECUTION_PERIOD_SECONDS = 10 - EDC_DATASOURCE_DEFAULT_URL = var.database.url - EDC_DATASOURCE_DEFAULT_USER = var.database.user - EDC_DATASOURCE_DEFAULT_PASSWORD = var.database.password - EDC_SQL_SCHEMA_AUTOCREATE = true - - # remote STS configuration - EDC_IAM_STS_OAUTH_TOKEN_URL = var.sts-token-url - EDC_IAM_STS_OAUTH_CLIENT_ID = var.participantId - EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS = "${var.participantId}-sts-client-secret" - } -} diff --git a/deployment/modules/connector/dataplane.tf b/deployment/modules/connector/dataplane.tf deleted file mode 100644 index 6a7d56e37..000000000 --- a/deployment/modules/connector/dataplane.tf +++ /dev/null @@ -1,137 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_deployment" "dataplane" { - # needs a hard dependency, otherwise the dataplane registration fails, and it is not retried - depends_on = [kubernetes_deployment.controlplane] - metadata { - name = "${lower(var.humanReadableName)}-dataplane" - namespace = var.namespace - labels = { - App = "${lower(var.humanReadableName)}-dataplane" - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = "${lower(var.humanReadableName)}-dataplane" - } - } - - template { - metadata { - labels = { - App = "${lower(var.humanReadableName)}-dataplane" - } - } - - spec { - container { - name = "dataplane-${lower(var.humanReadableName)}" - image = "dataplane:latest" - image_pull_policy = "Never" - - env_from { - config_map_ref { - name = kubernetes_config_map.dataplane-config.metadata[0].name - } - } - - port { - container_port = var.ports.public - name = "public-port" - } - - port { - container_port = var.ports.debug - name = "debug-port" - } - - liveness_probe { - http_get { - path = "/api/check/liveness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - readiness_probe { - http_get { - path = "/api/check/readiness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - startup_probe { - http_get { - path = "/api/check/startup" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - } - } - } - } -} - -resource "kubernetes_config_map" "dataplane-config" { - metadata { - name = "${lower(var.humanReadableName)}-dataplane-config" - namespace = var.namespace - } - - ## Create databases for keycloak and MIW, create users and assign privileges - data = { - # hostname is "localhost" by default, but must be the service name at which the dataplane is reachable. URL scheme and port are appended by the application - EDC_HOSTNAME = local.dataplane-service-name - EDC_RUNTIME_ID = "${var.humanReadableName}-dataplane" - EDC_PARTICIPANT_ID = var.participantId - EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS = "${var.participantId}#${var.aliases.sts-public-key-id}" - EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS = "${var.participantId}#${var.aliases.sts-private-key}" - EDC_DPF_SELECTOR_URL = "http://${local.controlplane-service-name}:${var.ports.control}/api/control/v1/dataplanes" - WEB_HTTP_PORT = var.ports.web - WEB_HTTP_PATH = "/api" - WEB_HTTP_CONTROL_PORT = var.ports.control - WEB_HTTP_CONTROL_PATH = "/api/control" - WEB_HTTP_PUBLIC_PORT = var.ports.public - WEB_HTTP_PUBLIC_PATH = "/api/public" - EDC_VAULT_HASHICORP_URL = var.vault-url - EDC_VAULT_HASHICORP_TOKEN = var.vault-token - JAVA_TOOL_OPTIONS = "${var.useSVE ? "-XX:UseSVE=0 " : ""}-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${var.ports.debug}" - EDC_DATASOURCE_DEFAULT_URL = var.database.url - EDC_DATASOURCE_DEFAULT_USER = var.database.user - EDC_DATASOURCE_DEFAULT_PASSWORD = var.database.password - EDC_SQL_SCHEMA_AUTOCREATE = true - - # remote STS configuration - EDC_IAM_STS_OAUTH_TOKEN_URL = var.sts-token-url - EDC_IAM_STS_OAUTH_CLIENT_ID = var.participantId - EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS = "${var.participantId}-sts-client-secret" - } -} diff --git a/deployment/modules/connector/ingress.tf b/deployment/modules/connector/ingress.tf deleted file mode 100644 index 8c4b5d3af..000000000 --- a/deployment/modules/connector/ingress.tf +++ /dev/null @@ -1,99 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_ingress_v1" "api-ingress" { - metadata { - name = "${var.humanReadableName}-ingress" - namespace = var.namespace - 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.humanReadableName}/health(/|$)(.*)" - backend { - service { - name = kubernetes_service.controlplane-service.metadata.0.name - port { - number = var.ports.web - } - } - } - } - - path { - path = "/${var.humanReadableName}/cp(/|$)(.*)" - backend { - service { - name = kubernetes_service.controlplane-service.metadata.0.name - port { - number = var.ports.management - } - } - } - } - - path { - path = "/${var.humanReadableName}/public(/|$)(.*)" - backend { - service { - name = kubernetes_service.dataplane-service.metadata.0.name - port { - number = var.ports.public - } - } - } - } - - path { - path = "/${var.humanReadableName}/fc(/|$)(.*)" - backend { - service { - name = kubernetes_service.controlplane-service.metadata.0.name - port { - number = var.ports.catalog - } - } - } - } - - path { - path = "/${var.humanReadableName}/vault(/|$)(.*)" - backend { - service { - name = "${var.humanReadableName}-vault" - port { - number = 8200 - } - } - } - } - } - } - } -} - -locals { - data-plane-service = "${var.humanReadableName}-dataplane" -} diff --git a/deployment/modules/connector/outputs.tf b/deployment/modules/connector/outputs.tf deleted file mode 100644 index 81a5e9c54..000000000 --- a/deployment/modules/connector/outputs.tf +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -output "connector-node-ip" { - value = kubernetes_service.controlplane-service.spec.0.cluster_ip -} - - -output "database-name" { - value = var.database -} - -output "ports" { - value = var.ports -} - -output "audience-mapping" { - value = { - # dspAudience = "http://${local.connector-cluster-ip}:${var.ports.protocol}/api/dsp" - dcpAudience = var.participantId - } -} diff --git a/deployment/modules/connector/services.tf b/deployment/modules/connector/services.tf deleted file mode 100644 index 972e1cd2d..000000000 --- a/deployment/modules/connector/services.tf +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_service" "controlplane-service" { - metadata { - name = local.controlplane-service-name - namespace = var.namespace - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.controlplane.spec.0.template.0.metadata[0].labels.App - } - port { - name = "health" - port = var.ports.web - } - port { - name = "management" - port = var.ports.management - } - port { - name = "catalog" - port = var.ports.catalog - } - port { - name = "protocol" - port = var.ports.protocol - } - port { - name = "debug" - port = var.ports.debug - } - port { - name = "control" - port = var.ports.control - } - } -} - -resource "kubernetes_service" "dataplane-service" { - metadata { - name = local.dataplane-service-name - namespace = var.namespace - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.dataplane.spec.0.template.0.metadata[0].labels.App - } - port { - name = "control" - port = var.ports.control - } - port { - name = "public" - port = var.ports.public - } - } -} \ No newline at end of file diff --git a/deployment/modules/connector/variables.tf b/deployment/modules/connector/variables.tf deleted file mode 100644 index 5c3c95f23..000000000 --- a/deployment/modules/connector/variables.tf +++ /dev/null @@ -1,115 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -## Normally, you shouldn't need to change any values here. If you do, please be sure to also change them in the seed script (seed-k8s.sh). -## Neglecting to do that will render the connectors and identity hubs inoperable! - - -variable "image-pull-policy" { - default = "Always" - type = string - description = "Kubernetes ImagePullPolicy for all images" -} - -variable "humanReadableName" { - type = string - description = "Human readable name of the connector, NOT the BPN!!. Required." -} - -variable "participantId" { - type = string - description = "DID:WEB identifier of the participant, will be used as runtime participantId" -} - -variable "namespace" { - type = string -} - -variable "ports" { - type = object({ - web = number - management = number - protocol = number - control = number - catalog = number - debug = number - public = number - }) - default = { - web = 8080 - management = 8081 - protocol = 8082 - control = 8083 - catalog = 8084 - debug = 1044 - public = 11002 - } -} - -variable "database" { - type = object({ - url = string - user = string - password = string - }) -} - -variable "participant-list-file" { - type = string - default = "./assets/participants/participants.k8s.json" -} - -variable "vault-token" { - default = "root" - description = "This is the authentication token for the vault. DO NOT USE THIS IN PRODUCTION!" - type = string -} - -variable "vault-url" { - description = "URL of the Hashicorp Vault" - type = string -} - -variable "sts-token-url" { - description = "Full URL of the STS token endpoint" - type = string -} - -variable "aliases" { - type = object({ - sts-private-key = string - sts-public-key-id = string - }) - default = { - sts-private-key = "key-1" - sts-public-key-id = "key-1" - } -} - -variable "useSVE" { - type = bool - description = "If true, the -XX:UseSVE=0 switch (Scalable Vector Extensions) will be appended to the JAVA_TOOL_OPTIONS. Can help on macOs on Apple Silicon processors" - default = false -} - -locals { - name = lower(var.humanReadableName) - controlplane-service-name = "${var.humanReadableName}-controlplane" - dataplane-service-name = "${var.humanReadableName}-dataplane" -} diff --git a/deployment/modules/identity-hub/ingress.tf b/deployment/modules/identity-hub/ingress.tf deleted file mode 100644 index dfacfac2d..000000000 --- a/deployment/modules/identity-hub/ingress.tf +++ /dev/null @@ -1,81 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -resource "kubernetes_ingress_v1" "api-ingress" { - metadata { - name = "${var.humanReadableName}-ingress" - namespace = var.namespace - 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.service-name}/cs(/|$)(.*)" - backend { - service { - name = kubernetes_service.ih-service.metadata.0.name - port { - number = var.ports.ih-identity-api - } - } - } - } - } - } - } -} - -// the DID endpoint can not actually modify the URL, otherwise it'll mess up the DID resolution -resource "kubernetes_ingress_v1" "did-ingress" { - metadata { - name = "${var.service-name}-did-ingress" - namespace = var.namespace - annotations = { - "nginx.ingress.kubernetes.io/rewrite-target" = "/${var.service-name}/$2" - } - } - - spec { - ingress_class_name = "nginx" - rule { - http { - - - # ingress routes for the DID endpoint - path { - path = "/${var.service-name}(/|&)(.*)" - backend { - service { - name = kubernetes_service.ih-service.metadata.0.name - port { - number = var.ports.ih-did - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/deployment/modules/identity-hub/main.tf b/deployment/modules/identity-hub/main.tf deleted file mode 100644 index e8aacd8f9..000000000 --- a/deployment/modules/identity-hub/main.tf +++ /dev/null @@ -1,171 +0,0 @@ -# -# 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 -# - -resource "kubernetes_deployment" "identityhub" { - metadata { - name = lower(var.humanReadableName) - namespace = var.namespace - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = lower(var.humanReadableName) - } - } - - template { - metadata { - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - container { - image_pull_policy = "Never" - image = "identity-hub:latest" - name = "identity-hub" - - env_from { - config_map_ref { - name = kubernetes_config_map.identityhub-config.metadata[0].name - } - } - port { - container_port = var.ports.credentials-api - name = "creds-port" - } - - port { - container_port = var.ports.ih-debug - name = "debug" - } - port { - container_port = var.ports.ih-identity-api - name = "identity" - } - port { - container_port = var.ports.ih-did - name = "did" - } - port { - container_port = var.ports.web - name = "default-port" - } - - volume_mount { - mount_path = "/etc/credentials" - name = "credentials-volume" - } - - liveness_probe { - http_get { - path = "/api/check/liveness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - readiness_probe { - http_get { - path = "/api/check/readiness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - startup_probe { - http_get { - path = "/api/check/startup" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - } - - volume { - name = "credentials-volume" - config_map { - name = kubernetes_config_map.identityhub-credentials-map.metadata[0].name - } - } - } - - } - } -} - - -resource "kubernetes_config_map" "identityhub-credentials-map" { - metadata { - name = "${lower(var.humanReadableName)}-credentials" - namespace = var.namespace - } - - data = { - for f in fileset(var.credentials-dir, "*-credential.json") : f => file(join("/", [var.credentials-dir, f])) - } -} - -resource "kubernetes_config_map" "identityhub-config" { - metadata { - name = "${lower(var.humanReadableName)}-ih-config" - namespace = var.namespace - } - - data = { - # IdentityHub variables - EDC_IH_IAM_ID = var.participantId - EDC_IAM_DID_WEB_USE_HTTPS = false - EDC_IH_IAM_PUBLICKEY_ALIAS = local.public-key-alias - EDC_IH_API_SUPERUSER_KEY = var.ih_superuser_apikey - WEB_HTTP_PORT = var.ports.web - WEB_HTTP_PATH = "/api" - WEB_HTTP_IDENTITY_PORT = var.ports.ih-identity-api - WEB_HTTP_IDENTITY_PATH = "/api/identity" - WEB_HTTP_IDENTITY_AUTH_KEY = "password" - WEB_HTTP_CREDENTIALS_PORT = var.ports.credentials-api - WEB_HTTP_CREDENTIALS_PATH = "/api/credentials" - WEB_HTTP_DID_PORT = var.ports.ih-did - WEB_HTTP_DID_PATH = "/" - WEB_HTTP_STS_PORT = var.ports.sts-api - WEB_HTTP_STS_PATH = var.sts-token-path - JAVA_TOOL_OPTIONS = "${var.useSVE ? "-XX:UseSVE=0 " : ""}-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${var.ports.debug}" - EDC_IAM_STS_PRIVATEKEY_ALIAS = var.aliases.sts-private-key - EDC_IAM_STS_PUBLICKEY_ID = var.aliases.sts-public-key-id - EDC_MVD_CREDENTIALS_PATH = "/etc/credentials/" - EDC_VAULT_HASHICORP_URL = var.vault-url - EDC_VAULT_HASHICORP_TOKEN = var.vault-token - EDC_DATASOURCE_DEFAULT_URL = var.database.url - EDC_DATASOURCE_DEFAULT_USER = var.database.user - EDC_DATASOURCE_DEFAULT_PASSWORD = var.database.password - EDC_SQL_SCHEMA_AUTOCREATE = true - EDC_IAM_ACCESSTOKEN_JTI_VALIDATION = true - - } -} - -locals { - public-key-alias = "${var.humanReadableName}-publickey" -} \ No newline at end of file diff --git a/deployment/modules/identity-hub/outputs.tf b/deployment/modules/identity-hub/outputs.tf deleted file mode 100644 index 007553071..000000000 --- a/deployment/modules/identity-hub/outputs.tf +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -output "identity-hub-node-ip" { - value = kubernetes_service.ih-service.spec.0.cluster_ip -} - - -output "ports" { - value = var.ports -} - -output "ih-superuser-apikey" { - value = var.ih_superuser_apikey -} - -output "credentials" { - value = { - path = var.credentials-dir - content = fileset(var.credentials-dir, "*-credential.json") - } -} - -output "sts-token-url" { - value = "http://${kubernetes_service.ih-service.metadata.0.name}:${var.ports.sts-api}${var.sts-token-path}" -} \ No newline at end of file diff --git a/deployment/modules/identity-hub/services.tf b/deployment/modules/identity-hub/services.tf deleted file mode 100644 index 65b503930..000000000 --- a/deployment/modules/identity-hub/services.tf +++ /dev/null @@ -1,46 +0,0 @@ -# -# 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 -# - -resource "kubernetes_service" "ih-service" { - metadata { - name = var.humanReadableName - namespace = var.namespace - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.identityhub.spec.0.template.0.metadata[0].labels.App - } - # we need a stable IP, otherwise there will be a cycle with the issuer - port { - name = "credentials" - port = var.ports.credentials-api - } - port { - name = "debug" - port = var.ports.ih-debug - } - port { - name = "management" - port = var.ports.ih-identity-api - } - port { - name = "did" - port = var.ports.ih-did - } - port { - name = "sts" - port = var.ports.sts-api - } - } -} \ No newline at end of file diff --git a/deployment/modules/identity-hub/variables.tf b/deployment/modules/identity-hub/variables.tf deleted file mode 100644 index c8e0f0d65..000000000 --- a/deployment/modules/identity-hub/variables.tf +++ /dev/null @@ -1,115 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -## Normally, you shouldn't need to change any values here. If you do, please be sure to also change them in the seed script (seed-k8s.sh). -## Neglecting to do that will render the connectors and identity hubs inoperable! - - -variable "humanReadableName" { - type = string - description = "Human readable name of the connector, NOT the ID!!. Required." -} - -variable "participantId" { - type = string - description = "Participant ID of the connector. Usually a DID" -} - -variable "namespace" { - type = string -} - -variable "ports" { - type = object({ - web = number - debug = number - ih-debug = number - ih-did = number - ih-identity-api = number - credentials-api = number - sts-api = number - }) - default = { - web = 7080 - debug = 1044 - ih-debug = 1044 - ih-did = 7083 - ih-identity-api = 7081 - credentials-api = 7082 - sts-api = 7084 - } -} - -variable "credentials-dir" { - type = string - description = "JSON object containing the credentials to seed, sorted by human-readable participant name" -} - -variable "ih_superuser_apikey" { - default = "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=" - description = "Management API Key for the Super-User. Defaults to 'base64(super-user).base64(super-secret-key)" - type = string -} - -variable "vault-url" { - description = "URL of the Hashicorp Vault" - type = string -} - -variable "vault-token" { - default = "root" - description = "This is the authentication token for the vault. DO NOT USE THIS IN PRODUCTION!" - type = string -} - -variable "aliases" { - type = object({ - sts-private-key = string - sts-public-key-id = string - }) - default = { - sts-private-key = "key-1" - sts-public-key-id = "key-1" - } -} - -variable "service-name" { - type = string - description = "Name of the Service endpoint" -} - -variable "database" { - type = object({ - url = string - user = string - password = string - }) -} - -variable "useSVE" { - type = bool - description = "If true, the -XX:UseSVE=0 switch (Scalable Vector Extensions) will be appended to the JAVA_TOOL_OPTIONS. Can help on macOs on Apple Silicon processors" - default = false -} - -variable "sts-token-path" { - description = "path suffix of the STS token API" - type = string - default = "/api/sts" -} \ No newline at end of file diff --git a/deployment/modules/issuer/ingress.tf b/deployment/modules/issuer/ingress.tf deleted file mode 100644 index b1219dd67..000000000 --- a/deployment/modules/issuer/ingress.tf +++ /dev/null @@ -1,87 +0,0 @@ -# -# Copyright (c) 2025 Cofinity-X -# -# 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: -# Cofinity-X - initial API and implementation -# - -resource "kubernetes_ingress_v1" "api-ingress" { - metadata { - name = "${var.humanReadableName}-ingress" - namespace = var.namespace - annotations = { - "nginx.ingress.kubernetes.io/rewrite-target" = "/$2" - "nginx.ingress.kubernetes.io/use-regex" = "true" - } - } - spec { - ingress_class_name = "nginx" - rule { - http { - - path { - path = "/issuer/cs(/|$)(.*)" - backend { - service { - name = kubernetes_service.issuerservice-service.metadata.0.name - port { - number = var.ports.identity - } - } - } - } - - path { - path = "/issuer/ad(/|$)(.*)" - backend { - service { - name = kubernetes_service.issuerservice-service.metadata.0.name - port { - number = var.ports.issueradmin - } - } - } - } - } - } - } -} - -// the DID endpoint can not actually modify the URL, otherwise it'll mess up the DID resolution -resource "kubernetes_ingress_v1" "did-ingress" { - metadata { - name = "${var.humanReadableName}-did-ingress" - namespace = var.namespace - annotations = { - "nginx.ingress.kubernetes.io/rewrite-target" = "/issuer/$2" - } - } - - spec { - ingress_class_name = "nginx" - rule { - http { - - - # ingress routes for the DID endpoint - path { - path = "/issuer(/|&)(.*)" - backend { - service { - name = kubernetes_service.issuerservice-service.metadata.0.name - port { - number = var.ports.did - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/deployment/modules/issuer/main.tf b/deployment/modules/issuer/main.tf deleted file mode 100644 index c19adf7e0..000000000 --- a/deployment/modules/issuer/main.tf +++ /dev/null @@ -1,159 +0,0 @@ -# -# Copyright (c) 2025 Cofinity-X -# -# 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: -# Cofinity-X - initial API and implementation -# - -resource "kubernetes_deployment" "issuerservice" { - metadata { - name = lower(var.humanReadableName) - namespace = var.namespace - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = lower(var.humanReadableName) - } - } - - template { - metadata { - labels = { - App = lower(var.humanReadableName) - } - } - - spec { - container { - image_pull_policy = "Never" - image = "issuerservice:latest" - name = "issuerservice" - - env_from { - config_map_ref { - name = kubernetes_config_map.issuerservice-config.metadata[0].name - } - } - port { - container_port = var.ports.web - name = "web" - } - - port { - container_port = var.ports.sts - name = "sts" - } - port { - container_port = var.ports.debug - name = "debug" - } - port { - container_port = var.ports.issuance - name = "issuance" - } - port { - container_port = var.ports.issueradmin - name = "issueradmin" - } - port { - container_port = var.ports.identity - name = "identity-port" - } - - port { - container_port = var.ports.did - name = "did" - } - - liveness_probe { - http_get { - path = "/api/check/liveness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - readiness_probe { - http_get { - path = "/api/check/readiness" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - - startup_probe { - http_get { - path = "/api/check/startup" - port = var.ports.web - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - } - } - } - } -} - -resource "kubernetes_config_map" "issuerservice-config" { - metadata { - name = "${lower(var.humanReadableName)}-config" - namespace = var.namespace - } - - data = { - EDC_ISSUER_STATUSLIST_SIGNING_KEY_ALIAS = "statuslist-signing-key" - EDC_IH_API_SUPERUSER_KEY = var.superuser_apikey - WEB_HTTP_PORT = var.ports.web - WEB_HTTP_PATH = "/api" - WEB_HTTP_STS_PORT = var.ports.sts - WEB_HTTP_STS_PATH = "/api/sts" - WEB_HTTP_ISSUANCE_PORT = var.ports.issuance - WEB_HTTP_ISSUANCE_PATH = "/api/issuance" - WEB_HTTP_ISSUERADMIN_PORT = var.ports.issueradmin - WEB_HTTP_ISSUERADMIN_PATH = "/api/admin" - WEB_HTTP_VERSION_PORT = var.ports.version - WEB_HTTP_VERSION_PATH = "/.well-known/api" - WEB_HTTP_IDENTITY_PORT = var.ports.identity - WEB_HTTP_IDENTITY_PATH = "/api/identity" - WEB_HTTP_IDENTITY_AUTH_KEY = "password" - WEB_HTTP_DID_PORT = var.ports.did - WEB_HTTP_DID_PATH = "/" - - JAVA_TOOL_OPTIONS = "${var.useSVE ? "-XX:UseSVE=0 " : ""}-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${var.ports.debug}" - EDC_VAULT_HASHICORP_URL = var.vault-url - EDC_VAULT_HASHICORP_TOKEN = var.vault-token - EDC_DATASOURCE_DEFAULT_URL = var.database.url - EDC_DATASOURCE_DEFAULT_USER = var.database.user - EDC_DATASOURCE_DEFAULT_PASSWORD = var.database.password - - # even though we have a default data source, we need a named datasource for the DatabaseAttestationSource, because - # that is configured in the AttestationDefinition - EDC_DATASOURCE_MEMBERSHIP_URL = var.database.url - EDC_DATASOURCE_MEMBERSHIP_USER = var.database.user - EDC_DATASOURCE_MEMBERSHIP_PASSWORD = var.database.password - - EDC_SQL_SCHEMA_AUTOCREATE = true - EDC_IAM_ACCESSTOKEN_JTI_VALIDATION = true - EDC_IAM_DID_WEB_USE_HTTPS = false - - } -} - diff --git a/deployment/modules/issuer/services.tf b/deployment/modules/issuer/services.tf deleted file mode 100644 index 8f577e265..000000000 --- a/deployment/modules/issuer/services.tf +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2025 Cofinity-X -# -# 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: -# Cofinity-X - initial API and implementation -# - -resource "kubernetes_service" "issuerservice-service" { - metadata { - name = var.humanReadableName - namespace = var.namespace - } - spec { - type = "NodePort" - selector = { - App = kubernetes_deployment.issuerservice.spec.0.template.0.metadata[0].labels.App - } - port { - name = "web" - port = var.ports.web - } - port { - name = "sts" - port = var.ports.sts - } - port { - name = "debug" - port = var.ports.debug - } - port { - name = "issuance" - port = var.ports.issuance - } - port { - name = "issueradmin" - port = var.ports.issueradmin - } - port { - name = "identity" - port = var.ports.identity - } - port { - name = "did" - port = var.ports.did - } - } -} \ No newline at end of file diff --git a/deployment/modules/issuer/variables.tf b/deployment/modules/issuer/variables.tf deleted file mode 100644 index c2119289a..000000000 --- a/deployment/modules/issuer/variables.tf +++ /dev/null @@ -1,82 +0,0 @@ -# -# Copyright (c) 2025 Cofinity-X -# -# 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: -# Cofinity-X - initial API and implementation -# - - -variable "humanReadableName" { - type = string - description = "Human readable name of the issuer, NOT the ID!!. Required." - default = "issuerservice" -} - -variable "participantId" { - type = string - description = "Participant ID of the issuer. Usually a DID" -} - -variable "namespace" { - type = string -} - -variable "ports" { - type = object({ - web = number - sts = number - issuance = number - issueradmin = number - version = number - identity = number - debug = number - did = number - }) - default = { - web = 10010 - sts = 10011 - issuance = 10012 - issueradmin = 10013 - version = 10014 - identity = 10015 - did = 10016 - debug = 1044 - } -} - -variable "database" { - type = object({ - url = string - user = string - password = string - }) -} - -variable "useSVE" { - type = bool - description = "If true, the -XX:UseSVE=0 switch (Scalable Vector Extensions) will be appended to the JAVA_TOOL_OPTIONS. Can help on macOs on Apple Silicon processors" - default = false -} - -variable "vault-url" { - description = "URL of the Hashicorp Vault" - type = string -} - -variable "vault-token" { - default = "root" - description = "This is the authentication token for the vault. DO NOT USE THIS IN PRODUCTION!" - type = string -} - -variable "superuser_apikey" { - default = "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=" - description = "Management API Key for the Super-User. Defaults to 'base64(super-user).base64(super-secret-key)" - type = string -} diff --git a/deployment/modules/postgres/main.tf b/deployment/modules/postgres/main.tf deleted file mode 100644 index 31571f954..000000000 --- a/deployment/modules/postgres/main.tf +++ /dev/null @@ -1,131 +0,0 @@ -# -# 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 -# - -resource "kubernetes_deployment" "postgres" { - metadata { - name = local.app-name - namespace = var.namespace - labels = { - App = local.app-name - } - } - - spec { - replicas = 1 - selector { - match_labels = { - App = local.app-name - } - } - template { - metadata { - labels = { - App = local.app-name - } - } - spec { - container { - image = local.pg-image - name = local.app-name - - env_from { - config_map_ref { - name = kubernetes_config_map.postgres-env.metadata[0].name - } - } - port { - container_port = 5432 - name = "postgres-port" - } - - dynamic "volume_mount" { - for_each = toset(var.init-sql-configs) - content { - mount_path = "/docker-entrypoint-initdb.d/${volume_mount.value}.sql" - name = volume_mount.value - sub_path = "${volume_mount.value}.sql" - read_only = true - } - } - - # Uncomment this to assign (more) resources - # resources { - # limits = { - # cpu = "2" - # memory = "512Mi" - # } - # requests = { - # cpu = "250m" - # memory = "50Mi" - # } - # } - liveness_probe { - exec { - command = ["pg_isready", "-U", "postgres"] - } - failure_threshold = 10 - period_seconds = 5 - timeout_seconds = 30 - } - } - - dynamic "volume" { - for_each = toset(var.init-sql-configs) - content { - name = volume.value - config_map { - name = volume.value - } - } - } - } - } - } -} - -resource "kubernetes_config_map" "postgres-env" { - metadata { - name = "${local.app-name}-env" - namespace = var.namespace - } - - ## Create databases for keycloak and MIW, create users and assign privileges - data = { - POSTGRES_USER = "postgres" - POSTGRES_PASSWORD = "postgres" - } -} - -resource "kubernetes_service" "pg-service" { - metadata { - name = "${local.app-name}-service" - namespace = var.namespace - } - spec { - selector = { - App = kubernetes_deployment.postgres.spec.0.template.0.metadata[0].labels.App - } - port { - name = "pg-port" - port = var.database-port - target_port = var.database-port - } - } -} - -locals { - app-name = "${var.instance-name}-postgres" - pg-image = "postgres:16.3-alpine3.20" - db-ip = kubernetes_service.pg-service.spec.0.cluster_ip - db-url = "${kubernetes_service.pg-service.metadata[0].name}:${var.database-port}" -} diff --git a/deployment/modules/postgres/outputs.tf b/deployment/modules/postgres/outputs.tf deleted file mode 100644 index 5e1ddfb1d..000000000 --- a/deployment/modules/postgres/outputs.tf +++ /dev/null @@ -1,28 +0,0 @@ -# -# 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 -# - -output "instance-name" { - value = var.instance-name -} - -output "database-host" { - value = local.db-ip -} - -output "database-port" { - value = var.database-port -} - -output "database-url" { - value = local.db-url -} diff --git a/deployment/modules/postgres/variables.tf b/deployment/modules/postgres/variables.tf deleted file mode 100644 index 7c5e66be2..000000000 --- a/deployment/modules/postgres/variables.tf +++ /dev/null @@ -1,29 +0,0 @@ -# -# 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 -# - -variable "instance-name" { - description = "Name for the Postgres instance, must be unique for each postgres instances" -} - -variable "database-port" { - default = 5432 -} - -variable "init-sql-configs" { - description = "Name of config maps with init sql scripts" - default = [] -} - -variable "namespace" { - description = "kubernetes namespace where the PG instance is deployed" -} \ No newline at end of file diff --git a/deployment/modules/vault/variables.tf b/deployment/modules/vault/variables.tf deleted file mode 100644 index 1ad67483a..000000000 --- a/deployment/modules/vault/variables.tf +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (c) 2024 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -variable "humanReadableName" { - type = string - description = "Human readable name. Should not contain special characters" -} - -variable "namespace" { - type = string -} - -variable "vault-token" { - default = "root" - description = "This is the authentication token for the vault. DO NOT USE THIS IN PRODUCTION!" - type = string -} - -variable "aliases" { - type = object({ - sts-private-key = string - sts-public-key-id = string - }) - default = { - sts-private-key = "key-1" - sts-public-key-id = "key-1" - } -} \ No newline at end of file diff --git a/deployment/modules/vault/vault-values.yaml b/deployment/modules/vault/vault-values.yaml deleted file mode 100644 index e7a5167ed..000000000 --- a/deployment/modules/vault/vault-values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# -# 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 -# - -server: - postStart: -hashicorp: - timeout: 30 - healthCheck: - enabled: true - standbyOk: true - paths: - secret: /v1/secret diff --git a/deployment/modules/vault/vault.tf b/deployment/modules/vault/vault.tf deleted file mode 100644 index 371ccf964..000000000 --- a/deployment/modules/vault/vault.tf +++ /dev/null @@ -1,70 +0,0 @@ -# -# 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 -# - -resource "helm_release" "vault" { - name = var.humanReadableName - namespace = var.namespace - - force_update = true - dependency_update = true - reuse_values = true - cleanup_on_fail = true - replace = true - - repository = "https://helm.releases.hashicorp.com" - chart = "vault" - - - - set = [ - { - name = "server.dev.devRootToken" - value = var.vault-token - }, - { - name = "server.dev.enabled" - value = true - }, - { - name = "injector.enabled" - value = false - }, - { - name = "hashicorp.token" - value = var.vault-token - } - ] - - values = [ - file("${path.module}/vault-values.yaml"), - # yamlencode({ - # "server" : { - # "postStart" : [ - # "sh", - # "-c", - # join(" && ", [ - # "sleep 5", - # "/bin/vault kv put secret/${var.aliases.sts-private-key} content=\"${tls_private_key.private_signing_key.private_key_pem}\"", - # # "/bin/vault kv put secret/${local.public-key-alias} content=\"${tls_private_key.ecdsa.public_key_pem}\"" - # ]) - # ] - # } - # }), - ] -} -# -# ECDSA key with P256 elliptic curve -resource "tls_private_key" "private_signing_key" { - algorithm = "ECDSA" - ecdsa_curve = "P256" -} diff --git a/deployment/outputs.tf b/deployment/outputs.tf deleted file mode 100644 index 6d848a95f..000000000 --- a/deployment/outputs.tf +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -output "consumer-jdbc-url" { - # jdbc:postgresql://localhost:5432/mydatabase?currentSchema=myschema - value = "jdbc:postgresql://${module.consumer-postgres.database-url}/consumer" -} - -output "provider-jdbc-url" { - value = { - catalog-server = "jdbc:postgresql://${module.provider-postgres.database-url}/catalog_server" - provider-qna = "jdbc:postgresql://${module.provider-postgres.database-url}/provider_qna" - provider-manufacturing = "jdbc:postgresql://${module.provider-postgres.database-url}/provider_manufacturing" - } -} \ No newline at end of file diff --git a/deployment/postman/MVD K8S.postman_environment.json b/deployment/postman/MVD K8S.postman_environment.json deleted file mode 100644 index 614bb5e74..000000000 --- a/deployment/postman/MVD K8S.postman_environment.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "id": "9330e6b5-fffa-40a9-8835-5e76233f9ccd", - "name": "MVD K8S", - "values": [ - { - "key": "HOST", - "value": "http://localhost/consumer/cp", - "type": "default", - "enabled": true - }, - { - "key": "CS_URL", - "value": "http://localhost/consumer/cs/", - "type": "default", - "enabled": true - }, - { - "key": "CATALOG_SERVER_DSP_URL", - "value": "http://provider-catalog-server-controlplane:8082", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_CATALOG_QUERY_URL", - "value": "http://localhost/consumer/fc", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_PUBLIC_API", - "value": "http://localhost/provider-qna/public", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_DSP_URL", - "value": "http://provider-qna-controlplane:8082", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_ID", - "value": "did:web:provider-identityhub%3A7083:provider", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_NAME", - "value": "MVD Provider Participant", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_ID", - "value": "did:web:consumer-identityhub%3A7083:consumer", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_NAME", - "value": "MVD Consumer Participant", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_DID", - "value": "did:web:dataspace-issuer-service%3A10016:issuer", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_BASE_URL", - "value": "http://localhost/issuer/ad", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_ADMIN_URL", - "value": "", - "type": "default", - "enabled": true - }, - { - "key": "PARTICIPANT_ID_BASE64", - "value": "", - "type": "default", - "enabled": true - }, - { - "key": "REQUEST_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "POLICY_ID_ASSET_1", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "CONTRACT_NEGOTIATION_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "CONTRACT_AGREEMENT_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "TRANSFER_PROCESS_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AUTHORIZATION", - "value": "", - "type": "any", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2025-03-05T06:26:50.206Z", - "_postman_exported_using": "Postman/11.34.4" -} \ No newline at end of file diff --git a/deployment/postman/MVD Local Development.postman_environment.json b/deployment/postman/MVD Local Development.postman_environment.json deleted file mode 100644 index bc81584fc..000000000 --- a/deployment/postman/MVD Local Development.postman_environment.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "id": "448d5e51-e4f9-4b2a-96ea-1054aab52c1d", - "name": "MVD Local Development", - "values": [ - { - "key": "HOST", - "value": "http://localhost:8081", - "type": "default", - "enabled": true - }, - { - "key": "CS_URL", - "value": "http://localhost:7082", - "type": "default", - "enabled": true - }, - { - "key": "CATALOG_SERVER_DSP_URL", - "value": "http://localhost:8092", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_CATALOG_QUERY_URL", - "value": "http://localhost:8084", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_DSP_URL", - "value": "http://localhost:8192", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_PUBLIC_API", - "value": "http://localhost:12001", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_BASE_URL", - "value": "", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_ADMIN_URL", - "value": "http://localhost:10013", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_ID", - "value": "did:web:localhost%3A7083", - "type": "default", - "enabled": true - }, - { - "key": "CONSUMER_NAME", - "value": "MVD Consumer Participant", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_ID", - "value": "did:web:localhost%3A7093", - "type": "default", - "enabled": true - }, - { - "key": "PROVIDER_NAME", - "value": "MVD Provider Participant", - "type": "default", - "enabled": true - }, - { - "key": "ISSUER_DID", - "value": "did:web:localhost%3A10100", - "type": "default", - "enabled": true - }, - { - "key": "POLICY_ID_ASSET_1", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "PARTICIPANT_ID_BASE64", - "value": "ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgz", - "type": "default", - "enabled": true - }, - { - "key": "REQUEST_ID", - "value": "", - "type": "any", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2025-03-05T06:26:44.509Z", - "_postman_exported_using": "Postman/11.34.4" -} \ No newline at end of file diff --git a/deployment/postman/MVD.postman_collection.json b/deployment/postman/MVD.postman_collection.json deleted file mode 100644 index c373dd48b..000000000 --- a/deployment/postman/MVD.postman_collection.json +++ /dev/null @@ -1,6218 +0,0 @@ -{ - "info": { - "_postman_id": "46b6d41a-f249-4571-8ffe-0ee7fc25f6e0", - "name": "MVD", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "647585" - }, - "item": [ - { - "name": "Seed", - "item": [ - { - "name": "Create Asset 1", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"asset-1\",\n \"@type\": \"Asset\",\n \"properties\": {\n \"description\": \"This asset requires Membership to view and negotiate.\"\n },\n \"dataAddress\": {\n \"@type\": \"DataAddress\",\n \"type\": \"HttpData\",\n \"baseUrl\": \"https://jsonplaceholder.typicode.com/todos\",\n \"proxyPath\": \"true\",\n \"proxyQueryParams\": \"true\"\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets" - ] - } - }, - "response": [] - }, - { - "name": "Create Asset 2", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"asset-2\",\n \"@type\": \"Asset\",\n \"properties\": {\n \"description\": \"This asset requires Membership to view and SensitiveData credential to negotiate.\"\n },\n \"dataAddress\": {\n \"@type\": \"DataAddress\",\n \"type\": \"HttpData\",\n \"baseUrl\": \"https://jsonplaceholder.typicode.com/todos\",\n \"proxyPath\": \"true\",\n \"proxyQueryParams\": \"true\"\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets" - ] - } - }, - "response": [] - }, - { - "name": "Create Membership Policy", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"PolicyDefinition\",\n \"@id\": \"require-membership\",\n \"policy\": {\n \"@type\": \"Set\",\n \"permission\": [\n {\n \"action\": \"use\",\n \"constraint\": {\n \"leftOperand\": \"MembershipCredential\",\n \"operator\": \"eq\",\n \"rightOperand\": \"active\"\n }\n }\n ]\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/policydefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "policydefinitions" - ] - } - }, - "response": [] - }, - { - "name": "Create DataProcessor policy", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"PolicyDefinition\",\n \"@id\": \"require-dataprocessor\",\n \"policy\": {\n \"@type\": \"Set\",\n \"obligation\": [\n {\n \"action\": \"use\",\n \"constraint\": {\n \"leftOperand\": \"DataAccess.level\",\n \"operator\": \"eq\",\n \"rightOperand\": \"processing\"\n }\n }\n ]\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/policydefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "policydefinitions" - ] - } - }, - "response": [] - }, - { - "name": "Create Sensitive Data Processor policy", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"PolicyDefinition\",\n \"@id\": \"require-sensitive\",\n \"policy\": {\n \"@type\": \"Set\",\n \"obligation\": [\n {\n \"action\": \"use\",\n \"constraint\": {\n \"leftOperand\": \"DataAccess.level\",\n \"operator\": \"eq\",\n \"rightOperand\": \"sensitive\"\n }\n }\n ]\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/policydefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "policydefinitions" - ] - } - }, - "response": [] - }, - { - "name": "Create \"member-and-data-cred\" definition", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"member-and-dataprocessor-def\",\n \"@type\": \"ContractDefinition\",\n \"accessPolicyId\": \"require-membership\",\n \"contractPolicyId\": \"require-dataprocessor\",\n \"assetsSelector\": {\n \"@type\": \"Criterion\",\n \"operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\n \"operator\": \"=\",\n \"operandRight\": \"asset-1\"\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/contractdefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "contractdefinitions" - ] - } - }, - "response": [] - }, - { - "name": "Create \"require sensitive\" definition", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"sensitive-only-def\",\n \"@type\": \"ContractDefinition\",\n \"accessPolicyId\": \"require-membership\",\n \"contractPolicyId\": \"require-sensitive\",\n \"assetsSelector\": {\n \"@type\": \"Criterion\",\n \"operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\n \"operator\": \"=\",\n \"operandRight\": \"asset-2\"\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/contractdefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "contractdefinitions" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204, 409])", - "})" - ] - } - } - ] - }, - { - "name": "Seed Catalog Server", - "item": [ - { - "name": "Create linked Asset for provider-qna", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"linked-asset-provider-qna\",\n \"@type\": \"CatalogAsset\",\n \"properties\": {\n \"description\": \"This is a linked asset that points to the catalog of the provider's Q&A department.\",\n \"isCatalog\": \"true\"\n },\n \"dataAddress\": {\n \"@type\": \"DataAddress\",\n \"type\": \"HttpData\",\n \"baseUrl\": \"{{PROVIDER_QNA_DSP_URL}}/api/dsp\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets" - ] - } - }, - "response": [] - }, - { - "name": "Create linked Asset for provider-manufacturing", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"linked-asset-provider-manufacturing\",\n \"@type\": \"CatalogAsset\",\n \"properties\": {\n \"description\": \"This is a linked asset that points to the catalog of the provider's Manufacturing department.\",\n \"isCatalog\": \"true\"\n },\n \"dataAddress\": {\n \"@type\": \"DataAddress\",\n \"type\": \"HttpData\",\n \"baseUrl\": \"{{PROVIDER_MF_DSP_URL}}/api/dsp\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets" - ] - } - }, - "response": [] - }, - { - "name": "Create normal asset for CatalogServer", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"normal-asset-1\",\n \"@type\": \"Asset\",\n \"properties\": {\n \"description\": \"This is a conventional asset, not a CatalogAsset.\"\n },\n \"dataAddress\": {\n \"@type\": \"DataAddress\",\n \"type\": \"HttpData\",\n \"baseUrl\": \"https://jsonplaceholder.typicode.com/todos\",\n \"proxyPath\": \"true\",\n \"proxyQueryParams\": \"true\"\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets" - ] - } - }, - "response": [] - }, - { - "name": "Create Membership Policy", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"PolicyDefinition\",\n \"@id\": \"require-membership\",\n \"policy\": {\n \"@type\": \"Set\",\n \"permission\": [\n {\n \"action\": \"use\",\n \"constraint\": {\n \"leftOperand\": \"MembershipCredential\",\n \"operator\": \"eq\",\n \"rightOperand\": \"active\"\n }\n }\n ]\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/policydefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "policydefinitions" - ] - } - }, - "response": [] - }, - { - "name": "Create \"require membership\" definition", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@id\": \"membership-required-def\",\n \"@type\": \"ContractDefinition\",\n \"accessPolicyId\": \"require-membership\",\n \"contractPolicyId\": \"require-membership\",\n \"assetsSelector\": {\n \"@type\": \"Criterion\",\n \"operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\n \"operator\": \"in\",\n \"operandRight\": [\n \"linked-asset-provider-qna\",\n \"linked-asset-provider-manufacturing\",\n \"normal-asset-1\"\n ]\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/contractdefinitions", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "contractdefinitions" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204, 409])", - "})" - ] - } - } - ] - }, - { - "name": "ControlPlane Management", - "item": [ - { - "name": "Get Assets", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": {\n \"@vocab\": \"https://w3id.org/edc/v0.0.1/ns/\"\n },\n \"@type\": \"QuerySpec\"\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/assets/request", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "assets", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Request Catalog", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"CatalogRequest\",\n \"counterPartyAddress\": \"{{CATALOG_SERVER_DSP_URL}}/api/dsp\",\n \"counterPartyId\": \"{{PROVIDER_ID}}\",\n \"protocol\": \"dataspace-protocol-http\",\n \"querySpec\": {\n \"offset\": 0,\n \"limit\": 50\n }\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/catalog/request", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "catalog", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Get Cached Catalogs", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "// get the policy id of \"asset-1\" and save it as an environment variable", - "if(pm.response.code < 300 && pm.response.code >= 200){", - " if(pm.response.json().length > 0){", - " const dcat_datasets = pm.response.json()[0][\"dcat:catalog\"][1][\"dcat:dataset\"]", - " const asset_1 = dcat_datasets.find((asset) => asset[\"@id\"] == \"asset-1\")", - " pm.environment.set(\"POLICY_ID_ASSET_1\", asset_1[\"odrl:hasPolicy\"][\"@id\"]);", - " }", - "}", - "", - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "pm.test(\"Policy id for asset 1 is set\", function(){", - " pm.expect(pm.environment.get(\"POLICY_ID_ASSET_1\")).not.to.be.undefined", - "})" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"QuerySpec\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CONSUMER_CATALOG_QUERY_URL}}/api/catalog/v1alpha/catalog/query", - "host": [ - "{{CONSUMER_CATALOG_QUERY_URL}}" - ], - "path": [ - "api", - "catalog", - "v1alpha", - "catalog", - "query" - ] - } - }, - "response": [] - }, - { - "name": "Initiate negotiation", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "if(!pm.environment.has(\"POLICY_ID_ASSET_1\")){", - " throw new Error('Policy-ID of Asset-1 is not yet available, please execute request \"Get Cached Catalog\" first!');", - "}" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.environment.set(\"CONTRACT_NEGOTIATION_ID\", pm.response.json()[\"@id\"])", - "", - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "pm.test(\"Contract negotiation id is set\", function(){", - " pm.expect(pm.environment.get(\"CONTRACT_NEGOTIATION_ID\")).not.to.be.undefined", - "})" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"ContractRequest\",\n \"counterPartyAddress\": \"{{PROVIDER_DSP_URL}}/api/dsp\",\n \"counterPartyId\": \"{{PROVIDER_ID}}\",\n \"protocol\": \"dataspace-protocol-http\",\n \"policy\": {\n \"@type\": \"Offer\",\n \"@id\": \"{{POLICY_ID_ASSET_1}}\",\n \"assigner\": \"{{PROVIDER_ID}}\",\n \"permission\": [],\n \"prohibition\": [],\n \"obligation\": {\n \"action\": \"use\",\n \"constraint\": {\n \"leftOperand\": \"DataAccess.level\",\n \"operator\": \"eq\",\n \"rightOperand\": \"processing\"\n }\n },\n \"target\": \"asset-1\"\n },\n \"callbackAddresses\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{HOST}}/api/management/v3/contractnegotiations", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "contractnegotiations" - ] - } - }, - "response": [] - }, - { - "name": "Get Contract Negotiations", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "// get the contact agreement id and save it as an environment variable", - "if(pm.response.code < 300 && pm.response.code >= 200 && pm.response.json().length > 0){", - " var find_negotiation;", - " if (pm.environment.has(\"CONTRACT_NEGOTIATION_ID\")){", - " find_negotiation = pm.response.json().find((el) => el[\"@id\"] == pm.environment.get(\"CONTRACT_NEGOTIATION_ID\"))", - " }", - "", - " if(find_negotiation){", - " const contractAgreementId = find_negotiation[\"contractAgreementId\"];", - " pm.environment.set(\"CONTRACT_AGREEMENT_ID\", contractAgreementId);", - " }", - "}", - "", - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "pm.test(\"Contract Agreement ID is set\", function(){", - " pm.expect(pm.environment.get(\"CONTRACT_AGREEMENT_ID\")).not.to.be.undefined", - "})", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"QuerySpec\"\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/contractnegotiations/request", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "contractnegotiations", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Initiate Transfer", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "if(!pm.environment.has(\"CONTRACT_AGREEMENT_ID\")){", - " throw new Error('Contract Agreement ID is not yet available, please execute requests \"Initiate Negotiation and Get Contract Negotiation\" first!');", - "}" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"assetId\": \"asset-1\",\n \"counterPartyAddress\": \"{{PROVIDER_DSP_URL}}/api/dsp\",\n \"connectorId\": \"{{PROVIDER_ID}}\",\n \"contractId\": \"{{CONTRACT_AGREEMENT_ID}}\",\n \"dataDestination\": {\n \"type\": \"HttpProxy\"\n },\n \"protocol\": \"dataspace-protocol-http\",\n \"transferType\": \"HttpData-PULL\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{HOST}}/api/management/v3/transferprocesses", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "transferprocesses" - ] - } - }, - "response": [] - }, - { - "name": "Get transfer processes", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"QuerySpec\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{HOST}}/api/management/v3/transferprocesses/request", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "transferprocesses", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Get cached EDRs", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "// get the transfer process id of \"asset-1\" and save it as an environment variable if the response body is not empty", - "if(pm.response.code < 300 && pm.response.code >= 200 && pm.response.json().length > 0){", - " const transferProcessId = pm.response.json()[0][\"transferProcessId\"];", - " pm.environment.set(\"TRANSFER_PROCESS_ID\", transferProcessId);", - "}", - "", - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});", - "pm.test(\"Transfer process id is set\", function(){", - " pm.expect(pm.environment.get(\"TRANSFER_PROCESS_ID\")).not.to.be.undefined", - "})", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"@context\": [\n \"https://w3id.org/edc/connector/management/v0.0.1\"\n ],\n \"@type\": \"QuerySpec\"\n}" - }, - "url": { - "raw": "{{HOST}}/api/management/v3/edrs/request", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "edrs", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Get EDR DataAddress for TransferId", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "if(!pm.environment.has(\"TRANSFER_PROCESS_ID\")){", - " throw new Error('Transfer Process ID is not yet available, please execute request \"Get Transfer Processes\" first!');", - "}" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "// get the authorization token and save it as an environment variable", - "if(pm.response.code < 300 && pm.response.code >= 200){", - " //using the first authorization token found", - " const authorization = pm.response.json()[\"authorization\"];", - " pm.environment.set(\"AUTHORIZATION\", authorization);", - "}", - "", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{HOST}}/api/management/v3/edrs/{{TRANSFER_PROCESS_ID}}/dataaddress", - "host": [ - "{{HOST}}" - ], - "path": [ - "api", - "management", - "v3", - "edrs", - "{{TRANSFER_PROCESS_ID}}", - "dataaddress" - ] - } - }, - "response": [] - }, - { - "name": "Download Data from Public API", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "if(!pm.environment.has(\"AUTHORIZATION\")){", - " throw new Error(' The authorization token is not yet available, please execute request \"Get EDR DataAddress for TransferId\" first!');", - "}" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is >=200 and <300\", function () {", - " pm.expect(pm.response.code < 300 && pm.response.code >= 200).to.be.true", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "{{AUTHORIZATION}}", - "type": "text" - } - ], - "url": { - "raw": "{{PROVIDER_PUBLIC_API}}/api/public", - "host": [ - "{{PROVIDER_PUBLIC_API}}" - ], - "path": [ - "api", - "public" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "IdentityHub", - "item": [ - { - "name": "Participant Context Mgmt API", - "item": [ - { - "name": "Get Participant By ID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}" - ] - } - }, - "response": [] - }, - { - "name": "Get all participants", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants" - ] - } - }, - "response": [] - }, - { - "name": "Create Participant", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"roles\":[],\n \"serviceEndpoints\":[],\n \"active\": true,\n \"participantId\": \"{{NEW_PARTICIPANT_ID}}\",\n \"did\": \"{{NEW_PARTICIPANT_ID}}\",\n \"key\":{\n \"keyId\": \"key-1\",\n \"privateKeyAlias\": \"{{NEW_PARTICIPANT_ID}}-alias\",\n \"keyGeneratorParams\":{\n \"algorithm\": \"EdDSA\",\n \"curve\": \"Ed25519\"\n }\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "" - ] - } - }, - "response": [] - }, - { - "name": "Create Participant (existing key)", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"roles\":[],\n \"serviceEndpoints\":[],\n \"active\": true,\n \"participantId\": \"{{NEW_PARTICIPANT_ID}}\",\n \"did\": \"{{NEW_PARTICIPANT_ID}}\",\n \"key\":{\n \"keyId\": \"key-1\",\n \"privateKeyAlias\": \"{{NEW_PARTICIPANT_ID}}-alias\",\n \"publicKeyPem\":\"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5r\\noYnkAXuqCYfNK3ex+hMWFuiXGUxHlzShAehR6wvwzV23bbC0tcFcVgW//A==\\n-----END PUBLIC KEY-----\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "" - ] - } - }, - "response": [] - }, - { - "name": "Update Roles", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "PUT", - "header": [], - "body": { - "mode": "raw", - "raw": "[\n \"role1\", \"role2\", \"admin\"\n]", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/roles", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "roles" - ] - } - }, - "response": [] - }, - { - "name": "Regenerate Token", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/api/admin/v1alpha/attestations?participantId=", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "attestations" - ], - "query": [ - { - "key": "participantId", - "value": "" - } - ] - } - }, - "response": [] - }, - { - "name": "Activate Participant", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"roles\":[],\n \"serviceEndpoints\":[],\n \"isActive\": true,\n \"participantId\": \"foobar\",\n \"did\": \"did:web:foobar\",\n \"key\":{\n \"keyId\": \"key1\",\n \"privateKeyAlias\": \"foobar-alias\",\n \"keyGeneratorParams\":{\n \"algorithm\": \"EC\",\n \"curve\": \"secp256r1\"\n }\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/state?isActive=true", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "state" - ], - "query": [ - { - "key": "isActive", - "value": "true" - } - ] - } - }, - "response": [] - }, - { - "name": "Deactivate Participant", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"roles\":[],\n \"serviceEndpoints\":[],\n \"isActive\": true,\n \"participantId\": \"foobar\",\n \"did\": \"did:web:foobar\",\n \"key\":{\n \"keyId\": \"key1\",\n \"privateKeyAlias\": \"foobar-alias\",\n \"keyGeneratorParams\":{\n \"algorithm\": \"EC\",\n \"curve\": \"secp256r1\"\n }\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/state?isActive=false", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "state" - ], - "query": [ - { - "key": "isActive", - "value": "false" - } - ] - } - }, - "response": [] - }, - { - "name": "Delete Participant", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"roles\":[],\n \"serviceEndpoints\":[],\n \"isActive\": true,\n \"participantId\": \"foobar\",\n \"did\": \"did:web:foobar\",\n \"key\":{\n \"keyId\": \"key1\",\n \"privateKeyAlias\": \"foobar-alias\",\n \"keyGeneratorParams\":{\n \"algorithm\": \"EC\",\n \"curve\": \"secp256r1\"\n }\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "KeyPair Resources Mgmt API", - "item": [ - { - "name": "Get KeyPair for Participant", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/BPN0000001/keypairs", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "BPN0000001", - "keypairs" - ] - } - }, - "response": [] - }, - { - "name": "Get all KeyPairs", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/keypairs", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "keypairs" - ] - } - }, - "response": [] - }, - { - "name": "Add KeyPair", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204, 409])", - "})" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "PUT", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"keyId\": \"key6\",\n \"privateKeyAlias\": \"new-foobar-alias5\",\n \"keyGeneratorParams\": {\n \"algorithm\": \"EdDSA\",\n \"curve\": \"Ed25519\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/keypairs", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "keypairs" - ] - } - }, - "response": [] - }, - { - "name": "Rotate key", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"keyId\": \"key2\",\n \"privateKeyAlias\": \"new-foobar-alias\",\n \"keyGeneratorParams\": {\n \"algorithm\": \"EC\",\n \"curve\": \"secp256r1\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/keypairs/key1/rotate", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "keypairs", - "key1", - "rotate" - ] - } - }, - "response": [] - }, - { - "name": "Revoke key", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/keypairs/key2/revoke", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "keypairs", - "key2", - "revoke" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "DID Document Mgmt API", - "item": [ - { - "name": "Query DIDs", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/BPN0000001/dids/query", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "BPN0000001", - "dids", - "query" - ] - } - }, - "response": [] - }, - { - "name": "Get All DID Documents", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/dids", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "dids" - ] - } - }, - "response": [] - }, - { - "name": "Publish DID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"did:web:BPN0000001\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/dids/publish", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "dids", - "publish" - ] - } - }, - "response": [] - }, - { - "name": "Add endpoint", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"id\": \"some-other-id\",\n \"type\": \"CredentialService\",\n \"serviceEndpoint\": \"https://foobar.myconnector.com\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/dids/{{DID}}/endpoints", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "dids", - "{{DID}}", - "endpoints" - ] - } - }, - "response": [] - }, - { - "name": "Un-Publish DID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"did:web:consumer-identityhub%3A7083:connector1\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/dids/unpublish", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "dids", - "unpublish" - ] - } - }, - "response": [] - }, - { - "name": "Delete DID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"did:web:consumer-identityhub%3A7083:connector1\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/dids", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "dids" - ] - } - }, - "response": [] - }, - { - "name": "Get DID Document state", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"did:web:BPN0000001\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/dids/state", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "dids", - "state" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "pm.test(\"Status is OK\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204])", - "})" - ] - } - } - ] - }, - { - "name": "VerifiableCredential Mgmt API", - "item": [ - { - "name": "Get Credential By ID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status is OK\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204])", - "})" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID}}/credentials/CREDENTIAL-ID", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID}}", - "credentials", - "CREDENTIAL-ID" - ] - } - }, - "response": [] - }, - { - "name": "Get All Credentials", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status is OK\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204])", - "})" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/credentials", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "credentials" - ] - } - }, - "response": [] - }, - { - "name": "Query Credentials by Type", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status is OK\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 204])", - "})" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgz/credentials?type=FoobarCredential", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgz", - "credentials" - ], - "query": [ - { - "key": "type", - "value": "FoobarCredential" - } - ] - } - }, - "response": [] - }, - { - "name": "Make Credential Request", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "if(pm.response.code < 300 && pm.response.code >= 200){", - " if(pm.response.text().length > 0){", - " const requestId = pm.response.text()", - " pm.environment.set(\"REQUEST_ID\", requestId);", - " }", - "}" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"issuerDid\": \"{{ISSUER_DID}}\",\n \"holderPid\": \"credential-request-1\",\n \"credentials\": [{\n \"format\": \"VC1_0_JWT\",\n \"credentialType\": \"FoobarCredential\"\n }]\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID_BASE64}}/credentials/request", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID_BASE64}}", - "credentials", - "request" - ] - } - }, - "response": [] - }, - { - "name": "Get Credential Reqeusts", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{CS_URL}}/api/identity/v1alpha/participants/{{PARTICIPANT_ID_BASE64}}/credentials/request/{{REQUEST_ID}}", - "host": [ - "{{CS_URL}}" - ], - "path": [ - "api", - "identity", - "v1alpha", - "participants", - "{{PARTICIPANT_ID_BASE64}}", - "credentials", - "request", - "{{REQUEST_ID}}" - ] - } - }, - "response": [] - } - ] - } - ], - "auth": { - "type": "apikey", - "apikey": [ - { - "key": "value", - "value": "{{IH_API_TOKEN}}", - "type": "string" - }, - { - "key": "key", - "value": "X-Api-Key", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 204, 409])", - "})" - ] - } - } - ] - }, - { - "name": "IssuerService", - "item": [ - { - "name": "Admin API", - "item": [ - { - "name": "Attestations", - "item": [ - { - "name": "create Attestation", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"database\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/attestations", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "attestations" - ] - }, - "description": "Creates an attestation definition in the runtime." - }, - "response": [ - { - "name": "The attestation definition was added successfully.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations" - ] - } - }, - "status": "Created", - "code": 201, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The participant was not found.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations" - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "Can't add the participant, because a object with the same ID already exists", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"\",\n \"configuration\": {\n \"commodof4\": {},\n \"laborisb27\": {}\n },\n \"id\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations" - ] - } - }, - "status": "Conflict", - "code": 409, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "query Attestations", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/attestations/query", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "attestations", - "query" - ] - }, - "description": "Query attestation definitions" - }, - "response": [ - { - "name": "A list of attestation metadata.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations", - "query" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"attestationType\": \"\",\n \"configuration\": {\n \"aliquip2\": {},\n \"pariatur_b3\": {},\n \"essebab\": {}\n },\n \"id\": \"\"\n },\n {\n \"attestationType\": \"\",\n \"configuration\": {\n \"sint_9f6\": {}\n },\n \"id\": \"\"\n }\n]" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations", - "query" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/attestations/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "attestations", - "query" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - } - ] - }, - { - "name": "CredentialDefinitions", - "item": [ - { - "name": "create Credential Definition", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\",\n \"formats\": [\"VC1_0_JWT\"]\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions" - ] - }, - "description": "Adds a new credential definition." - }, - "response": [ - { - "name": "The credential definition was created successfully.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Created", - "code": 201, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "Can't create the credential definition, because a object with the same ID already exists", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Conflict", - "code": 409, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "query Credential Definitions", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions/query", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions", - "query" - ] - }, - "description": "Gets all credential definitions for a certain query." - }, - "response": [ - { - "name": "A list of credentials definitions.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - "query" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_1_1\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"in_85a\": {},\n \"dolor310\": {},\n \"incididunt_b\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"eud_\": {},\n \"dolor777\": {},\n \"Utb\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n },\n {\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"laborum7\": {},\n \"voluptate726\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"amet_27c\": {},\n \"voluptate8\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n }\n]" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - "query" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - "query" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "get by ID", - "request": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Gets a credential definition by its ID." - }, - "response": [ - { - "name": "The credential definition was found.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential definition was not found.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "update Credential Definition", - "request": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions" - ] - }, - "description": "Updates credential definition." - }, - "response": [ - { - "name": "The credential definition was updated successfully.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "Can't update the credential definition because it was not found.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions" - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "delete Credential Definition By Id", - "request": { - "method": "DELETE", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Deletes a credential definition by its ID." - }, - "response": [ - { - "name": "The credential definition was deleted.", - "originalRequest": { - "method": "DELETE", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"credentialType\": \"\",\n \"dataModel\": \"V_2_0\",\n \"id\": \"\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"\",\n \"mappings\": [\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n },\n {\n \"input\": \"\",\n \"output\": \"\",\n \"required\": \"\"\n }\n ],\n \"rules\": [\n {\n \"configuration\": {\n \"addca\": {}\n },\n \"type\": \"\"\n },\n {\n \"configuration\": {\n \"incididunt_a1f\": {}\n },\n \"type\": \"\"\n }\n ],\n \"validity\": \"\"\n}" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "DELETE", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "DELETE", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential definition was not found.", - "originalRequest": { - "method": "DELETE", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentialdefinitions/:credentialDefinitionId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentialdefinitions", - ":credentialDefinitionId" - ], - "variable": [ - { - "key": "credentialDefinitionId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - } - ] - }, - { - "name": "Credentials", - "item": [ - { - "name": "query Credentials", - "protocolProfileBehavior": { - "disabledSystemHeaders": {} - }, - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/query", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - "query" - ] - }, - "description": "Query credentials, possibly across multiple participants." - }, - "response": [ - { - "name": "A list of verifiable credential metadata. Note that these are not actual VerifiableCredentials.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - "query" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"credential\": {\n \"credentialSchema\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialStatus\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialSubject\": [\n {\n \"id\": \"\"\n },\n {\n \"id\": \"\"\n }\n ],\n \"dataModelVersion\": \"V_2_0\",\n \"description\": \"\",\n \"expirationDate\": \"\",\n \"id\": \"\",\n \"issuanceDate\": \"\",\n \"issuer\": {\n \"additionalProperties\": {\n \"ex_991\": {}\n },\n \"id\": \"\"\n },\n \"name\": \"\",\n \"type\": [\n \"\",\n \"\"\n ]\n },\n \"format\": \"JSON_LD\"\n },\n {\n \"credential\": {\n \"credentialSchema\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialStatus\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialSubject\": [\n {\n \"id\": \"\"\n },\n {\n \"id\": \"\"\n }\n ],\n \"dataModelVersion\": \"V_1_1\",\n \"description\": \"\",\n \"expirationDate\": \"\",\n \"id\": \"\",\n \"issuanceDate\": \"\",\n \"issuer\": {\n \"additionalProperties\": {\n \"enima7\": {},\n \"ad_a5\": {},\n \"ipsum_65\": {}\n },\n \"id\": \"\"\n },\n \"name\": \"\",\n \"type\": [\n \"\",\n \"\"\n ]\n },\n \"format\": \"JWT\"\n }\n]" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - "query" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - "query" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "resume Credential", - "request": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/:credentialId/resume", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - ":credentialId", - "resume" - ], - "variable": [ - { - "key": "credentialId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Resumes a credential with the given ID for the given participant. Resumed credentials will be removed from the Revocation List." - }, - "response": [ - { - "name": "The credential was resumed successfully. Check the Revocation List credential to confirm.", - "originalRequest": { - "method": "POST", - "header": [], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/resume", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "resume" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "No Content", - "code": 204, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/resume", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "resume" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/resume", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "resume" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential or the participant was not found.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/resume", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "resume" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "revoke Credential", - "request": { - "method": "POST", - "header": [], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/:credentialId/revoke", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - ":credentialId", - "revoke" - ], - "variable": [ - { - "key": "credentialId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Revokes a credential with the given ID for the given participant. Revoked credentials will be added to the Revocation List" - }, - "response": [ - { - "name": "The credential was revoked successfully. Check the Revocation List credential to confirm.", - "originalRequest": { - "method": "POST", - "header": [], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/revoke", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "revoke" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "No Content", - "code": 204, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/revoke", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "revoke" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/revoke", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "revoke" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential or the participant was not found.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/revoke", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "revoke" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "check Credential Status", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/:credentialId/status", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - ":credentialId", - "status" - ], - "variable": [ - { - "key": "credentialId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Checks the revocation status of a credential with the given ID for the given participant." - }, - "response": [ - { - "name": "The credential status.", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/status", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "status" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/status", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "status" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/status", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "status" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential or the participant was not found.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/status", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "status" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "suspend Credential", - "request": { - "method": "POST", - "header": [], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/:credentialId/suspend", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - ":credentialId", - "suspend" - ], - "variable": [ - { - "key": "credentialId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Suspends a credential with the given ID for the given participant. Suspended credentials will be added to the Revocation List. Suspension is reversible." - }, - "response": [ - { - "name": "The credential was suspended successfully. Check the Revocation List credential to confirm.", - "originalRequest": { - "method": "POST", - "header": [], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/suspend", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "suspend" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "No Content", - "code": 204, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/suspend", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "suspend" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/suspend", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "suspend" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The credential or the participant was not found.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:credentialId/suspend", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":credentialId", - "suspend" - ], - "variable": [ - { - "key": "credentialId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "get Credentials", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentials/{{PARTICIPANT_ID}}", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentials", - "{{PARTICIPANT_ID}}" - ] - }, - "description": "Gets all credentials for a certain participant." - }, - "response": [ - { - "name": "A list of verifiable credential metadata. Note that these are not actual VerifiableCredentials.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"credential\": {\n \"credentialSchema\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialStatus\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialSubject\": [\n {\n \"id\": \"\"\n },\n {\n \"id\": \"\"\n }\n ],\n \"dataModelVersion\": \"V_2_0\",\n \"description\": \"\",\n \"expirationDate\": \"\",\n \"id\": \"\",\n \"issuanceDate\": \"\",\n \"issuer\": {\n \"additionalProperties\": {\n \"ex_991\": {}\n },\n \"id\": \"\"\n },\n \"name\": \"\",\n \"type\": [\n \"\",\n \"\"\n ]\n },\n \"format\": \"JSON_LD\"\n },\n {\n \"credential\": {\n \"credentialSchema\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialStatus\": [\n {\n \"id\": \"\",\n \"type\": \"\"\n },\n {\n \"id\": \"\",\n \"type\": \"\"\n }\n ],\n \"credentialSubject\": [\n {\n \"id\": \"\"\n },\n {\n \"id\": \"\"\n }\n ],\n \"dataModelVersion\": \"V_1_1\",\n \"description\": \"\",\n \"expirationDate\": \"\",\n \"id\": \"\",\n \"issuanceDate\": \"\",\n \"issuer\": {\n \"additionalProperties\": {\n \"enima7\": {},\n \"ad_a5\": {},\n \"ipsum_65\": {}\n },\n \"id\": \"\"\n },\n \"name\": \"\",\n \"type\": [\n \"\",\n \"\"\n ]\n },\n \"format\": \"JWT\"\n }\n]" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The participant was not found.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/credentials/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "credentials", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - } - ] - }, - { - "name": "Participants", - "item": [ - { - "name": "update Participant", - "request": { - "method": "PUT", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Updates participant data." - }, - "response": [ - { - "name": "The participant was updated successfully.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "Can't update the participant because it was not found.", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "Create Participant", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"did:web:test\",\n \"participantId\": \"did:web:test\",\n \"name\": \"Test Participant\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Adds a new participant." - }, - "response": [ - { - "name": "The participant was added successfully.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Created", - "code": 201, - "_postman_previewlanguage": "text", - "header": [], - "cookie": [], - "body": "" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "Can't add the participant, because a object with the same ID already exists", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants" - ] - } - }, - "status": "Conflict", - "code": 409, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "query Participants", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders/query", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders", - "query" - ] - }, - "description": "Gets all participants for a certain query." - }, - "response": [ - { - "name": "A list of participant metadata.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - "query" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n },\n {\n \"did\": \"\",\n \"participantId\": \"\",\n \"name\": \"\"\n }\n]" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - "query" - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - "query" - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The participant was not found.", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Accept", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"filterExpression\": [\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n },\n {\n \"operandLeft\": {},\n \"operandRight\": {},\n \"operator\": \"\"\n }\n ],\n \"limit\": \"\",\n \"offset\": \"\",\n \"sortField\": \"\",\n \"sortOrder\": \"DESC\"\n}", - "options": { - "raw": { - "headerFamily": "json", - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/query", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - "query" - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - }, - { - "name": "get Participant By Id", - "request": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders/:participantId", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders", - ":participantId" - ], - "variable": [ - { - "key": "participantId", - "value": "", - "description": "(Required) " - } - ] - }, - "description": "Gets metadata for a certain participant." - }, - "response": [ - { - "name": "A list of verifiable credential metadata. Note that these are not actual VerifiableCredentials.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "{\n \"attestations\": [\n \"\",\n \"\"\n ],\n \"did\": \"\",\n \"participantId\": \"\",\n \"participantName\": \"\"\n}" - }, - { - "name": "Request body was malformed, or the request could not be processed", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Bad Request", - "code": 400, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The request could not be completed, because either the authentication was missing or was not valid.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Unauthorized", - "code": 401, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - }, - { - "name": "The participant was not found.", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "url": { - "raw": "{{baseUrl}}/v1alpha/participants/:participantId", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1alpha", - "participants", - ":participantId" - ], - "variable": [ - { - "key": "participantId" - } - ] - } - }, - "status": "Not Found", - "code": 404, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "cookie": [], - "body": "[\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n },\n {\n \"invalidValue\": {},\n \"message\": \"\",\n \"path\": \"\",\n \"type\": \"\"\n }\n]" - } - ] - } - ] - }, - { - "name": "IssuanceProcesses", - "item": [ - { - "name": "Query issuance processes", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/issuanceprocesses/query", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "issuanceprocesses", - "query" - ] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "Seed Issuer SQL", - "item": [ - { - "name": "Create consumer participant", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"{{CONSUMER_ID}}\",\n \"holderId\": \"{{CONSUMER_ID}}\",\n \"name\": \"{{CONSUMER_NAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/holders' \\\n-H 'Content-Type: application/json' \\\n-d '{ \"did\": \"did:web:localhost%3A7083\", \"participantId\": \"did:web:localhost%3A7083\", \"name\": \"Consumer Participant\"}'" - }, - "response": [] - }, - { - "name": "Create provider participant", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"{{PROVIDER_ID}}\",\n \"holderId\": \"{{PROVIDER_ID}}\",\n \"name\": \"{{PROVIDER_NAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/holders' \\\n-H 'Content-Type: application/json' \\\n-d '{ \"did\": \"did:web:localhost%3A7093\", \"participantId\": \"did:web:localhost%3A7093\", \"name\": \"Provider Participant\"}'" - }, - "response": [] - }, - { - "name": "Create attestation definitions", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"database\",\n \"configuration\": {\n \"tableName\": \"membership_attestations\",\n \"dataSourceName\": \"membership\",\n \"idColumn\": \"holder_id\"\n },\n \"id\": \"db-attestation-def-1\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/attestations", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "attestations" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/attestations' \\\n-H 'Content-Type: application/json' \\\n-d '{\n \"attestationType\": \"demo\",\n \"configuration\": {\n },\n \"id\": \"demo-attestation-def-1\"\n}'" - }, - "response": [] - }, - { - "name": "Create credential definitions", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"db-attestation-def-1\"\n ],\n \"credentialType\": \"FoobarCredential\",\n \"id\": \"demo-credential-def-2\",\n \"jsonSchema\": \"{}\",\n \"jsonSchemaUrl\": \"https://example.com/schema/demo-credential.json\",\n \"mappings\": [\n {\n \"input\": \"membership_type\",\n \"output\": \"credentialSubject.membershipType\",\n \"required\": \"true\"\n },\n {\n \"input\": \"membership_start_date\",\n \"output\": \"credentialSubject.membershipStartDate\",\n \"required\": true\n }\n ],\n \"rules\": [],\n \"format\": \"VC1_0_JWT\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/credentialdefinitions' \\\n-H 'Content-Type: application/json' \\\n-d '{\n \"attestations\": [\n \"demo-attestation-def-1\"\n ],\n \"credentialType\": \"DemoCredential\",\n \"dataModel\": \"V_1_1\",\n \"id\": \"demo-credential-def-1\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"https://example.com/schema/demo-credential.json\",\n \"mappings\": [\n {\n \"input\": \"name\",\n \"output\": \"credentialSubject.name\",\n \"required\": \"true\"\n }\n ],\n \"rules\": []\n }'" - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 204, 409])", - "})" - ] - } - } - ] - }, - { - "name": "Seed Issuer", - "item": [ - { - "name": "Create consumer participant", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"{{CONSUMER_ID}}\",\n \"holderId\": \"{{CONSUMER_ID}}\",\n \"name\": \"{{CONSUMER_NAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/holders' \\\n-H 'Content-Type: application/json' \\\n-d '{ \"did\": \"did:web:localhost%3A7083\", \"participantId\": \"did:web:localhost%3A7083\", \"name\": \"Consumer Participant\"}'" - }, - "response": [] - }, - { - "name": "Create provider participant", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"did\": \"{{PROVIDER_ID}}\",\n \"holderId\": \"{{PROVIDER_ID}}\",\n \"name\": \"{{PROVIDER_NAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/holders", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "holders" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/holders' \\\n-H 'Content-Type: application/json' \\\n-d '{ \"did\": \"did:web:localhost%3A7093\", \"participantId\": \"did:web:localhost%3A7093\", \"name\": \"Provider Participant\"}'" - }, - "response": [] - }, - { - "name": "Create attestation definitions", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestationType\": \"demo\",\n \"configuration\": {\n },\n \"id\": \"demo-attestation-def-1\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/attestations", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "attestations" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/attestations' \\\n-H 'Content-Type: application/json' \\\n-d '{\n \"attestationType\": \"demo\",\n \"configuration\": {\n },\n \"id\": \"demo-attestation-def-1\"\n}'" - }, - "response": [] - }, - { - "name": "Create credential definitions", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"attestations\": [\n \"demo-attestation-def-1\"\n ],\n \"credentialType\": \"DemoCredential\",\n \"id\": \"demo-credential-def-1\",\n \"jsonSchema\": \"{}\",\n \"jsonSchemaUrl\": \"https://example.com/schema/demo-credential.json\",\n \"mappings\": [\n {\n \"input\": \"participant.name\",\n \"output\": \"credentialSubject.participant_name\",\n \"required\": \"true\"\n }\n ],\n \"rules\": [],\n \"format\": \"VC1_0_JWT\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{ISSUER_ADMIN_URL}}/api/admin/v1alpha/participants/{{ISSUER_CONTEXT_ID}}/credentialdefinitions", - "host": [ - "{{ISSUER_ADMIN_URL}}" - ], - "path": [ - "api", - "admin", - "v1alpha", - "participants", - "{{ISSUER_CONTEXT_ID}}", - "credentialdefinitions" - ] - }, - "description": "Generated from cURL: curl -sL -X POST 'http://localhost:10013/api/admin/v1alpha/credentialdefinitions' \\\n-H 'Content-Type: application/json' \\\n-d '{\n \"attestations\": [\n \"demo-attestation-def-1\"\n ],\n \"credentialType\": \"DemoCredential\",\n \"dataModel\": \"V_1_1\",\n \"id\": \"demo-credential-def-1\",\n \"jsonSchema\": \"\",\n \"jsonSchemaUrl\": \"https://example.com/schema/demo-credential.json\",\n \"mappings\": [\n {\n \"input\": \"name\",\n \"output\": \"credentialSubject.name\",\n \"required\": \"true\"\n }\n ],\n \"rules\": []\n }'" - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "pm.test(\"Status is OK or conflict\", function() {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 204, 409])", - "})" - ] - } - } - ] - } - ], - "auth": { - "type": "apikey", - "apikey": [ - { - "key": "value", - "value": "{{ISSUER_ADMIN_API_TOKEN}}", - "type": "string" - }, - { - "key": "key", - "value": "x-api-key", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ] - } - ], - "auth": { - "type": "apikey", - "apikey": [ - { - "key": "value", - "value": "password", - "type": "string" - }, - { - "key": "key", - "value": "X-Api-Key", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "if(pm.request.method == \"POST\" || pm.request.method == \"PUT\"){", - " pm.request.headers.add(\"Content-Type: application/json\");", - "}" - ] - } - }, - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ], - "variable": [ - { - "key": "HOST", - "value": "http://localhost:8081", - "type": "string" - }, - { - "key": "PROVIDER_DSP", - "value": "http://localhost:8092", - "type": "string" - }, - { - "key": "PROVIDER_ID", - "value": "did:web:localhost%3A7093", - "type": "string" - }, - { - "key": "CS_URL", - "value": "http://localhost:8181", - "type": "string" - }, - { - "key": "ISSUER_ADMIN_URL", - "value": "http://localhost:10013", - "type": "string" - }, - { - "key": "IH_API_TOKEN", - "value": "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=", - "type": "string" - }, - { - "key": "ISSUER_ADMIN_API_TOKEN", - "value": "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=", - "type": "string" - }, - { - "key": "PARTICIPANT_ID", - "value": "super-user" - }, - { - "key": "DID", - "value": "did:web:super-user" - }, - { - "key": "NEW_PARTICIPANT_ID", - "value": "did:web:localhost%3A7083", - "type": "string" - }, - { - "key": "CATALOG_URL", - "value": "http://localhost:8084", - "type": "string" - }, - { - "key": "TED_DSP_URL", - "value": "", - "type": "string" - }, - { - "key": "ISSUER_CONTEXT_ID", - "value": "ZGlkOndlYjpsb2NhbGhvc3QlM0ExMDEwMA==", - "type": "string" - }, - { - "key": "ISSUER_DID", - "value": "did:web:localhost%3A10100", - "type": "string" - }, - { - "key": "PARTICIPANT_ID_BASE64", - "value": "ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgz", - "type": "string" - } - ] -} \ No newline at end of file diff --git a/deployment/postman/http-client.env.json b/deployment/postman/http-client.env.json deleted file mode 100644 index 0550d19b4..000000000 --- a/deployment/postman/http-client.env.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Local": { - "CS_URL": "http://localhost:7082", - "HOST": "http://localhost:8081", - "PARTICIPANT_ID": "super-user", - "CATALOG_URL": "http://localhost:8084", - "DID": "did:web:super-user" - } -} diff --git a/deployment/provider.tf b/deployment/provider.tf deleted file mode 100644 index 454fa76ff..000000000 --- a/deployment/provider.tf +++ /dev/null @@ -1,163 +0,0 @@ -# -# 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 -# - - -# This file deploys all the components needed for the provider side of the scenario, -# i.e. a catalog server ("bob"), two connectors ("ted" and "carol") as well as one identityhub and one vault - -# first provider connector "provider-qna" -module "provider-qna-connector" { - source = "./modules/connector" - humanReadableName = "provider-qna" - participantId = var.provider-did - database = { - user = "qna" - password = "provider-qna" - url = "jdbc:postgresql://${module.provider-postgres.database-url}/provider_qna" - } - namespace = kubernetes_namespace.ns.metadata.0.name - vault-url = "http://provider-vault:8200" - sts-token-url = "${module.provider-identityhub.sts-token-url}/token" - useSVE = var.useSVE -} - -# Second provider connector "provider-manufacturing" -module "provider-manufacturing-connector" { - source = "./modules/connector" - humanReadableName = "provider-manufacturing" - participantId = var.provider-did - database = { - user = "manufacturing" - password = "provider-manufacturing" - url = "jdbc:postgresql://${module.provider-postgres.database-url}/provider_manufacturing" - } - namespace = kubernetes_namespace.ns.metadata.0.name - vault-url = "http://provider-vault:8200" - sts-token-url = "${module.provider-identityhub.sts-token-url}/token" - useSVE = var.useSVE -} - -module "provider-identityhub" { - depends_on = [module.provider-vault] - source = "./modules/identity-hub" - credentials-dir = dirname("./assets/credentials/k8s/provider/") - humanReadableName = "provider-identityhub" - # must be named "provider-identityhub" until we regenerate DIDs and credentials - participantId = var.provider-did - vault-url = "http://provider-vault:8200" - service-name = "provider" - namespace = kubernetes_namespace.ns.metadata.0.name - - database = { - user = "identity" - password = "identity" - url = "jdbc:postgresql://${module.provider-postgres.database-url}/identity" - } - useSVE = var.useSVE -} - -# Catalog server runtime -module "provider-catalog-server" { - source = "./modules/catalog-server" - humanReadableName = "provider-catalog-server" - participantId = var.provider-did - namespace = kubernetes_namespace.ns.metadata.0.name - vault-url = "http://provider-vault:8200" - sts-token-url = "${module.provider-identityhub.sts-token-url}/token" - - database = { - user = "catalog_server" - password = "catalog_server" - url = "jdbc:postgresql://${module.provider-postgres.database-url}/catalog_server" - } - useSVE = var.useSVE -} - -module "provider-vault" { - source = "./modules/vault" - humanReadableName = "provider-vault" - namespace = kubernetes_namespace.ns.metadata.0.name -} - -# Postgres database for the consumer -module "provider-postgres" { - depends_on = [kubernetes_config_map.postgres-initdb-config-cs] - source = "./modules/postgres" - instance-name = "provider" - init-sql-configs = [ - kubernetes_config_map.postgres-initdb-config-cs.metadata[0].name, - kubernetes_config_map.postgres-initdb-config-pqna.metadata[0].name, - kubernetes_config_map.postgres-initdb-config-pm.metadata[0].name, - kubernetes_config_map.postgres-initdb-config-ih.metadata[0].name, - ] - namespace = kubernetes_namespace.ns.metadata.0.name -} - -resource "kubernetes_config_map" "postgres-initdb-config-cs" { - metadata { - name = "cs-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "cs-initdb-config.sql" = <<-EOT - CREATE USER catalog_server WITH ENCRYPTED PASSWORD 'catalog_server' SUPERUSER; - CREATE DATABASE catalog_server; - \c catalog_server - - EOT - } -} - -resource "kubernetes_config_map" "postgres-initdb-config-pqna" { - metadata { - name = "provider-qna-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "provider-qna-initdb-config.sql" = <<-EOT - CREATE USER qna WITH ENCRYPTED PASSWORD 'provider-qna' SUPERUSER; - CREATE DATABASE provider_qna; - \c provider_qna - - EOT - } -} - -resource "kubernetes_config_map" "postgres-initdb-config-pm" { - metadata { - name = "provider-manufacturing-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "provider-manufacturing-initdb-config.sql" = <<-EOT - CREATE USER manufacturing WITH ENCRYPTED PASSWORD 'provider-manufacturing' SUPERUSER; - CREATE DATABASE provider_manufacturing; - \c provider_manufacturing - - EOT - } -} - -resource "kubernetes_config_map" "postgres-initdb-config-ih" { - metadata { - name = "ih-initdb-config" - namespace = kubernetes_namespace.ns.metadata.0.name - } - data = { - "ih-initdb-config.sql" = <<-EOT - CREATE USER identity WITH ENCRYPTED PASSWORD 'identity' SUPERUSER; - CREATE DATABASE identity; - \c identity - EOT - } -} \ No newline at end of file diff --git a/deployment/variables.tf b/deployment/variables.tf deleted file mode 100644 index 8b636a5ed..000000000 --- a/deployment/variables.tf +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -variable "consumer-did" { - default = "did:web:consumer-identityhub%3A7083:consumer" -} - -variable "provider-did" { - default = "did:web:provider-identityhub%3A7083:provider" -} - -variable "useSVE" { - type = bool - description = "If true, the -XX:UseSVE=0 switch (Scalable Vector Extensions) will be added to the JAVA_TOOL_OPTIONS. Can help on macOs on Apple Silicon processors" - default = false -} \ No newline at end of file diff --git a/extensions/catalog-node-resolver/build.gradle.kts b/extensions/catalog-node-resolver/build.gradle.kts deleted file mode 100644 index 5d2be6faa..000000000 --- a/extensions/catalog-node-resolver/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -/* -* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -* -* 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: -* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - Initial API and Implementation -* -*/ - -plugins { - `java-library` -} - -dependencies { - implementation(libs.edc.spi.identity.did) - implementation(libs.edc.fc.spi.crawler) - runtimeOnly(libs.edc.fc.core) - // todo: use 2025 once it is used everywhere - // runtimeOnly(libs.edc.fc.core2025) - runtimeOnly(libs.edc.fc.core08) - runtimeOnly(libs.edc.fc.api) -} diff --git a/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/ParticipantsResolverExtension.java b/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/ParticipantsResolverExtension.java deleted file mode 100644 index c31ec3918..000000000 --- a/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/ParticipantsResolverExtension.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.demo.participants; - -import org.eclipse.edc.crawler.spi.TargetNodeDirectory; -import org.eclipse.edc.crawler.spi.TargetNodeFilter; -import org.eclipse.edc.demo.participants.resolver.LazyLoadNodeDirectory; -import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; - -import java.io.File; - -import static org.eclipse.edc.demo.participants.ParticipantsResolverExtension.NAME; - -@Extension(value = NAME) -public class ParticipantsResolverExtension implements ServiceExtension { - public static final String NAME = "MVD Participant Resolver Extension"; - - public static final String PARTICIPANT_LIST_FILE_PATH = "edc.mvd.participants.list.file"; - - @Inject - private TypeManager typeManager; - - @Inject - private DidResolverRegistry didResolverRegistry; - - private File participantListFile; - private Monitor monitor; - private TargetNodeDirectory nodeDirectory; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - var participantsPath = context.getConfig().getString(PARTICIPANT_LIST_FILE_PATH); - monitor = context.getMonitor().withPrefix("DEMO"); - - participantListFile = new File(participantsPath).getAbsoluteFile(); - if (!participantListFile.exists()) { - monitor.warning("Path '%s' does not exist. It must be a resolvable path with read access. Will not add any VCs.".formatted(participantsPath)); - } - } - - @Provider - public TargetNodeDirectory createLazyTargetNodeDirectory() { - if (nodeDirectory == null) { - nodeDirectory = new LazyLoadNodeDirectory(typeManager.getMapper(), participantListFile, didResolverRegistry, monitor); - } - return nodeDirectory; - } - - @Provider - public TargetNodeFilter skipSelfNodeFilter(ServiceExtensionContext context) { - return targetNode -> { - var predicateTest = !targetNode.id().equals(context.getParticipantId()); - if (!predicateTest) { - monitor.debug("Node filter: skipping node '%s' for participant '%s'".formatted(targetNode.id(), context.getParticipantId())); - } - return predicateTest; - }; - } - - -} diff --git a/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/resolver/LazyLoadNodeDirectory.java b/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/resolver/LazyLoadNodeDirectory.java deleted file mode 100644 index 2330467c6..000000000 --- a/extensions/catalog-node-resolver/src/main/java/org/eclipse/edc/demo/participants/resolver/LazyLoadNodeDirectory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.demo.participants.resolver; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.eclipse.edc.crawler.spi.TargetNode; -import org.eclipse.edc.crawler.spi.TargetNodeDirectory; -import org.eclipse.edc.iam.did.spi.document.Service; -import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.monitor.Monitor; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * {@link TargetNodeDirectory} that is initialized with a file, that contains participant DIDs. On the first getAll() request - * the DIDs are resolved and converted into {@link TargetNode} objects. From then on, they are held in memory and cached. - *

- * DIDs must contain a {@link org.eclipse.edc.iam.did.spi.document.Service} where the {@link Service#getType()} equals {@code ProtocolEndpoint} - */ -public class LazyLoadNodeDirectory implements TargetNodeDirectory { - private static final TypeReference> MAP_TYPE = new TypeReference<>() { - }; - private static final String PROTOCOL_ENDPOINT = "ProtocolEndpoint"; - - private final ObjectMapper mapper; - private final File participantListFile; - private final DidResolverRegistry didResolverRegistry; - private final Monitor monitor; - - public LazyLoadNodeDirectory(ObjectMapper mapper, File participantListFile, DidResolverRegistry didResolverRegistry, Monitor monitor) { - - this.mapper = mapper; - this.participantListFile = participantListFile; - this.didResolverRegistry = didResolverRegistry; - this.monitor = monitor; - } - - @Override - public List getAll() { - try { - var entries = mapper.readValue(participantListFile, MAP_TYPE); - - return entries.entrySet().stream() - .map(e -> createNode(e.getKey(), e.getValue())) - .filter(Objects::nonNull) - .toList(); - } catch (IOException e) { - throw new EdcException(e); - } - } - - @Override - public void insert(TargetNode targetNode) { - //noop - } - - @Override - public TargetNode remove(String s) { - return null; - } - - private TargetNode createNode(String name, String did) { - var didResult = didResolverRegistry.resolve(did); - if (didResult.failed()) { - monitor.warning(didResult.getFailureDetail()); - return null; - } - var document = didResult.getContent(); - var service = document.getService().stream().filter(s -> s.getType().equalsIgnoreCase(PROTOCOL_ENDPOINT)).findFirst(); - return service.map(s -> new TargetNode(name, did, s.getServiceEndpoint(), List.of("dataspace-protocol-http"))) - .orElse(null); - } -} diff --git a/extensions/catalog-node-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/catalog-node-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 9b6064c26..000000000 --- a/extensions/catalog-node-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,15 +0,0 @@ -# -# 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 -# -# - -org.eclipse.edc.demo.participants.ParticipantsResolverExtension \ No newline at end of file diff --git a/extensions/data-plane-public-api-v2/build.gradle.kts b/extensions/data-plane-public-api-v2/build.gradle.kts new file mode 100644 index 000000000..78db2ebea --- /dev/null +++ b/extensions/data-plane-public-api-v2/build.gradle.kts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 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 + * + */ + +plugins { + `java-library` + id(libs.plugins.swagger.get().pluginId) +} + +dependencies { + api(libs.edc.spi.http) + api(libs.edc.spi.web) + api(libs.edc.spi.dataplane) + implementation(libs.edc.lib.util) + implementation(libs.edc.lib.util.dataplane) + implementation(libs.jakarta.rsApi) + + testImplementation(libs.edc.lib.http) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(testFixtures(libs.edc.core.jersey)) + +} +edcBuild { + swagger { + apiGroup.set("public-api") + } +} + + diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java new file mode 100644 index 000000000..612e0256c --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api; + +import org.eclipse.edc.connector.dataplane.api.controller.DataPlanePublicApiV2Controller; +import org.eclipse.edc.connector.dataplane.spi.Endpoint; +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAuthorizationService; +import org.eclipse.edc.connector.dataplane.spi.iam.PublicEndpointGeneratorService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; +import org.eclipse.edc.runtime.metamodel.annotation.Configuration; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.runtime.metamodel.annotation.Settings; +import org.eclipse.edc.spi.system.ExecutorInstrumentation; +import org.eclipse.edc.spi.system.Hostname; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.edc.web.spi.configuration.PortMapping; +import org.eclipse.edc.web.spi.configuration.PortMappingRegistry; + +import java.util.concurrent.Executors; + +/** + * This extension provides generic endpoints which are open to public participants of the Dataspace to execute + * requests on the actual data source. + */ +@Extension(value = DataPlanePublicApiV2Extension.NAME) +public class DataPlanePublicApiV2Extension implements ServiceExtension { + public static final String NAME = "Data Plane Public API"; + + public static final String API_CONTEXT = "public"; + private static final int DEFAULT_PUBLIC_PORT = 8185; + private static final String DEFAULT_PUBLIC_PATH = "/api/public"; + private static final int DEFAULT_THREAD_POOL = 10; + @Setting(description = "Base url of the public API endpoint without the trailing slash. This should point to the public endpoint configured.", + required = false, + key = "edc.dataplane.api.public.baseurl", warnOnMissingConfig = true) + private String publicBaseUrl; + @Setting(description = "Optional base url of the response channel endpoint without the trailing slash. A common practice is to use /responseChannel", key = "edc.dataplane.api.public.response.baseurl", required = false) + private String publicApiResponseUrl; + @Configuration + private PublicApiConfiguration apiConfiguration; + @Inject + private PortMappingRegistry portMappingRegistry; + @Inject + private PipelineService pipelineService; + @Inject + private WebService webService; + @Inject + private ExecutorInstrumentation executorInstrumentation; + @Inject + private DataPlaneAuthorizationService authorizationService; + @Inject + private PublicEndpointGeneratorService generatorService; + @Inject + private Hostname hostname; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + context.getMonitor().warning("The `data-plane-public-api-v2` has been deprecated, please provide an" + + "alternative implementation for Http Proxy if needed"); + + var portMapping = new PortMapping(API_CONTEXT, apiConfiguration.port(), apiConfiguration.path()); + portMappingRegistry.register(portMapping); + var executorService = executorInstrumentation.instrument( + Executors.newFixedThreadPool(DEFAULT_THREAD_POOL), + "Data plane proxy transfers" + ); + + if (publicBaseUrl == null) { + publicBaseUrl = "http://%s:%d%s".formatted(hostname.get(), portMapping.port(), portMapping.path()); + context.getMonitor().warning("The public API endpoint was not explicitly configured, the default '%s' will be used.".formatted(publicBaseUrl)); + } + var endpoint = Endpoint.url(publicBaseUrl); + generatorService.addGeneratorFunction("HttpData", dataAddress -> endpoint); + + if (publicApiResponseUrl != null) { + generatorService.addResponseGeneratorFunction("HttpData", () -> Endpoint.url(publicApiResponseUrl)); + } + + var publicApiController = new DataPlanePublicApiV2Controller(pipelineService, executorService, authorizationService); + webService.registerResource(API_CONTEXT, publicApiController); + } + + @Settings + record PublicApiConfiguration( + @Setting(key = "web.http." + API_CONTEXT + ".port", description = "Port for " + API_CONTEXT + " api context", defaultValue = DEFAULT_PUBLIC_PORT + "") + int port, + @Setting(key = "web.http." + API_CONTEXT + ".path", description = "Path for " + API_CONTEXT + " api context", defaultValue = DEFAULT_PUBLIC_PATH) + String path + ) { + + } +} diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApi.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApi.java new file mode 100644 index 000000000..5bc605054 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApi.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import jakarta.ws.rs.container.ContainerRequestContext; + +import java.util.Map; + +/** + * Wrapper around {@link ContainerRequestContext} enabling mocking. + */ +public interface ContainerRequestContextApi { + + /** + * Get the request headers. Note that if more than one value is associated to a specific header, + * only the first one is retained. + * + * @return Headers map. + */ + Map headers(); + + /** + * Format query of the request as string, e.g. "hello=world\&foo=bar". + * + * @return Query param string. + */ + String queryParams(); + + /** + * Format the request body into a string. + * + * @return Request body. + */ + String body(); + + /** + * Get the media type from incoming request. + * + * @return Media type. + */ + String mediaType(); + + /** + * Return request path, e.g. "hello/world/foo/bar". + * + * @return Path string. + */ + String path(); + + /** + * Get http method from the incoming request, e.g. "GET", "POST"... + * + * @return Http method. + */ + String method(); +} diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApiImpl.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApiImpl.java new file mode 100644 index 000000000..6bcb5ba6d --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/ContainerRequestContextApiImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.spi.EdcException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * This class provides a set of API wrapping a {@link ContainerRequestContext}. + */ +public class ContainerRequestContextApiImpl implements ContainerRequestContextApi { + + private static final String QUERY_PARAM_SEPARATOR = "&"; + + private final ContainerRequestContext context; + + public ContainerRequestContextApiImpl(ContainerRequestContext context) { + this.context = context; + } + + @Override + public Map headers() { + return context.getHeaders().entrySet() + .stream() + .filter(entry -> !entry.getValue().isEmpty()) + .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get(0))); + } + + @Override + public String queryParams() { + return context.getUriInfo().getQueryParameters().entrySet() + .stream() + .flatMap(entry -> entry.getValue().stream().map(val -> new QueryParam(entry.getKey(), val))) + .map(QueryParam::toString) + .collect(Collectors.joining(QUERY_PARAM_SEPARATOR)); + } + + @Override + public String body() { + try (BufferedReader br = new BufferedReader(new InputStreamReader(context.getEntityStream()))) { + return br.lines().collect(Collectors.joining("\n")); + } catch (IOException e) { + throw new EdcException("Failed to read request body: " + e.getMessage()); + } + } + + @Override + public String mediaType() { + return Optional.ofNullable(context.getMediaType()) + .map(MediaType::toString) + .orElse(null); + } + + @Override + public String path() { + var pathInfo = context.getUriInfo().getPath(); + return pathInfo.startsWith("/") ? pathInfo.substring(1) : pathInfo; + } + + @Override + public String method() { + return context.getMethod(); + } + + private static final class QueryParam { + + private final String key; + private final String values; + private final boolean valid; + + private QueryParam(String key, String values) { + this.key = key; + this.values = values; + this.valid = key != null && values != null && !values.isEmpty(); + } + + public boolean isValid() { + return valid; + } + + @Override + public String toString() { + return valid ? key + "=" + values : ""; + } + } +} diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowRequestSupplier.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowRequestSupplier.java new file mode 100644 index 000000000..c3c1aa7b9 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowRequestSupplier.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; +import org.eclipse.edc.spi.types.domain.transfer.FlowType; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.function.BiFunction; + +import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.BODY; +import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.MEDIA_TYPE; +import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.METHOD; +import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.PATH; +import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.QUERY_PARAMS; + +public class DataFlowRequestSupplier implements BiFunction { + + /** + * Put all properties of the incoming request (method, request body, query params...) into a map. + */ + private static Map createProps(ContainerRequestContextApi contextApi) { + var props = new HashMap(); + props.put(METHOD, contextApi.method()); + props.put(QUERY_PARAMS, contextApi.queryParams()); + props.put(PATH, contextApi.path()); + Optional.ofNullable(contextApi.mediaType()) + .ifPresent(mediaType -> { + props.put(MEDIA_TYPE, mediaType); + props.put(BODY, contextApi.body()); + }); + return props; + } + + /** + * Create a {@link DataFlowStartMessage} based on incoming request and claims decoded from the access token. + * + * @param contextApi Api for accessing request properties. + * @param dataAddress Source data address. + * @return DataFlowRequest + */ + @Override + public DataFlowStartMessage apply(ContainerRequestContextApi contextApi, DataAddress dataAddress) { + var props = createProps(contextApi); + return DataFlowStartMessage.Builder.newInstance() + .processId(UUID.randomUUID().toString()) + .sourceDataAddress(dataAddress) + .flowType(FlowType.PULL) // if a request hits the public DP API, we can assume a PULL transfer + .destinationDataAddress(DataAddress.Builder.newInstance() + .type(AsyncStreamingDataSink.TYPE) + .build()) + .id(UUID.randomUUID().toString()) + .properties(props) + .build(); + } +} diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2.java new file mode 100644 index 000000000..aea4942e4 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.container.ContainerRequestContext; + +@OpenAPIDefinition +@Tag(name = "Data Plane public API", + description = "The public API of the Data Plane is a data proxy enabling a data consumer to actively query" + + "data from the provider data source (e.g. backend Rest API, internal database...) through its Data Plane" + + "instance. Thus the Data Plane is the only entry/output door for the data, which avoids the provider to expose" + + "directly its data externally." + + "The Data Plane public API being a proxy, it supports all verbs (i.e. GET, POST, PUT, PATCH, DELETE), which" + + "can then conveyed until the data source is required. This is especially useful when the actual data source" + + "is a Rest API itself." + + "In the same manner, any set of arbitrary query parameters, path parameters and request body are supported " + + "(in the limits fixed by the HTTP server) and can also conveyed to the actual data source.") +public interface DataPlanePublicApiV2 { + + @Operation(description = "Send `GET` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void get(ContainerRequestContext context, AsyncResponse response); + + @Operation(description = "Send `HEAD` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void head(ContainerRequestContext context, AsyncResponse response); + + @Operation(description = "Send `POST` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void post(ContainerRequestContext context, AsyncResponse response); + + @Operation(description = "Send `PUT` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void put(ContainerRequestContext context, AsyncResponse response); + + @Operation(description = "Send `DELETE` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void delete(ContainerRequestContext context, AsyncResponse response); + + @Operation(description = "Send `PATCH` data query to the Data Plane.", + responses = { + @ApiResponse(responseCode = "400", description = "Missing access token"), + @ApiResponse(responseCode = "403", description = "Access token is expired or invalid"), + @ApiResponse(responseCode = "500", description = "Failed to transfer data") + } + ) + void patch(ContainerRequestContext context, AsyncResponse response); +} diff --git a/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2Controller.java b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2Controller.java new file mode 100644 index 000000000..1502fe8a1 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2Controller.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HEAD; +import jakarta.ws.rs.PATCH; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.Suspended; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.StreamingOutput; +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAuthorizationService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; +import org.eclipse.edc.connector.dataplane.spi.response.TransferErrorResponse; +import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.MediaType.WILDCARD; +import static jakarta.ws.rs.core.Response.Status.FORBIDDEN; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static jakarta.ws.rs.core.Response.Status.UNAUTHORIZED; +import static jakarta.ws.rs.core.Response.status; + +@Path("{any:.*}") +@Produces(WILDCARD) +public class DataPlanePublicApiV2Controller implements DataPlanePublicApiV2 { + + private final PipelineService pipelineService; + private final DataFlowRequestSupplier requestSupplier; + private final ExecutorService executorService; + private final DataPlaneAuthorizationService authorizationService; + + public DataPlanePublicApiV2Controller(PipelineService pipelineService, + ExecutorService executorService, + DataPlaneAuthorizationService authorizationService) { + this.pipelineService = pipelineService; + this.authorizationService = authorizationService; + this.requestSupplier = new DataFlowRequestSupplier(); + this.executorService = executorService; + } + + private static Response error(Response.Status status, List errors) { + return status(status).type(APPLICATION_JSON).entity(new TransferErrorResponse(errors)).build(); + } + + @GET + @Override + public void get(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + @HEAD + @Override + public void head(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + /** + * Sends a {@link POST} request to the data source and returns data. + * + * @param requestContext Request context. + * @param response Data fetched from the data source. + */ + @POST + @Override + public void post(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + /** + * Sends a {@link PUT} request to the data source and returns data. + * + * @param requestContext Request context. + * @param response Data fetched from the data source. + */ + @PUT + @Override + public void put(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + /** + * Sends a {@link DELETE} request to the data source and returns data. + * + * @param requestContext Request context. + * @param response Data fetched from the data source. + */ + @DELETE + @Override + public void delete(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + /** + * Sends a {@link PATCH} request to the data source and returns data. + * + * @param requestContext Request context. + * @param response Data fetched from the data source. + */ + @PATCH + @Override + public void patch(@Context ContainerRequestContext requestContext, @Suspended AsyncResponse response) { + handle(requestContext, response); + } + + private void handle(ContainerRequestContext requestContext, AsyncResponse response) { + var contextApi = new ContainerRequestContextApiImpl(requestContext); + + var token = contextApi.headers().get(HttpHeaders.AUTHORIZATION); + if (token == null) { + response.resume(error(UNAUTHORIZED, List.of("Missing Authorization Header"))); + return; + } + + var sourceDataAddress = authorizationService.authorize(token, buildRequestData(requestContext)); + if (sourceDataAddress.failed()) { + response.resume(error(FORBIDDEN, sourceDataAddress.getFailureMessages())); + return; + } + + var startMessage = requestSupplier.apply(contextApi, sourceDataAddress.getContent()); + + processRequest(startMessage, response); + } + + private Map buildRequestData(ContainerRequestContext requestContext) { + var requestData = new HashMap(); + requestData.put("headers", requestContext.getHeaders()); + requestData.put("path", requestContext.getUriInfo()); + requestData.put("method", requestContext.getMethod()); + requestData.put("content-type", requestContext.getMediaType()); + return requestData; + } + + private void processRequest(DataFlowStartMessage dataFlowStartMessage, AsyncResponse response) { + + AsyncStreamingDataSink.AsyncResponseContext asyncResponseContext = callback -> { + StreamingOutput output = t -> callback.outputStreamConsumer().accept(t); + var resp = Response.ok(output).type(callback.mediaType()).build(); + return response.resume(resp); + }; + + var sink = new AsyncStreamingDataSink(asyncResponseContext, executorService); + + pipelineService.transfer(dataFlowStartMessage, sink) + .whenComplete((result, throwable) -> { + if (throwable == null) { + if (result.failed()) { + response.resume(error(INTERNAL_SERVER_ERROR, result.getFailureMessages())); + } + } else { + var error = "Unhandled exception occurred during data transfer: " + throwable.getMessage(); + response.resume(error(INTERNAL_SERVER_ERROR, List.of(error))); + } + }); + } + +} diff --git a/extensions/data-plane-public-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/data-plane-public-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..b9313e304 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1 @@ +org.eclipse.edc.connector.dataplane.api.DataplaneRegistrationExtension diff --git a/extensions/data-plane-public-api-v2/src/main/resources/public-api-version.json b/extensions/data-plane-public-api-v2/src/main/resources/public-api-version.json new file mode 100644 index 000000000..72890702c --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/main/resources/public-api-version.json @@ -0,0 +1,8 @@ +[ + { + "version": "2.0.1", + "urlPath": "/v2", + "lastUpdated": "2024-07-10T08:56:00Z", + "maturity": "stable" + } +] diff --git a/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowStartMessageSupplierTest.java b/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowStartMessageSupplierTest.java new file mode 100644 index 000000000..8961e2e42 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataFlowStartMessageSupplierTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 Amadeus + * + * 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: + * Amadeus - initial API and implementation + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import jakarta.ws.rs.HttpMethod; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema; +import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class DataFlowStartMessageSupplierTest { + + + private final DataFlowRequestSupplier supplier = new DataFlowRequestSupplier(); + + private static DataAddress createDataAddress() { + return DataAddress.Builder.newInstance().type("test-type").build(); + } + + @Test + void verifyMapping_noInputBody() { + var contextApi = mock(ContainerRequestContextApi.class); + var address = createDataAddress(); + + var method = HttpMethod.GET; + var queryParams = "test-query-param"; + var path = "test-path"; + + when(contextApi.method()).thenReturn(method); + when(contextApi.queryParams()).thenReturn(queryParams); + when(contextApi.path()).thenReturn(path); + + var request = supplier.apply(contextApi, address); + + assertThat(request.getId()).isNotBlank(); + assertThat(request.getDestinationDataAddress().getType()).isEqualTo(AsyncStreamingDataSink.TYPE); + assertThat(request.getSourceDataAddress().getType()).isEqualTo(address.getType()); + assertThat(request.getProperties()).containsExactlyInAnyOrderEntriesOf(Map.of( + DataFlowRequestSchema.PATH, path, + DataFlowRequestSchema.METHOD, method, + DataFlowRequestSchema.QUERY_PARAMS, queryParams + + )); + } + + @Test + void verifyMapping_withInputBody() { + var contextApi = mock(ContainerRequestContextApi.class); + var address = createDataAddress(); + + var method = HttpMethod.GET; + var queryParams = "test-query-param"; + var path = "test-path"; + var body = "Test request body"; + + when(contextApi.method()).thenReturn(method); + when(contextApi.queryParams()).thenReturn(queryParams); + when(contextApi.path()).thenReturn(path); + when(contextApi.mediaType()).thenReturn(MediaType.TEXT_PLAIN); + when(contextApi.body()).thenReturn(body); + + var request = supplier.apply(contextApi, address); + + assertThat(request.getId()).isNotBlank(); + assertThat(request.getDestinationDataAddress().getType()).isEqualTo(AsyncStreamingDataSink.TYPE); + assertThat(request.getSourceDataAddress().getType()).isEqualTo(address.getType()); + assertThat(request.getProperties()).containsExactlyInAnyOrderEntriesOf(Map.of( + DataFlowRequestSchema.PATH, path, + DataFlowRequestSchema.METHOD, method, + DataFlowRequestSchema.QUERY_PARAMS, queryParams, + DataFlowRequestSchema.BODY, body, + DataFlowRequestSchema.MEDIA_TYPE, MediaType.TEXT_PLAIN + )); + } +} diff --git a/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2ControllerTest.java b/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2ControllerTest.java new file mode 100644 index 000000000..05aba40c3 --- /dev/null +++ b/extensions/data-plane-public-api-v2/src/test/java/org/eclipse/edc/connector/dataplane/api/controller/DataPlanePublicApiV2ControllerTest.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2022 Amadeus + * + * 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: + * Amadeus - initial API and implementation + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - improvements + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import io.restassured.specification.RequestSpecification; +import jakarta.ws.rs.core.Response; +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAuthorizationService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSource; +import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.StreamFailure; +import org.eclipse.edc.connector.dataplane.spi.pipeline.StreamResult; +import org.eclipse.edc.connector.dataplane.spi.resolver.DataAddressResolver; +import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; +import org.eclipse.edc.junit.annotations.ApiTest; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; +import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.stream.Stream; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; +import static java.util.concurrent.CompletableFuture.completedFuture; +import static java.util.concurrent.CompletableFuture.failedFuture; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.isA; +import static org.hamcrest.CoreMatchers.not; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ApiTest +class DataPlanePublicApiV2ControllerTest extends RestControllerTestBase { + + private final PipelineService pipelineService = mock(); + private final DataAddressResolver dataAddressResolver = mock(); + private final DataPlaneAuthorizationService authorizationService = mock(); + + @BeforeEach + void setup() { + when(authorizationService.authorize(anyString(), anyMap())) + .thenReturn(Result.success(testDestAddress())); + } + + @Test + void should_returnBadRequest_if_missingAuthorizationHeader() { + baseRequest() + .post("/any") + .then() + .statusCode(Response.Status.UNAUTHORIZED.getStatusCode()) + .body("errors[0]", is("Missing Authorization Header")); + } + + @Test + void shouldNotReturn302_whenUrlWithoutTrailingSlash() { + baseRequest() + .post("") + .then() + .statusCode(not(302)); + } + + @Test + void should_returnForbidden_if_tokenValidationFails() { + var token = UUID.randomUUID().toString(); + when(authorizationService.authorize(anyString(), anyMap())).thenReturn(Result.failure("token is not valid")); + + baseRequest() + .header(AUTHORIZATION, token) + .post("/any") + .then() + .statusCode(Response.Status.FORBIDDEN.getStatusCode()) + .contentType(JSON) + .body("errors.size()", is(1)); + + verify(authorizationService).authorize(eq(token), anyMap()); + } + + @Test + void should_returnInternalServerError_if_transferFails() { + var token = UUID.randomUUID().toString(); + var errorMsg = UUID.randomUUID().toString(); + when(dataAddressResolver.resolve(any())).thenReturn(Result.success(testDestAddress())); + when(pipelineService.transfer(any(), any())) + .thenReturn(completedFuture(StreamResult.error(errorMsg))); + + baseRequest() + .header(AUTHORIZATION, token) + .when() + .post("/any") + .then() + .statusCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .contentType(JSON) + .body("errors[0]", is(errorMsg)); + } + + @Test + void should_returnListOfErrorsAsResponse_if_anythingFails() { + var token = UUID.randomUUID().toString(); + var firstErrorMsg = UUID.randomUUID().toString(); + var secondErrorMsg = UUID.randomUUID().toString(); + + when(dataAddressResolver.resolve(any())).thenReturn(Result.success(testDestAddress())); + when(pipelineService.transfer(any(), any())) + .thenReturn(completedFuture(StreamResult.failure(new StreamFailure(List.of(firstErrorMsg, secondErrorMsg), StreamFailure.Reason.GENERAL_ERROR)))); + + baseRequest() + .header(AUTHORIZATION, token) + .when() + .post("/any") + .then() + .statusCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .contentType(JSON) + .body("errors", isA(List.class)) + .body("errors[0]", is(firstErrorMsg)) + .body("errors[1]", is(secondErrorMsg)); + } + + @Test + void should_returnInternalServerError_if_transferThrows() { + var token = UUID.randomUUID().toString(); + var errorMsg = UUID.randomUUID().toString(); + when(dataAddressResolver.resolve(any())).thenReturn(Result.success(testDestAddress())); + when(pipelineService.transfer(any(DataFlowStartMessage.class), any())) + .thenReturn(failedFuture(new RuntimeException(errorMsg))); + + baseRequest() + .header(AUTHORIZATION, token) + .when() + .post("/any") + .then() + .statusCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .contentType(JSON) + .body("errors[0]", is("Unhandled exception occurred during data transfer: " + errorMsg)); + } + + @Test + void shouldStreamSourceToResponse() { + when(dataAddressResolver.resolve(any())).thenReturn(Result.success(testDestAddress())); + when(pipelineService.transfer(any(), any())).thenAnswer(i -> { + ((AsyncStreamingDataSink) i.getArgument(1)).transfer(new TestDataSource("application/something", "data")); + return CompletableFuture.completedFuture(StreamResult.success()); + }); + + var responseBody = baseRequest() + .header(AUTHORIZATION, UUID.randomUUID().toString()) + .when() + .post("/any?foo=bar") + .then() + .log().ifError() + .statusCode(Response.Status.OK.getStatusCode()) + .contentType("application/something") + .extract().body().asString(); + + assertThat(responseBody).isEqualTo("data"); + var requestCaptor = ArgumentCaptor.forClass(DataFlowStartMessage.class); + verify(pipelineService).transfer(requestCaptor.capture(), any()); + var request = requestCaptor.getValue(); + assertThat(request.getDestinationDataAddress().getType()).isEqualTo(AsyncStreamingDataSink.TYPE); + assertThat(request.getSourceDataAddress().getType()).isEqualTo("test"); + assertThat(request.getProperties()).containsEntry("method", "POST").containsEntry("pathSegments", "any").containsEntry("queryParams", "foo=bar"); + } + + @Override + protected Object controller() { + return new DataPlanePublicApiV2Controller(pipelineService, Executors.newSingleThreadExecutor(), authorizationService); + } + + private RequestSpecification baseRequest() { + return given() + .baseUri("http://localhost:" + port) + .when(); + } + + private DataAddress testDestAddress() { + return DataAddress.Builder.newInstance().type("test").build(); + } + + private record TestDataSource(String mediaType, String data) implements DataSource, DataSource.Part { + + @Override + public StreamResult> openPartStream() { + return StreamResult.success(Stream.of(this)); + } + + @Override + public String name() { + return "test"; + } + + @Override + public InputStream openStream() { + return new ByteArrayInputStream(data.getBytes()); + } + + } + +} diff --git a/extensions/data-plane-registration/build.gradle.kts b/extensions/data-plane-registration/build.gradle.kts new file mode 100644 index 000000000..f03369094 --- /dev/null +++ b/extensions/data-plane-registration/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 + * + */ + +plugins { + `java-library` + id(libs.plugins.swagger.get().pluginId) +} + +dependencies { + api(libs.edc.spi.http) + api(libs.edc.spi.web) + api(libs.edc.spi.dataplane) + implementation(libs.edc.spi.dataplane.selector) + implementation(libs.edc.lib.util) + implementation(libs.edc.lib.util.dataplane) + implementation(libs.jakarta.rsApi) + +} +edcBuild { + swagger { + apiGroup.set("public-api") + } +} + + diff --git a/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/DataplaneRegistrationExtension.java b/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/DataplaneRegistrationExtension.java new file mode 100644 index 000000000..c3c492a8c --- /dev/null +++ b/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/DataplaneRegistrationExtension.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api; + +import org.eclipse.edc.connector.dataplane.api.controller.DataplaneRegistrationApiController; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.edc.web.spi.configuration.ApiContext; + +/** + * This extension provides generic endpoints which are open to public participants of the Dataspace to execute + * requests on the actual data source. + */ +@Extension(value = DataplaneRegistrationExtension.NAME) +public class DataplaneRegistrationExtension implements ServiceExtension { + public static final String NAME = "Data Plane Registration API"; + + @Inject + private WebService webService; + @Inject + private DataPlaneSelectorService selectorService; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + webService.registerResource(ApiContext.MANAGEMENT, new DataplaneRegistrationApiController(selectorService)); + } +} diff --git a/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataplaneRegistrationApiController.java b/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataplaneRegistrationApiController.java new file mode 100644 index 000000000..641f73271 --- /dev/null +++ b/extensions/data-plane-registration/src/main/java/org/eclipse/edc/connector/dataplane/api/controller/DataplaneRegistrationApiController.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.connector.dataplane.api.controller; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; + +@Consumes(APPLICATION_JSON) +@Produces(APPLICATION_JSON) +@Path("/v4beta/dataplanes") +public class DataplaneRegistrationApiController { + + private final DataPlaneSelectorService dataPlaneSelectorService; + + public DataplaneRegistrationApiController(DataPlaneSelectorService dataPlaneSelectorService) { + this.dataPlaneSelectorService = dataPlaneSelectorService; + } + + @POST + public void registerDataplane(DataPlaneInstance instance) { + dataPlaneSelectorService.register(instance.toBuilder().build()) // ugly, but will initialize all internal objects e.g. clock + .orElseThrow(exceptionMapper(DataPlaneInstance.class)); + + } +} diff --git a/extensions/data-plane-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/data-plane-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..b9313e304 --- /dev/null +++ b/extensions/data-plane-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1 @@ +org.eclipse.edc.connector.dataplane.api.DataplaneRegistrationExtension diff --git a/extensions/dcp-impl/build.gradle.kts b/extensions/dcp-impl/build.gradle.kts deleted file mode 100644 index 87863004d..000000000 --- a/extensions/dcp-impl/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -/* -* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -* -* 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: -* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - Initial API and Implementation -* -*/ - -plugins { - `java-library` -} - -dependencies { - implementation(libs.edc.dcp.core) - implementation(libs.edc.spi.identity.trust) - implementation(libs.edc.spi.transform) - implementation(libs.edc.spi.catalog) - implementation(libs.edc.spi.identity.did) - implementation(libs.edc.lib.jws2020) - implementation(libs.edc.lib.transform) -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DataAccessCredentialScopeExtractor.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DataAccessCredentialScopeExtractor.java deleted file mode 100644 index 46b192f37..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DataAccessCredentialScopeExtractor.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.core; - -import org.eclipse.edc.iam.identitytrust.spi.scope.ScopeExtractor; -import org.eclipse.edc.policy.context.request.spi.RequestPolicyContext; -import org.eclipse.edc.policy.model.Operator; - -import java.util.Set; - -class DataAccessCredentialScopeExtractor implements ScopeExtractor { - public static final String DATA_PROCESSOR_CREDENTIAL_TYPE = "DataProcessorCredential"; - private static final String DATA_ACCESS_CONSTRAINT_PREFIX = "DataAccess."; - private static final String CREDENTIAL_TYPE_NAMESPACE = "org.eclipse.edc.vc.type"; - - @Override - public Set extractScopes(Object leftValue, Operator operator, Object rightValue, RequestPolicyContext context) { - Set scopes = Set.of(); - if (leftValue instanceof String leftOperand) { - if (leftOperand.startsWith(DATA_ACCESS_CONSTRAINT_PREFIX)) { - scopes = Set.of("%s:%s:read".formatted(CREDENTIAL_TYPE_NAMESPACE, DATA_PROCESSOR_CREDENTIAL_TYPE)); - } - } - return scopes; - } -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DcpPatchExtension.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DcpPatchExtension.java deleted file mode 100644 index 2f4d8f46a..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DcpPatchExtension.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.demo.dcp.core; - -import org.eclipse.edc.iam.identitytrust.spi.scope.ScopeExtractorRegistry; -import org.eclipse.edc.iam.identitytrust.spi.verification.SignatureSuiteRegistry; -import org.eclipse.edc.iam.verifiablecredentials.spi.VcConstants; -import org.eclipse.edc.iam.verifiablecredentials.spi.model.Issuer; -import org.eclipse.edc.iam.verifiablecredentials.spi.validation.TrustedIssuerRegistry; -import org.eclipse.edc.policy.context.request.spi.RequestCatalogPolicyContext; -import org.eclipse.edc.policy.context.request.spi.RequestContractNegotiationPolicyContext; -import org.eclipse.edc.policy.context.request.spi.RequestTransferProcessPolicyContext; -import org.eclipse.edc.policy.context.request.spi.RequestVersionPolicyContext; -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.security.signature.jws2020.Jws2020SignatureSuite; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; - -import java.util.Map; -import java.util.Set; - -import static org.eclipse.edc.iam.verifiablecredentials.spi.validation.TrustedIssuerRegistry.WILDCARD; -import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; - -public class DcpPatchExtension implements ServiceExtension { - @Inject - private TypeManager typeManager; - - @Inject - private PolicyEngine policyEngine; - - @Inject - private SignatureSuiteRegistry signatureSuiteRegistry; - - @Inject - private TrustedIssuerRegistry trustedIssuerRegistry; - - @Inject - private ScopeExtractorRegistry scopeExtractorRegistry; - @Inject - private TypeTransformerRegistry typeTransformerRegistry; - - @Override - public void initialize(ServiceExtensionContext context) { - - // register signature suite - var suite = new Jws2020SignatureSuite(typeManager.getMapper(JSON_LD)); - signatureSuiteRegistry.register(VcConstants.JWS_2020_SIGNATURE_SUITE, suite); - - // register dataspace issuer - trustedIssuerRegistry.register(new Issuer("did:web:dataspace-issuer", Map.of()), WILDCARD); - trustedIssuerRegistry.register(new Issuer("did:web:localhost%3A9876", Map.of()), WILDCARD); // for the standard credentials - trustedIssuerRegistry.register(new Issuer("did:web:localhost%3A10100", Map.of()), WILDCARD); // for the credential used to demo the issuance flow - - // register a default scope provider - var contextMappingFunction = new DefaultScopeMappingFunction(Set.of("org.eclipse.edc.vc.type:MembershipCredential:read")); - - policyEngine.registerPostValidator(RequestCatalogPolicyContext.class, contextMappingFunction::apply); - policyEngine.registerPostValidator(RequestContractNegotiationPolicyContext.class, contextMappingFunction::apply); - policyEngine.registerPostValidator(RequestTransferProcessPolicyContext.class, contextMappingFunction::apply); - policyEngine.registerPostValidator(RequestVersionPolicyContext.class, contextMappingFunction::apply); - - - //register scope extractor - scopeExtractorRegistry.registerScopeExtractor(new DataAccessCredentialScopeExtractor()); - - - typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(typeManager, JSON_LD)); - } -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DefaultScopeMappingFunction.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DefaultScopeMappingFunction.java deleted file mode 100644 index e580078f5..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/core/DefaultScopeMappingFunction.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.core; - -import org.eclipse.edc.policy.context.request.spi.RequestPolicyContext; -import org.eclipse.edc.policy.engine.spi.PolicyValidatorRule; -import org.eclipse.edc.policy.model.Policy; - -import java.util.HashSet; -import java.util.Set; - -public class DefaultScopeMappingFunction implements PolicyValidatorRule { - private final Set defaultScopes; - - public DefaultScopeMappingFunction(Set defaultScopes) { - this.defaultScopes = defaultScopes; - } - - @Override - public Boolean apply(Policy policy, RequestPolicyContext requestPolicyContext) { - var requestScopeBuilder = requestPolicyContext.requestScopeBuilder(); - var rq = requestScopeBuilder.build(); - var existingScope = rq.getScopes(); - var newScopes = new HashSet<>(defaultScopes); - newScopes.addAll(existingScope); - requestScopeBuilder.scopes(newScopes); - return true; - } -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/AbstractCredentialEvaluationFunction.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/AbstractCredentialEvaluationFunction.java deleted file mode 100644 index 3d6992a48..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/AbstractCredentialEvaluationFunction.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.demo.dcp.policy; - -import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; -import org.eclipse.edc.participant.spi.ParticipantAgent; -import org.eclipse.edc.spi.result.Result; - -import java.util.List; - -public class AbstractCredentialEvaluationFunction { - private static final String VC_CLAIM = "vc"; - protected static final String MVD_NAMESPACE = "https://w3id.org/mvd/credentials/"; - - protected Result> getCredentialList(ParticipantAgent agent) { - var vcListClaim = agent.getClaims().get(VC_CLAIM); - - if (vcListClaim == null) { - return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); - } - if (!(vcListClaim instanceof List)) { - return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, received %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); - } - var vcList = (List) vcListClaim; - if (vcList.isEmpty()) { - return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); - } - return Result.success(vcList); - } -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/DataAccessLevelFunction.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/DataAccessLevelFunction.java deleted file mode 100644 index 49ac49b3e..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/DataAccessLevelFunction.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.policy; - -import org.eclipse.edc.participant.spi.ParticipantAgentPolicyContext; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintRuleFunction; -import org.eclipse.edc.policy.model.Duty; -import org.eclipse.edc.policy.model.Operator; - -import java.util.Objects; - -public class DataAccessLevelFunction extends AbstractCredentialEvaluationFunction implements AtomicConstraintRuleFunction { - - private static final String DATAPROCESSOR_CRED_TYPE = "DataProcessorCredential"; - - private DataAccessLevelFunction() { - - } - - public static DataAccessLevelFunction create() { - return new DataAccessLevelFunction<>() { - }; - } - - @Override - public boolean evaluate(Operator operator, Object rightOperand, Duty duty, C policyContext) { - if (!operator.equals(Operator.EQ)) { - policyContext.reportProblem("Cannot evaluate operator %s, only %s is supported".formatted(operator, Operator.EQ)); - return false; - } - var pa = policyContext.participantAgent(); - if (pa == null) { - policyContext.reportProblem("ParticipantAgent not found on PolicyContext"); - return false; - } - - var credentialResult = getCredentialList(pa); - if (credentialResult.failed()) { - policyContext.reportProblem(credentialResult.getFailureDetail()); - return false; - } - - return credentialResult.getContent() - .stream() - .filter(vc -> vc.getType().stream().anyMatch(t -> t.endsWith(DATAPROCESSOR_CRED_TYPE))) - .flatMap(credential -> credential.getCredentialSubject().stream()) - .anyMatch(credentialSubject -> { - var version = credentialSubject.getClaim(MVD_NAMESPACE, "contractVersion"); - var level = credentialSubject.getClaim(MVD_NAMESPACE, "level"); - - return version != null && Objects.equals(level, rightOperand); - }); - - - } - -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/MembershipCredentialEvaluationFunction.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/MembershipCredentialEvaluationFunction.java deleted file mode 100644 index 4f9e51525..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/MembershipCredentialEvaluationFunction.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.policy; - -import org.eclipse.edc.participant.spi.ParticipantAgentPolicyContext; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintRuleFunction; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; - -import java.time.Instant; -import java.util.Map; - -public class MembershipCredentialEvaluationFunction extends AbstractCredentialEvaluationFunction implements AtomicConstraintRuleFunction { - public static final String MEMBERSHIP_CONSTRAINT_KEY = "MembershipCredential"; - - private static final String MEMBERSHIP_CLAIM = "membership"; - private static final String SINCE_CLAIM = "since"; - private static final String ACTIVE = "active"; - - private MembershipCredentialEvaluationFunction() { - } - - public static MembershipCredentialEvaluationFunction create() { - return new MembershipCredentialEvaluationFunction<>() { - }; - } - - @SuppressWarnings("unchecked") - @Override - public boolean evaluate(Operator operator, Object rightOperand, Permission permission, C policyContext) { - if (!operator.equals(Operator.EQ)) { - policyContext.reportProblem("Invalid operator '%s', only accepts '%s'".formatted(operator, Operator.EQ)); - return false; - } - if (!ACTIVE.equals(rightOperand)) { - policyContext.reportProblem("Right-operand must be equal to '%s', but was '%s'".formatted(ACTIVE, rightOperand)); - return false; - } - - var pa = policyContext.participantAgent(); - if (pa == null) { - policyContext.reportProblem("No ParticipantAgent found on context."); - return false; - } - var credentialResult = getCredentialList(pa); - if (credentialResult.failed()) { - policyContext.reportProblem(credentialResult.getFailureDetail()); - return false; - } - - return credentialResult.getContent() - .stream() - .filter(vc -> vc.getType().stream().anyMatch(t -> t.endsWith(MEMBERSHIP_CONSTRAINT_KEY))) - .flatMap(vc -> vc.getCredentialSubject().stream().filter(cs -> cs.getClaims().containsKey(MEMBERSHIP_CLAIM))) - .anyMatch(credential -> { - var membershipClaim = (Map) credential.getClaim(MVD_NAMESPACE, MEMBERSHIP_CLAIM); - var membershipStartDate = Instant.parse(membershipClaim.get(SINCE_CLAIM).toString()); - return membershipStartDate.isBefore(Instant.now()); - }); - } - -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyEvaluationExtension.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyEvaluationExtension.java deleted file mode 100644 index 01b761a17..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyEvaluationExtension.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.policy; - -import org.eclipse.edc.connector.controlplane.catalog.spi.policy.CatalogPolicyContext; -import org.eclipse.edc.connector.controlplane.contract.spi.policy.ContractNegotiationPolicyContext; -import org.eclipse.edc.connector.controlplane.contract.spi.policy.TransferProcessPolicyContext; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintRuleFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Duty; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - -import static org.eclipse.edc.demo.dcp.policy.MembershipCredentialEvaluationFunction.MEMBERSHIP_CONSTRAINT_KEY; -import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; - -public class PolicyEvaluationExtension implements ServiceExtension { - - @Inject - private PolicyEngine policyEngine; - - @Inject - private RuleBindingRegistry ruleBindingRegistry; - - @Override - public void initialize(ServiceExtensionContext context) { - - bindPermissionFunction(MembershipCredentialEvaluationFunction.create(), TransferProcessPolicyContext.class, TransferProcessPolicyContext.TRANSFER_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - bindPermissionFunction(MembershipCredentialEvaluationFunction.create(), ContractNegotiationPolicyContext.class, ContractNegotiationPolicyContext.NEGOTIATION_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - bindPermissionFunction(MembershipCredentialEvaluationFunction.create(), CatalogPolicyContext.class, CatalogPolicyContext.CATALOG_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - - registerDataAccessLevelFunction(); - - } - - private void registerDataAccessLevelFunction() { - var accessLevelKey = "DataAccess.level"; - - bindDutyFunction(DataAccessLevelFunction.create(), TransferProcessPolicyContext.class, TransferProcessPolicyContext.TRANSFER_SCOPE, accessLevelKey); - bindDutyFunction(DataAccessLevelFunction.create(), ContractNegotiationPolicyContext.class, ContractNegotiationPolicyContext.NEGOTIATION_SCOPE, accessLevelKey); - bindDutyFunction(DataAccessLevelFunction.create(), CatalogPolicyContext.class, CatalogPolicyContext.CATALOG_SCOPE, accessLevelKey); - } - - private void bindPermissionFunction(AtomicConstraintRuleFunction function, Class contextClass, String scope, String constraintType) { - ruleBindingRegistry.bind("use", scope); - ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope); - ruleBindingRegistry.bind(constraintType, scope); - - policyEngine.registerFunction(contextClass, Permission.class, constraintType, function); - } - - private void bindDutyFunction(AtomicConstraintRuleFunction function, Class contextClass, String scope, String constraintType) { - ruleBindingRegistry.bind("use", scope); - ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope); - ruleBindingRegistry.bind(constraintType, scope); - - policyEngine.registerFunction(contextClass, Duty.class, constraintType, function); - } -} diff --git a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyScopes.java b/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyScopes.java deleted file mode 100644 index 1ce4d171f..000000000 --- a/extensions/dcp-impl/src/main/java/org/eclipse/edc/demo/dcp/policy/PolicyScopes.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.demo.dcp.policy; - -/** - * Defines standard EDC policy scopes. - */ -public interface PolicyScopes { - String CATALOG_REQUEST_SCOPE = "request.catalog"; - String NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation"; - String TRANSFER_PROCESS_REQUEST_SCOPE = "request.transfer.process"; - - String CATALOG_SCOPE = "catalog"; - String NEGOTIATION_SCOPE = "contract.negotiation"; - String TRANSFER_PROCESS_SCOPE = "transfer.process"; -} diff --git a/extensions/dcp-impl/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/dcp-impl/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index b26ac18f9..000000000 --- a/extensions/dcp-impl/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,16 +0,0 @@ -# -# 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 -# -# - -org.eclipse.edc.demo.dcp.core.DcpPatchExtension -org.eclipse.edc.demo.dcp.policy.PolicyEvaluationExtension diff --git a/extensions/did-example-resolver/build.gradle.kts b/extensions/did-example-resolver/build.gradle.kts deleted file mode 100644 index 8b49fe622..000000000 --- a/extensions/did-example-resolver/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -* -* 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: -* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - Initial API and Implementation -* -*/ - -plugins { - `java-library` -} - -dependencies { - implementation(libs.edc.did.core) - implementation(libs.edc.ih.spi.did) -} diff --git a/extensions/did-example-resolver/src/main/java/org/eclipse/edc/iam/identitytrust/core/SecretsExtension.java b/extensions/did-example-resolver/src/main/java/org/eclipse/edc/iam/identitytrust/core/SecretsExtension.java deleted file mode 100644 index d55d3c1e9..000000000 --- a/extensions/did-example-resolver/src/main/java/org/eclipse/edc/iam/identitytrust/core/SecretsExtension.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * 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: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.edc.iam.identitytrust.core; - -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - - -public class SecretsExtension implements ServiceExtension { - // duplicated from DcpDefaultServicesExtension - private static final String STS_PRIVATE_KEY_ALIAS = "edc.iam.sts.privatekey.alias"; - private static final String STS_PUBLIC_KEY_ID = "edc.iam.sts.publickey.id"; - @Inject - private Vault vault; - - @Override - public void initialize(ServiceExtensionContext context) { - seedKeys(context); - } - - /** - * We need this, because we don't have a vault that is shared between Connector and IdentityHub, so this needs to be seeded to either of them. - * - * @param context the service extension context used for accessing configuration and other services - */ - private void seedKeys(ServiceExtensionContext context) { - // Let's avoid pulling in the connector-core module, just for the instanceof check - if (vault.getClass().getSimpleName().equals("InMemoryVault")) { - var publicKey = """ - -----BEGIN PUBLIC KEY----- - MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5r - oYnkAXuqCYfNK3ex+hMWFuiXGUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== - -----END PUBLIC KEY----- - """; - - var privateKey = """ - -----BEGIN EC PRIVATE KEY----- - MHcCAQEEIARDUGJgKy1yzxkueIJ1k3MPUWQ/tbQWQNqW6TjyHpdcoAoGCCqGSM49 - AwEHoUQDQgAE1l0Lof0a1yBc8KXhesAnoBvxZw5roYnkAXuqCYfNK3ex+hMWFuiX - GUxHlzShAehR6wvwzV23bbC0tcFcVgW//A== - -----END EC PRIVATE KEY----- - """; - - - vault.storeSecret(context.getConfig().getString(STS_PRIVATE_KEY_ALIAS), privateKey); - vault.storeSecret(context.getConfig().getString(STS_PUBLIC_KEY_ID), publicKey); - - context.getMonitor().withPrefix("DEMO").warning(">>>>>> This extension hard-codes a keypair into the vault! <<<<<<"); - } - } -} diff --git a/extensions/did-example-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/did-example-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index e8aee0b40..000000000 --- a/extensions/did-example-resolver/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,15 +0,0 @@ -# -# 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 -# -# - -org.eclipse.edc.iam.identitytrust.core.SecretsExtension \ No newline at end of file diff --git a/extensions/superuser-seed/build.gradle.kts b/extensions/superuser-seed/build.gradle.kts deleted file mode 100644 index 461762a40..000000000 --- a/extensions/superuser-seed/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -/* -* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -* -* 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: -* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - Initial API and Implementation -* -*/ - -plugins { - `java-library` -} - -dependencies { - implementation(libs.edc.ih.spi.credentials) - implementation(libs.edc.ih.spi) - testImplementation(libs.edc.junit) - -} diff --git a/extensions/superuser-seed/src/main/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtension.java b/extensions/superuser-seed/src/main/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtension.java deleted file mode 100644 index df2634a0e..000000000 --- a/extensions/superuser-seed/src/main/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtension.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.identityhub.seed; - -import org.eclipse.edc.identityhub.spi.authentication.ServicePrincipal; -import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService; -import org.eclipse.edc.identityhub.spi.participantcontext.model.KeyDescriptor; -import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantManifest; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - -import java.util.List; -import java.util.Map; - -import static java.util.Optional.ofNullable; - -public class ParticipantContextSeedExtension implements ServiceExtension { - public static final String NAME = "MVD ParticipantContext Seed Extension"; - public static final String DEFAULT_SUPER_USER_PARTICIPANT_ID = "super-user"; - - @Setting(value = "Explicitly set the initial API key for the Super-User") - public static final String SUPERUSER_APIKEY_PROPERTY = "edc.ih.api.superuser.key"; - - @Setting(value = "Config value to set the super-user's participant ID.", defaultValue = DEFAULT_SUPER_USER_PARTICIPANT_ID) - public static final String SUPERUSER_PARTICIPANT_ID_PROPERTY = "edc.ih.api.superuser.id"; - private String superUserParticipantId; - private String superUserApiKey; - private Monitor monitor; - @Inject - private ParticipantContextService participantContextService; - @Inject - private Vault vault; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - superUserParticipantId = context.getSetting(SUPERUSER_PARTICIPANT_ID_PROPERTY, DEFAULT_SUPER_USER_PARTICIPANT_ID); - superUserApiKey = context.getSetting(SUPERUSER_APIKEY_PROPERTY, null); - monitor = context.getMonitor(); - } - - @Override - public void start() { - // create super-user - if (participantContextService.getParticipantContext(superUserParticipantId).succeeded()) { // already exists - monitor.debug("super-user already exists with ID '%s', will not re-create".formatted(superUserParticipantId)); - return; - } - participantContextService.createParticipantContext(ParticipantManifest.Builder.newInstance() - .participantId(superUserParticipantId) - .did("did:web:%s".formatted(superUserParticipantId)) // doesn't matter, not intended for resolution - .active(true) - .key(KeyDescriptor.Builder.newInstance() - .keyGeneratorParams(Map.of("algorithm", "EdDSA", "curve", "Ed25519")) - .keyId("%s-key".formatted(superUserParticipantId)) - .privateKeyAlias("%s-alias".formatted(superUserParticipantId)) - .build()) - .roles(List.of(ServicePrincipal.ROLE_ADMIN)) - .build()) - .onSuccess(generatedKey -> { - var apiKey = ofNullable(superUserApiKey) - .map(key -> { - if (!key.contains(".")) { - monitor.warning("Super-user key override: this key appears to have an invalid format, you may be unable to access some APIs. It must follow the structure: 'base64().'"); - } - participantContextService.getParticipantContext(superUserParticipantId) - .onSuccess(pc -> vault.storeSecret(pc.getApiTokenAlias(), key) - .onSuccess(u -> monitor.debug("Super-user key override successful")) - .onFailure(f -> monitor.warning("Error storing API key in vault: %s".formatted(f.getFailureDetail())))) - .onFailure(f -> monitor.warning("Error overriding API key for '%s': %s".formatted(superUserParticipantId, f.getFailureDetail()))); - return key; - }) - .orElse(generatedKey.apiKey()); - monitor.info("Created user 'super-user'. Please take note of the API Key: %s".formatted(apiKey)); - }) - .orElseThrow(f -> new EdcException("Error creating Super-User: " + f.getFailureDetail())); - } -} diff --git a/extensions/superuser-seed/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/superuser-seed/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 94348f1c8..000000000 --- a/extensions/superuser-seed/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,15 +0,0 @@ -# -# 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 -# -# - -org.eclipse.edc.identityhub.seed.ParticipantContextSeedExtension \ No newline at end of file diff --git a/extensions/superuser-seed/src/test/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtensionTest.java b/extensions/superuser-seed/src/test/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtensionTest.java deleted file mode 100644 index 3b12ab8fb..000000000 --- a/extensions/superuser-seed/src/test/java/org/eclipse/edc/identityhub/seed/ParticipantContextSeedExtensionTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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 - * - */ - -package org.eclipse.edc.identityhub.seed; - -import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService; -import org.eclipse.edc.identityhub.spi.participantcontext.model.CreateParticipantContextResponse; -import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantContext; -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -class ParticipantContextSeedExtensionTest { - - public static final String SUPER_USER = "super-user"; - public static final String API_KEY = "apiKey"; - private final ParticipantContextService participantContextService = mock(); - private final Vault vault = mock(); - private final Monitor monitor = mock(); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(ParticipantContextService.class, participantContextService); - context.registerService(Vault.class, vault); - context.registerService(Monitor.class, monitor); - when(participantContextService.getParticipantContext(eq(SUPER_USER))).thenReturn(ServiceResult.notFound("foobar")); - } - - @Test - void start_verifySuperUser(ParticipantContextSeedExtension ext, - ServiceExtensionContext context) { - - when(participantContextService.createParticipantContext(any())).thenReturn(ServiceResult.success(new CreateParticipantContextResponse("some-key", null, null))); - ext.initialize(context); - - ext.start(); - verify(participantContextService).getParticipantContext(eq(SUPER_USER)); - verify(participantContextService).createParticipantContext(any()); - verifyNoMoreInteractions(participantContextService); - } - - @Test - void start_failsToCreate(ParticipantContextSeedExtension ext, ServiceExtensionContext context) { - - when(participantContextService.createParticipantContext(any())) - .thenReturn(ServiceResult.badRequest("test-message")); - ext.initialize(context); - assertThatThrownBy(ext::start).isInstanceOf(EdcException.class); - - verify(participantContextService).getParticipantContext(eq(SUPER_USER)); - verify(participantContextService).createParticipantContext(any()); - verifyNoMoreInteractions(participantContextService); - } - - @Test - void start_withApiKeyOverride(ParticipantContextSeedExtension ext, - ServiceExtensionContext context) { - - - when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - - var apiKeyOverride = "c3VwZXItdXNlcgo=.asdfl;jkasdfl;kasdf"; - when(context.getSetting(eq(ParticipantContextSeedExtension.SUPERUSER_APIKEY_PROPERTY), eq(null))) - .thenReturn(apiKeyOverride); - - when(participantContextService.createParticipantContext(any())) - .thenReturn(ServiceResult.success(new CreateParticipantContextResponse("generated-api-key", null, null))); - when(participantContextService.getParticipantContext(eq(SUPER_USER))) - .thenReturn(ServiceResult.notFound("foobar")) - .thenReturn(ServiceResult.success(superUserContext().build())); - - ext.initialize(context); - ext.start(); - verify(participantContextService, times(2)).getParticipantContext(eq(SUPER_USER)); - verify(participantContextService).createParticipantContext(any()); - verify(vault).storeSecret(eq("super-user-apikey"), eq(apiKeyOverride)); - verifyNoMoreInteractions(participantContextService, vault); - } - - @Test - void start_withInvalidKeyOverride(ParticipantContextSeedExtension ext, - ServiceExtensionContext context) { - when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - - var apiKeyOverride = "some-invalid-key"; - when(context.getSetting(eq(ParticipantContextSeedExtension.SUPERUSER_APIKEY_PROPERTY), eq(null))) - .thenReturn(apiKeyOverride); - - when(participantContextService.createParticipantContext(any())) - .thenReturn(ServiceResult.success(new CreateParticipantContextResponse("generated-api-key", null, null))); - when(participantContextService.getParticipantContext(eq(SUPER_USER))) - .thenReturn(ServiceResult.notFound("foobar")) - .thenReturn(ServiceResult.success(superUserContext().build())); - - ext.initialize(context); - ext.start(); - verify(participantContextService).createParticipantContext(any()); - verify(participantContextService, times(2)).getParticipantContext(eq(SUPER_USER)); - verify(vault).storeSecret(eq("super-user-apikey"), eq(apiKeyOverride)); - verify(monitor).warning(contains("this key appears to have an invalid format")); - verifyNoMoreInteractions(participantContextService, vault); - } - - @Test - void start_whenVaultReturnsFailure(ParticipantContextSeedExtension ext, - ServiceExtensionContext context) { - when(vault.storeSecret(any(), any())).thenReturn(Result.failure("test-failure")); - - var apiKeyOverride = "c3VwZXItdXNlcgo=.asdfl;jkasdfl;kasdf"; - when(context.getSetting(eq(ParticipantContextSeedExtension.SUPERUSER_APIKEY_PROPERTY), eq(null))) - .thenReturn(apiKeyOverride); - - when(participantContextService.createParticipantContext(any())) - .thenReturn(ServiceResult.success(new CreateParticipantContextResponse("generated-api-key", null, null))); - when(participantContextService.getParticipantContext(eq(SUPER_USER))) - .thenReturn(ServiceResult.notFound("foobar")) - .thenReturn(ServiceResult.success(superUserContext().build())); - - ext.initialize(context); - ext.start(); - verify(participantContextService, times(2)).getParticipantContext(eq(SUPER_USER)); - verify(participantContextService).createParticipantContext(any()); - verify(vault).storeSecret(eq("super-user-apikey"), eq(apiKeyOverride)); - verify(monitor).warning(eq("Error storing API key in vault: test-failure")); - verifyNoMoreInteractions(participantContextService, vault); - } - - private ParticipantContext.Builder superUserContext() { - return ParticipantContext.Builder.newInstance() - .participantContextId(SUPER_USER) - .apiTokenAlias("super-user-apikey"); - - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e6e4c6a03..0b55ba92d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ group=org.eclipse.edc -version=0.15.0-SNAPSHOT +version=0.17.0-SNAPSHOT diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 97eb57c36..a8fbacab6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,13 +3,15 @@ format.version = "1.1" [versions] awaitility = "4.3.0" -edc = "0.14.1" +edc = "0.17.0-SNAPSHOT" edc-build = "1.3.0" jackson = "2.21.2" jakarta-json = "2.1.3" parsson = "1.1.6" postgres = "42.7.10" restAssured = "6.0.0" +rsApi = "4.0.0" +swagger = "2.2.44" [libraries] # upstream EDC dependencies @@ -17,7 +19,9 @@ edc-boot = { module = "org.eclipse.edc:boot", version.ref = "edc" } edc-config-fs = { module = "org.eclipse.edc:configuration-filesystem", version.ref = "edc" } edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } edc-did-core = { module = "org.eclipse.edc:identity-did-core", version.ref = "edc" } +edc-core-jersey = { module = "org.eclipse.edc:jersey-core", version.ref = "edc" } edc-did-web = { module = "org.eclipse.edc:identity-did-web", version.ref = "edc" } +edc-core-participantcontext-config = { module = "org.eclipse.edc:participant-context-config-core", version.ref = "edc" } edc-core-api = { module = "org.eclipse.edc:api-core", version.ref = "edc" } edc-core-connector = { module = "org.eclipse.edc:connector-core", version.ref = "edc" } edc-core-token = { module = "org.eclipse.edc:token-core", version.ref = "edc" } @@ -26,23 +30,28 @@ edc-core-edrstore = { module = "org.eclipse.edc:edr-store-core", version.ref = " edc-ext-http = { module = "org.eclipse.edc:http", version.ref = "edc" } edc-ext-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } edc-api-dsp-config = { module = "org.eclipse.edc:dsp-http-api-configuration-2025", version.ref = "edc" } -edc-dcp = { module = "org.eclipse.edc:identity-trust-service", version.ref = "edc" } +edc-dcp = { module = "org.eclipse.edc:decentralized-claims-service", version.ref = "edc" } edc-controlplane-core = { module = "org.eclipse.edc:control-plane-core", version.ref = "edc" } edc-controlplane-transform = { module = "org.eclipse.edc:control-plane-transform", version.ref = "edc" } edc-controlplane-services = { module = "org.eclipse.edc:control-plane-aggregate-services", version.ref = "edc" } edc-api-management-config = { module = "org.eclipse.edc:management-api-configuration", version.ref = "edc" } edc-api-management = { module = "org.eclipse.edc:management-api", version.ref = "edc" } +edc-api-cel-v5 = {module = "org.eclipse.edc:cel-api-v5", version.ref= "edc"} edc-api-secrets = { module = "org.eclipse.edc:secrets-api", version.ref = "edc" } edc-api-observability = { module = "org.eclipse.edc:api-observability", version.ref = "edc" } edc-dsp = { module = "org.eclipse.edc:dsp", version.ref = "edc" } edc-dataplane-v2 = { module = "org.eclipse.edc:data-plane-public-api-v2", version.ref = "edc" } - -edc-dcp-core = { module = "org.eclipse.edc:identity-trust-core", version.ref = "edc" } +edc-core-cel = { module = "org.eclipse.edc:cel-core", version.ref = "edc" } +edc-dcp-core = { module = "org.eclipse.edc:decentralized-claims-core", version.ref = "edc" } edc-vault-hashicorp = { module = "org.eclipse.edc:vault-hashicorp", version.ref = "edc" } -edc-spi-identity-trust = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } +edc-spi-identity-trust = { module = "org.eclipse.edc:decentralized-claims-spi", version.ref = "edc" } edc-spi-transform = { module = "org.eclipse.edc:transform-spi", version.ref = "edc" } edc-spi-catalog = { module = "org.eclipse.edc:catalog-spi", version.ref = "edc" } edc-spi-identity-did = { module = "org.eclipse.edc:identity-did-spi", version.ref = "edc" } +edc-spi-http = { module = "org.eclipse.edc:http-spi", version.ref = "edc" } +edc-spi-web = { module = "org.eclipse.edc:web-spi", version.ref = "edc" } +edc-spi-dataplane = { module = "org.eclipse.edc:data-plane-spi", version.ref = "edc" } +edc-spi-dataplane-selector = { module = "org.eclipse.edc:data-plane-selector-spi", version.ref = "edc" } # EDC lib dependencies edc-lib-jws2020 = { module = "org.eclipse.edc:jws2020-lib", version.ref = "edc" } @@ -50,6 +59,12 @@ edc-lib-transform = { module = "org.eclipse.edc:transform-lib", version.ref = "e edc-lib-crypto = { module = "org.eclipse.edc:crypto-common-lib", version.ref = "edc" } edc-lib-keys = { module = "org.eclipse.edc:keys-lib", version.ref = "edc" } edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" } +edc-lib-http = { module = "org.eclipse.edc:http-lib", version.ref = "edc" } +edc-lib-util = { module = "org.eclipse.edc:util-lib", version.ref = "edc" } +edc-lib-sql = { module = "org.eclipse.edc:sql-lib", version.ref = "edc" } +edc-lib-util-dataplane = { module = "org.eclipse.edc:data-plane-util", version.ref = "edc" } +edc-lib-oauth2-authn = { module = "org.eclipse.edc:auth-authentication-oauth2-lib", version.ref = "edc" } +edc-lib-oauth2-authz = { module = "org.eclipse.edc:auth-authorization-oauth2-lib", version.ref = "edc" } # EDC Postgres modules edc-sql-assetindex = { module = "org.eclipse.edc:asset-index-sql", version.ref = "edc" } @@ -63,6 +78,8 @@ edc-sql-lease = { module = "org.eclipse.edc:sql-lease", version.ref = "edc" } edc-sql-pool = { module = "org.eclipse.edc:sql-pool-apache-commons", version.ref = "edc" } edc-sql-transactionlocal = { module = "org.eclipse.edc:transaction-local", version.ref = "edc" } edc-sql-dataplane-instancestore = { module = "org.eclipse.edc:data-plane-instance-store-sql", version.ref = "edc" } +edc-store-participantcontext-config-sql = { module = "org.eclipse.edc:participantcontext-config-store-sql", version.ref = "edc" } +edc-cel-store-sql = { module = "org.eclipse.edc:cel-store-sql", version.ref = "edc" } # identityhub SPI modules edc-ih-spi-did = { module = "org.eclipse.edc:did-spi", version.ref = "edc" } @@ -80,18 +97,13 @@ edc-issuance-spi = { module = "org.eclipse.edc:issuerservice-issuance-spi", vers # EDC STS dependencies, used in IdentityHub edc-sts-remote-client = { module = "org.eclipse.edc:identity-trust-sts-remote-client", version.ref = "edc" } -# federated catalog modules -edc-fc-spi-crawler = { module = "org.eclipse.edc:crawler-spi", version.ref = "edc" } -edc-fc-core = { module = "org.eclipse.edc:federated-catalog-core", version.ref = "edc" } -edc-fc-core2025 = { module = "org.eclipse.edc:federated-catalog-core-2025", version.ref = "edc" } -edc-fc-core08 = { module = "org.eclipse.edc:federated-catalog-core-08", version.ref = "edc" } -edc-fc-api = { module = "org.eclipse.edc:federated-catalog-api", version.ref = "edc" } - # Third party libs postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" } awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" } restAssured = { module = "io.rest-assured:rest-assured", version.ref = "restAssured" } jakarta-json-api = { module = "jakarta.json:jakarta.json-api", version.ref = "jakarta-json" } +jakarta-rsApi = { module = "jakarta.ws.rs:jakarta.ws.rs-api", version.ref = "rsApi" } +tink = { module = "com.google.crypto.tink:tink", version = "1.20.0" } jackson-datatype-jakarta-jsonp = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp", version.ref = "jackson" } parsson = { module = "org.eclipse.parsson:parsson", version.ref = "parsson" } @@ -100,47 +112,14 @@ edc-bom-controlplane = { module = "org.eclipse.edc:controlplane-dcp-bom", versio edc-bom-dataplane = { module = "org.eclipse.edc:dataplane-base-bom", version.ref = "edc" } edc-bom-controlplane-sql = { module = "org.eclipse.edc:controlplane-feature-sql-bom", version.ref = "edc" } edc-bom-dataplane-sql = { module = "org.eclipse.edc:dataplane-feature-sql-bom", version.ref = "edc" } -edc-bom-identityhub = { module = "org.eclipse.edc:identityhub-bom", version.ref = "edc" } +edc-bom-identityhub = { module = "org.eclipse.edc:identityhub-oauth2-bom", version.ref = "edc" } edc-bom-identityhub-sql = { module = "org.eclipse.edc:identityhub-feature-sql-bom", version.ref = "edc" } -edc-bom-issuerservice = { module = "org.eclipse.edc:issuerservice-bom", version.ref = "edc" } +edc-bom-issuerservice = { module = "org.eclipse.edc:issuerservice-oauth2-bom", version.ref = "edc" } edc-bom-issuerservice-sql = { module = "org.eclipse.edc:issuerservice-feature-sql-bom", version.ref = "edc" } [bundles] -connector = [ - "edc-boot", - "edc-core-connector", - "edc-core-runtime", - "edc-core-api", - "edc-ext-http", - "edc-api-observability", - "edc-ext-jsonld", - "edc-core-token", - "edc-config-fs", -] - -dcp = [ - "edc-dcp", - "edc-did-core", - "edc-did-web", - "edc-oauth2-client", - "edc-dcp-core", -] - -sql-edc = [ - "edc-sql-assetindex", - "edc-sql-contractdef", - "edc-sql-contractneg", - "edc-sql-policydef", - "edc-sql-edrcache", - "edc-sql-transferprocess", - "edc-sql-dataplane-instancestore", - "edc-sql-core", - "edc-sql-lease", - "edc-sql-pool", - "edc-sql-transactionlocal", - "postgres", -] [plugins] shadow = { id = "com.gradleup.shadow", version = "9.4.0" } edc-build = { id = "org.eclipse.edc.edc-build", version.ref = "edc-build" } +swagger = { id = "io.swagger.core.v3.swagger-gradle-plugin", version.ref = "swagger" } diff --git a/k8s/common/gateway-class.yaml b/k8s/common/gateway-class.yaml new file mode 100644 index 000000000..c6d0744a5 --- /dev/null +++ b/k8s/common/gateway-class.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: traefik +spec: + controllerName: traefik.io/gateway-controller \ No newline at end of file diff --git a/k8s/common/gateway.yaml b/k8s/common/gateway.yaml new file mode 100644 index 000000000..9f70e6beb --- /dev/null +++ b/k8s/common/gateway.yaml @@ -0,0 +1,31 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: common-gateway + namespace: mvd-common +spec: + gatewayClassName: traefik + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All #or Same or Selector +# kinds: +# - kind: HTTPRoute +# group: gateway.networking.k8s.io \ No newline at end of file diff --git a/k8s/common/keycloak.yaml b/k8s/common/keycloak.yaml new file mode 100644 index 000000000..443c2b3df --- /dev/null +++ b/k8s/common/keycloak.yaml @@ -0,0 +1,291 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: keycloak + namespace: mvd-common +spec: + replicas: 1 + selector: + matchLabels: + app: keycloak + template: + metadata: + labels: + app: keycloak + type: edc-infra + spec: + containers: + - name: keycloak + image: quay.io/keycloak/keycloak:latest + args: + - "start-dev" + - "--health-enabled=true" + - "--import-realm" + ports: + - containerPort: 8080 + name: http + - containerPort: 9000 + name: health + env: + - name: KEYCLOAK_ADMIN + value: "admin" + - name: KC_BOOTSTRAP_ADMIN_USERNAME + value: "admin" + - name: KC_BOOTSTRAP_ADMIN_PASSWORD + value: "admin" + - name: KC_HTTP_ENABLED + value: "true" + - name: KC_HOSTNAME + value: http://keycloak.mvd-common.svc.cluster.local:8080 + - name: KC_HOSTNAME_STRICT + value: "false" + - name: KC_HOSTNAME_URL + value: "http://keycloak.mvd-common.svc.cluster.local:8080" + - name: KC_PROXY + value: "edge" + - name: KC_HEALTH_ENABLED + value: "true" + - name: KC_METRICS_ENABLED + value: "true" + - name: KC_LOG_LEVEL + value: INFO + - name: KC_DB + value: postgres + - name: POSTGRES_DB + value: keycloak + - name: KC_DB_URL + value: jdbc:postgresql://postgres.mvd-common.svc.cluster.local:5432/keycloak + - name: KC_DB_USERNAME + value: "kc" + - name: KC_DB_PASSWORD + value: "kc" + volumeMounts: + - name: realm-config + mountPath: /opt/keycloak/data/import + readinessProbe: + httpGet: + path: /health/ready + port: 9000 + initialDelaySeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 12 + livenessProbe: + httpGet: + path: /health/live + port: 9000 + initialDelaySeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 12 + volumes: + - name: realm-config + configMap: + name: keycloak-realm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: keycloak-realm + namespace: mvd-common + labels: + tier: infrastructure +data: + mvd-realm.json: | + { + "realm": "mvd", + "enabled": true, + "sslRequired": "none", + "displayName": "MVD Realm", + "roles": { + "realm": [ + { + "name": "admin", + "description": "Administrator with full access to all tenants and their resources"}, + { + "name": "provisioner", + "description": "Can create and delete tenants but cannot access their resources"}, + { + "name": "participant", + "description": "Regular participant context access role, can access their own resources"} + ] + }, + "clientScopes": [ + { + "name": "identity-api:read", + "description": "Read access to Identity API", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }, + { + "name": "identity-api:write", + "description": "Create, update delete objects in the Identity API", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }, + { + "name": "issuer-admin-api:read", + "description": "read access to the Issuer Admin API", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + }, + { + "name": "issuer-admin-api:write", + "description": "write access to the Issuer Admin API", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" + } + } + ], + "defaultOptionalClientScopes": [ + "offline_access", + "management-api:read", + "management-api:write", + "identity-api:read", + "identity-api:write", + "issuer-admin-api:read", + "issuer-admin-api:write" + ], + "clients": [ + { + "clientId": "admin", + "name": "EDC-V Admin User", + "description": "Global admin client with full access", + "enabled": true, + "protocol": "openid-connect", + "publicClient": false, + "serviceAccountsEnabled": true, + "secret": "edc-v-admin-secret", + "standardFlowEnabled": false, + "directAccessGrantsEnabled": false, + "fullScopeAllowed": true, + "protocolMappers": [ + { + "name": "role", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "claim.name": "role", + "claim.value": "admin", + "jsonType.label": "String", + "access.token.claim": "true", + "id.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "issuer-admin-api:write", + "issuer-admin-api:read", + "identity-api:write", + "identity-api:read" + ] + }, + { + "clientId": "provisioner", + "name": "Provisioner User", + "description": "Can create and delete tenants", + "enabled": true, + "protocol": "openid-connect", + "publicClient": false, + "serviceAccountsEnabled": true, + "secret": "provisioner-secret", + "standardFlowEnabled": false, + "directAccessGrantsEnabled": false, + "fullScopeAllowed": true, + "protocolMappers": [ + { + "name": "role", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "claim.name": "role", + "claim.value": "provisioner", + "jsonType.label": "String", + "access.token.claim": "true", + "id.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "issuer-admin-api:write", + "issuer-admin-api:read", + "identity-api:write", + "identity-api:read", + "management-api:write", + "management-api:read" + ] + } + ], + "users": [], + "groups": [], + "eventsEnabled": false + } + +--- +apiVersion: v1 +kind: Service +metadata: + name: keycloak + namespace: mvd-common + labels: + tier: infrastructure +spec: + selector: + app: keycloak + ports: + - port: 8080 + targetPort: 8080 + name: http + - port: 9000 + targetPort: 9000 + name: health + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: keycloak + namespace: mvd-common +spec: + parentRefs: + - name: common-gateway + kind: Gateway + sectionName: http + hostnames: + - keycloak.localhost + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: keycloak + port: 8080 \ No newline at end of file diff --git a/k8s/common/kustomization.yaml b/k8s/common/kustomization.yaml new file mode 100644 index 000000000..af8786dae --- /dev/null +++ b/k8s/common/kustomization.yaml @@ -0,0 +1,19 @@ +# +# Copyright (c) 2026 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 +# + +resources: + - namespace.yaml + - gateway-class.yaml + - gateway.yaml + - postgres.yaml + - keycloak.yaml \ No newline at end of file diff --git a/k8s/common/namespace.yaml b/k8s/common/namespace.yaml new file mode 100644 index 000000000..aee2d8754 --- /dev/null +++ b/k8s/common/namespace.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: v1 +kind: Namespace +metadata: + name: mvd-common diff --git a/k8s/common/postgres.yaml b/k8s/common/postgres.yaml new file mode 100644 index 000000000..1229873cb --- /dev/null +++ b/k8s/common/postgres.yaml @@ -0,0 +1,76 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: mvd-common + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + platform: edcv + type: edc-infra + spec: + containers: + - name: postgres + image: postgres:17.7-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: "keycloak" + - name: POSTGRES_USER + value: "kc" + - name: POSTGRES_PASSWORD + value: "kc" + volumeMounts: + - name: init-script + mountPath: /docker-entrypoint-initdb.d + volumes: + - name: init-script + configMap: + name: postgres-init +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: mvd-common +spec: + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init + namespace: mvd-common +data: + init.sql: | + + GRANT ALL PRIVILEGES ON DATABASE keycloak TO kc; + \c keycloak + GRANT ALL ON SCHEMA public TO kc; \ No newline at end of file diff --git a/k8s/consumer/application/controlplane-config.yaml b/k8s/consumer/application/controlplane-config.yaml new file mode 100644 index 000000000..c69107b2a --- /dev/null +++ b/k8s/consumer/application/controlplane-config.yaml @@ -0,0 +1,72 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: controlplane-config + namespace: consumer +data: + # base config + edc.hostname: "controlplane.consumer.svc.cluster.local" + edc.vault.hashicorp.url: "http://vault.consumer.svc.cluster.local:8200" + edc.vault.hashicorp.token: "root" + edc.participant.id: "did:web:identityhub.consumer.svc.cluster.local%3A7083:consumer" + edc.iam.did.web.use.https: "false" + edc.iam.credential.revocation.mimetype: "application/json" + edc.iam.sts.oauth.token.url: "http://identityhub.consumer.svc.cluster.local:7084/api/sts/token" + edc.iam.sts.oauth.client.id: "did:web:identityhub.consumer.svc.cluster.local%3A7083:consumer" + edc.iam.sts.oauth.client.secret.alias: "consumer-participant-sts-client-secret" + + + # web config + web.http.port: "8080" + web.http.path: "/api" + web.http.protocol.port: "8082" + web.http.protocol.path: "/api/dsp" + web.http.management.port: "8081" + web.http.management.path: "/api/mgmt" + web.http.control.port: "8083" + web.http.control.path: "/api/control" + + # dataplane config + edc.datasource.default.url: "jdbc:postgresql://postgres.consumer.svc.cluster.local:5432/controlplane" + edc.datasource.default.user: "cp" + edc.datasource.default.password: "cp" + edc.sql.schema.autocreate: "true" + + edc.encryption.aes.key.alias: "aes-key-alias" + + # Oauth2 config + # KeyCloak takes the `iss` claim's host from the request URL. For now, this is the URL defined in the ingress route. + # to do this properly, we should probably configure the following properties on the ingress route: + # proxy_set_header Host $host; + # proxy_set_header X-Forwarded-Proto $scheme; + edc.iam.oauth2.issuer: "http://keycloak.mvd-common.svc.cluster.local:8080/realms/edcv" + edc.iam.oauth2.jwks.url: "http://keycloak.mvd-common.svc.cluster.local:8080/realms/edcv/protocol/openid-connect/certs" + + # Default scopes config + edc.iam.dcp.scopes.membership.id: "membership-scope" + edc.iam.dcp.scopes.membership.type: "DEFAULT" + edc.iam.dcp.scopes.membership.value: "org.eclipse.dspace.dcp.vc.type:MembershipCredential:read" + + edc.iam.dcp.scopes.manufacturer.id: "manufacturer-scope" + edc.iam.dcp.scopes.manufacturer.type: "POLICY" + edc.iam.dcp.scopes.manufacturer.value: "org.eclipse.dspace.dcp.vc.type:ManufacturerCredential:read" + edc.iam.dcp.scopes.manufacturer.prefix-mapping: "ManufacturerCredential" + + # Trusted Issuers + edc.iam.trusted-issuer.issuer.id: "did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer" + + JAVA_TOOL_OPTIONS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044" \ No newline at end of file diff --git a/k8s/consumer/application/controlplane-seed.yaml b/k8s/consumer/application/controlplane-seed.yaml new file mode 100644 index 000000000..335096559 --- /dev/null +++ b/k8s/consumer/application/controlplane-seed.yaml @@ -0,0 +1,119 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: controlplane-seed + namespace: consumer + labels: + app: controlplane-seed + platform: edcv + type: edc-job +spec: + backoffLimit: 5 + template: + metadata: + labels: + app: controlplane-seed + type: edc-job + spec: + restartPolicy: OnFailure + initContainers: + - name: wait-for-controlplane + image: curlimages/curl:latest + command: + - sh + - -c + - | + until curl -sf http://controlplane.consumer.svc.cluster.local:8080/api/check/readiness; do + echo "Waiting for controlplane to be ready..." + sleep 5 + done + echo "" + echo "Controlplane is ready!" + containers: + - name: seed-controlplane + image: curlimages/curl:latest + command: + - sh + - -c + - | + set -e + + MGMT_URL="http://controlplane.consumer.svc.cluster.local:8081/api/mgmt/v5alpha/celexpressions" + + # Posts to the management API, treating 409 (already exists) as success. + create_cel() { + HTTP_STATUS=$(curl -sS -o /dev/null -w "%{http_code}" -X POST "${MGMT_URL}" \ + -H "Content-Type: application/json" \ + -d "$1") + if [ "${HTTP_STATUS}" -eq 409 ]; then + echo "⚠ CEL Expression already exists (HTTP 409), skipping." + elif [ "${HTTP_STATUS}" -lt 200 ] || [ "${HTTP_STATUS}" -ge 300 ]; then + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + exit 1 + fi + } + + echo "================================================" + echo "Step 1: Create Membership CEL Expression " + echo "================================================" + + create_cel '{ + "@context": [ + "https://w3id.org/edc/connector/management/v2" + ], + "@type": "CelExpression", + "@id": "membership-cel", + "leftOperand": "MembershipCredential", + "description": "Expression for evaluating membership credential", + "scopes": [ + "catalog", + "contract.negotiation", + "transfer.process" + ], + "expression": "ctx.agent.claims.vc.filter(c, c.type.exists(t, t == '\''MembershipCredential'\'')).exists(c, c.credentialSubject.exists(cs, timestamp(cs.membershipStartDate) < now))" + }' + + echo "✓ Membership CEL Expression done" + + echo "" + echo "================================================" + echo "Step 2: Create ManufacturerCredential CEL Expression" + echo "================================================" + + create_cel '{ + "@context": [ + "https://w3id.org/edc/connector/management/v2" + ], + "@type": "CelExpression", + "@id": "membership-cel", + "leftOperand": "ManufacturerCredential", + "description": "Expression for evaluating manufacturer credential", + "scopes": [ + "catalog", + "contract.negotiation", + "transfer.process" + ], + "expression": "ctx.agent.claims.vc.filter(c, c.type.exists(t, t == '\''ManufacturerCredential'\'')).size() > 0" + }' + + echo "✓ ManufacturerCredential CEL Expression done" + + echo "" + echo "================================================" + echo "Controlplane seeding completed successfully!" + echo "================================================" + diff --git a/k8s/consumer/application/controlplane.yaml b/k8s/consumer/application/controlplane.yaml new file mode 100644 index 000000000..f0bbd8490 --- /dev/null +++ b/k8s/consumer/application/controlplane.yaml @@ -0,0 +1,112 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controlplane + namespace: consumer + labels: + app: controlplane + type: edc-app +spec: + replicas: 1 + selector: + matchLabels: + app: controlplane + template: + metadata: + name: controlplane + labels: + app: controlplane + platform: edcv + type: edc-app + spec: + containers: + - name: controlplane + image: ghcr.io/eclipse-edc/mvd/controlplane:latest + imagePullPolicy: Never + envFrom: + - configMapRef: { name: controlplane-config } + ports: + - containerPort: 1044 + name: debug-port + livenessProbe: + httpGet: + path: /api/check/liveness + port: 8080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + readinessProbe: + httpGet: + path: /api/check/readiness + port: 8080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + startupProbe: + httpGet: + path: /api/check/startup + port: 8080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + restartPolicy: Always + +--- +apiVersion: v1 +kind: Service +metadata: + name: controlplane + namespace: consumer +spec: + type: ClusterIP + selector: + app: controlplane + ports: + - name: health + port: 8080 + targetPort: 8080 + - name: management + port: 8081 + targetPort: 8081 + - name: protocol + port: 8082 + targetPort: 8082 + - name: debug + port: 1044 + targetPort: 1044 + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: controlplane + namespace: consumer +spec: + parentRefs: + - name: consumer-gateway + kind: Gateway + sectionName: http + hostnames: + - cp.consumer.localhost + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: controlplane + port: 8081 + weight: 1 \ No newline at end of file diff --git a/k8s/consumer/application/identityhub-config.yaml b/k8s/consumer/application/identityhub-config.yaml new file mode 100644 index 000000000..c117059b1 --- /dev/null +++ b/k8s/consumer/application/identityhub-config.yaml @@ -0,0 +1,55 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: v1 +kind: ConfigMap +metadata: + name: ih-config + namespace: consumer +data: + edc.hostname: "identityhub.consumer.svc.cluster.local" + edc.iam.credentia.revocation.mimetype: "application/json" + edc.iam.did.web.use.https: "false" + edc.ih.iam.publickey.alias: "publickey-alias" + web.http.port: "7080" + web.http.path: "/api" + web.http.identity.port: "7081" + web.http.identity.path: "/api/identity" + web.http.identity.auth.key: "password" + web.http.credentials.port: "7082" + web.http.credentials.path: "/api/credentials" + web.http.did.port: "7083" + web.http.did.path: "/" + web.http.sts.port: "7084" + web.http.sts.path: "/api/sts" + JAVA_TOOL_OPTIONS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044" + + edc.vault.hashicorp.url: "http://vault.consumer.svc.cluster.local:8200" + edc.vault.hashicorp.token: "root" + + edc.datasource.default.url: "jdbc:postgresql://postgres.consumer.svc.cluster.local:5432/identityhub" + edc.datasource.default.user: "ih" + edc.datasource.default.password: "ih" + edc.sql.schema.autocreate: "true" + edc.iam.accesstoken.jti.validation: "true" + # grace period for credential expiry, 3600*24 = 1 day + edc.iam.credential.renewal.graceperiod: "86400" + + edc.encryption.aes.key.alias: "aes-key-alias" + # Oauth2 config + # KeyCloak takes the `iss` claim's host from the request URL. For now, this is the URL defined in the ingress route. + # to do this properly, we should probably configure the following properties on the ingress route: + # proxy_set_header Host $host; + # proxy_set_header X-Forwarded-Proto $scheme; + edc.iam.oauth2.issuer: "http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd" + edc.iam.oauth2.jwks.url: "http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/protocol/openid-connect/certs" \ No newline at end of file diff --git a/k8s/consumer/application/identityhub-seed.yaml b/k8s/consumer/application/identityhub-seed.yaml new file mode 100644 index 000000000..833a30e66 --- /dev/null +++ b/k8s/consumer/application/identityhub-seed.yaml @@ -0,0 +1,268 @@ +# +# Copyright (c) 2026 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 +# + +# This seed job creates a participant context in the consumer's IdentityHub and a holder entry in the IssuerService. + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: identityhub-seed + namespace: consumer + labels: + app: identityhub-seed + type: edc-job +spec: + backoffLimit: 5 + template: + metadata: + labels: + app: identityhub-seed + type: edc-job + spec: + restartPolicy: OnFailure + initContainers: + - name: wait-for-dependencies + image: curlimages/curl:latest + env: + - name: KC_HOST + value: "http://keycloak.mvd-common.svc.cluster.local:8080" + + command: + - sh + - -c + - | + until curl -sf http://identityhub.consumer.svc.cluster.local:7080/api/check/readiness; do + echo "Waiting for identityhub to be ready..." + sleep 5 + done + echo "" + echo "IdentityHub is ready!" + + until curl -sf http://issuerservice.issuer.svc.cluster.local:10010/api/check/readiness; do + echo "Waiting for issuer service to be ready..." + sleep 5 + done + echo "" + echo "IssuerService is ready!" + + # Wait for Keycloak + echo "Waiting for Keycloak to be ready..." + until wget -q --spider "${KC_HOST}/realms/mvd/.well-known/openid-configuration" > /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + containers: + + - name: seed-identityhub + image: curlimages/curl:latest + env: + - name: KC_HOST + value: "http://keycloak.mvd-common.svc.cluster.local:8080" + - name: PROVISIONER_CLIENT_ID + value: "provisioner" + - name: PROVISIONER_CLIENT_SECRET + value: "provisioner-secret" + - name: ADMIN_CLIENT_ID + value: "admin" + - name: ADMIN_CLIENT_SECRET + value: "edc-v-admin-secret" + - name: IH_URL + value: "http://identityhub.consumer.svc.cluster.local:7081/api/identity/v1alpha/participants/" + - name: PARTICIPANT_DID + value: "did:web:identityhub.consumer.svc.cluster.local%3A7083:consumer" + - name: PARTICIPANT_ID + value: "consumer-participant" + - name: ISSUER_CLIENT_ID + value: "issuer" + - name: ISSUER_CLIENT_SECRET + value: "issuer-secret" + - name: ISSUER_ADMIN_URL + value: "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha" + command: + - sh + - -c + - | + set -e + + echo "" + echo "================================================" + echo "Step 1: Create Consumer Holder in IssuerService" + echo "================================================" + + ISSUER_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${ISSUER_CLIENT_ID}" \ + -d "client_secret=${ISSUER_CLIENT_SECRET}" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$ISSUER_TOKEN" ]; then + echo "Failed to get issuer token" + exit 1 + fi + + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${ISSUER_ADMIN_URL}/participants/issuer/holders" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"did\": \"${PARTICIPANT_DID}\", + \"holderId\": \"${PARTICIPANT_DID}\", + \"name\": \"MVD Consumer Participant\" + }") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -eq 200 ] || [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ Consumer holder created in IssuerService" + elif [ "${HTTP_STATUS}" -eq 409 ]; then + echo "⚠ Consumer holder already exists (HTTP 409), skipping." + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + + echo "================================================" + echo "Step 2: Create Consumer Participant Context in IdentityHub" + echo "================================================" + + PROVISIONER_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${PROVISIONER_CLIENT_ID}" \ + -d "client_secret=${PROVISIONER_CLIENT_SECRET}" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$PROVISIONER_TOKEN" ]; then + echo "Failed to get issuer token" + exit 1 + fi + + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${IH_URL}" \ + -H "Authorization: Bearer ${PROVISIONER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"roles\": [], + \"serviceEndpoints\": [ + { + \"type\": \"CredentialService\", + \"serviceEndpoint\": \"http://identityhub.consumer.svc.cluster.local:7082/api/credentials/v1/participants/${PARTICIPANT_ID}\", + \"id\": \"consumer-credentialservice-1\" + }, + { + \"type\": \"ProtocolEndpoint\", + \"serviceEndpoint\": \"http://controlplane.consumer.svc.cluster.local:8082/api/dsp/2025-1\", + \"id\": \"consumer-dsp\" + } + ], + \"active\": true, + \"participantId\": \"${PARTICIPANT_DID}\", + \"participantContextId\": \"${PARTICIPANT_ID}\", + \"did\": \"${PARTICIPANT_DID}\", + \"key\": { + \"keyId\": \"${PARTICIPANT_DID}#key-1\", + \"privateKeyAlias\": \"${PARTICIPANT_DID}#key-1\", + \"keyGeneratorParams\": { + \"algorithm\": \"EC\" + } + } + }") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -eq 200 ] || [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ Consumer participant context created" + elif [ "${HTTP_STATUS}" -eq 409 ]; then + echo "⚠ Consumer participant context already exists (HTTP 409), skipping." + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + + echo "================================================" + echo "Step 3: Requesting credential issuance" + echo "================================================" + + ADMIN_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${ADMIN_CLIENT_ID}" \ + -d "client_secret=${ADMIN_CLIENT_SECRET}" \ + -d "scope=identity-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$ADMIN_TOKEN" ]; then + echo "Failed to get OAuth2 token" + exit 1 + fi + + HOLDER_PID="credential-request-1" + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${IH_URL}${PARTICIPANT_ID}/credentials/request" \ + -H "Authorization: Bearer ${ADMIN_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"issuerDid\": \"did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer\", + \"holderPid\": \"${HOLDER_PID}\", + \"credentials\": [{ + \"format\": \"VC1_0_JWT\", + \"type\": \"MembershipCredential\", + \"id\": \"membership-credential-def\" + }, + { + \"format\": \"VC1_0_JWT\", + \"type\": \"ManufacturerCredential\", + \"id\": \"manufacturer-credential-def\" + }] + }") + + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + if [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ Consumer participant context created" + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${RESPONSE}" + exit 1 + fi + + echo "================================================" + echo "Step 4: Wait for credentials to be issued" + echo "================================================" + + STATUS="" + MAX_RETRIES=30 + RETRY=0 + while [ "${STATUS}" != "ISSUED" ]; do + if [ "${RETRY}" -ge "${MAX_RETRIES}" ]; then + echo "✗ Credentials not ISSUED after ${MAX_RETRIES} attempts" + exit 1 + fi + RESPONSE=$(curl -sS -w "\n%{http_code}" "${IH_URL}${PARTICIPANT_ID}/credentials/request/${HOLDER_PID}" \ + -H "Authorization: Bearer ${ADMIN_TOKEN}") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -ne 200 ]; then + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + STATUS=$(echo "${BODY}" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p') + echo "Credential status: ${STATUS}" + RETRY=$((RETRY + 1)) + sleep 5 + done + echo "✓ Credentials are ISSUED" + + echo "" + echo "================================================" + echo "IdentityHub seeding completed successfully!" + echo "================================================" \ No newline at end of file diff --git a/k8s/consumer/application/identityhub.yaml b/k8s/consumer/application/identityhub.yaml new file mode 100644 index 000000000..e65c0e531 --- /dev/null +++ b/k8s/consumer/application/identityhub.yaml @@ -0,0 +1,131 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: identityhub + namespace: consumer + labels: + app: identityhub + type: edc-app +spec: + replicas: 1 + selector: + matchLabels: + app: identityhub + template: + metadata: + labels: + app: identityhub + type: edc-app + spec: + containers: + - name: identityhub + image: ghcr.io/eclipse-edc/mvd/identity-hub:latest + imagePullPolicy: Never + envFrom: + - configMapRef: + name: ih-config + ports: + - containerPort: 1044 + name: debug + livenessProbe: + httpGet: + path: /api/check/liveness + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + readinessProbe: + httpGet: + path: /api/check/readiness + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + startupProbe: + httpGet: + path: /api/check/startup + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + +--- +apiVersion: v1 +kind: Service +metadata: + name: identityhub + namespace: consumer +spec: + type: ClusterIP + selector: + app: identityhub + ports: + - port: 7080 + targetPort: 7080 + name: web + - port: 7082 + targetPort: 7082 + name: creds-port + - port: 1044 + targetPort: 1044 + name: debug + - port: 7081 + targetPort: 7081 + name: identity-api + - port: 7083 + targetPort: 7083 + name: did + - port: 7084 + targetPort: 7084 + name: sts + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: identityhub + namespace: consumer +spec: + parentRefs: + - name: consumer-gateway + kind: Gateway + sectionName: http + hostnames: + - ih.consumer.localhost + rules: + - matches: + - path: + type: PathPrefix + value: /cs + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + backendRefs: + - name: identityhub + port: 7081 + + # DID Route + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: identityhub + port: 7083 \ No newline at end of file diff --git a/k8s/consumer/base/gateway.yaml b/k8s/consumer/base/gateway.yaml new file mode 100644 index 000000000..ebcce40ad --- /dev/null +++ b/k8s/consumer/base/gateway.yaml @@ -0,0 +1,31 @@ +# +# Copyright (c) 2025 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 +# + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: consumer-gateway + namespace: consumer +spec: + gatewayClassName: traefik + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All #or Same or Selector +# kinds: +# - kind: HTTPRoute +# group: gateway.networking.k8s.io \ No newline at end of file diff --git a/k8s/consumer/base/namespace.yaml b/k8s/consumer/base/namespace.yaml new file mode 100644 index 000000000..ed98e925d --- /dev/null +++ b/k8s/consumer/base/namespace.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: v1 +kind: Namespace +metadata: + name: consumer diff --git a/k8s/consumer/base/postgres.yaml b/k8s/consumer/base/postgres.yaml new file mode 100644 index 000000000..d061205de --- /dev/null +++ b/k8s/consumer/base/postgres.yaml @@ -0,0 +1,83 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: consumer + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + platform: edcv + type: edc-infra + spec: + containers: + - name: postgres + image: postgres:17.7-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: "controlplane" + - name: POSTGRES_USER + value: "cp" + - name: POSTGRES_PASSWORD + value: "cp" + volumeMounts: + - name: init-script + mountPath: /docker-entrypoint-initdb.d + volumes: + - name: init-script + configMap: + name: postgres-init +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: consumer +spec: + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init + namespace: consumer +data: + init.sql: | + CREATE DATABASE identityhub; + CREATE USER ih WITH PASSWORD 'ih'; + GRANT ALL PRIVILEGES ON DATABASE identityhub TO ih; + \c identityhub + GRANT ALL ON SCHEMA public TO ih; + + CREATE DATABASE dataplane; + CREATE USER dp WITH PASSWORD 'dp'; + GRANT ALL PRIVILEGES ON DATABASE dataplane TO dp; + \c dataplane + GRANT ALL ON SCHEMA public TO dp; \ No newline at end of file diff --git a/k8s/consumer/base/vault.yaml b/k8s/consumer/base/vault.yaml new file mode 100644 index 000000000..bf85b6e3b --- /dev/null +++ b/k8s/consumer/base/vault.yaml @@ -0,0 +1,210 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vault + namespace: consumer + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: vault + template: + metadata: + labels: + app: vault + type: edc-infra + spec: + containers: + - name: vault + image: hashicorp/vault:latest + ports: + - containerPort: 8200 + env: + - name: VAULT_DEV_ROOT_TOKEN_ID + value: "root" + - name: VAULT_DEV_LISTEN_ADDRESS + value: "0.0.0.0:8200" + args: + - "server" + - "-dev" + securityContext: + capabilities: + add: + - IPC_LOCK + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vault-auth + namespace: consumer + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: vault-bootstrap + namespace: consumer +spec: + backoffLimit: 10 + template: + metadata: + labels: + type: edc-job + spec: + serviceAccountName: vault-auth + containers: + - name: vault-cli + image: hashicorp/vault:latest + env: + - name: VAULT_ADDR + value: "http://vault.consumer.svc.cluster.local:8200" + - name: VAULT_TOKEN + value: "root" + command: [ "sh", "-ec" ] + args: + - | + # Wait for vault to be ready + echo "Waiting for Vault to be ready..." + until vault status > /dev/null 2>&1; do + echo "Vault not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Vault is ready!" + + # Wait for Keycloak to be ready + echo "Waiting for Keycloak to be ready..." + until wget -q --spider http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/.well-known/openid-configuration > /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + + # Enable JWT auth method + vault auth enable jwt || true + + # Configure JWT auth (example: using Keycloak as JWT backend) + vault write auth/jwt/config \ + jwks_url="http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/protocol/openid-connect/certs" \ + default_role="participant" || { echo "Failed to configure JWT auth"; exit 1; } + + # create mount for participants, each stores their secrets in a subdirectory + vault secrets enable -path=participants -version=2 kv || { echo "Failed to enable secrets engine"; exit 1; } + + # get accessor for entity aliases + ACCESSOR=$(vault auth list | grep 'jwt/' | awk '{print $3}') + if [ -z "$ACCESSOR" ]; then + echo "Failed to get JWT accessor" + exit 1 + fi + echo "Using JWT accessor: $ACCESSOR" + + + # Allow full CRUD + list on the participant's own data path + + cat < /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + containers: + - name: seed-issuerservice + image: curlimages/curl:latest + env: + - name: KC_HOST + value: "http://keycloak.mvd-common.svc.cluster.local:8080" + - name: ISSUER_CLIENT_ID + value: "issuer" + - name: ISSUER_CLIENT_SECRET + value: "issuer-secret" + command: + - sh + - -c + - | + set -e + + echo "================================================" + echo "Step 1: Create Vault Access Token (Issuer)" + echo "================================================" + + # Get Keycloak admin token + KC_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/master/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "username=admin" \ + -d "password=admin" \ + -d "client_id=admin-cli" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$KC_TOKEN" ]; then + echo "Failed to get Keycloak admin token" + exit 1 + fi + + # Create Keycloak client for Vault access + echo "Creating Vault Access Client" + if curl -sf -X POST "${KC_HOST}/admin/realms/mvd/clients" \ + -H "Authorization: Bearer ${KC_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "clientId": "'"${ISSUER_CLIENT_ID}"'", + "name": "Issuer Client", + "description": "Client for Vault Access (Issuer)", + "enabled": true, + "secret": "'"${ISSUER_CLIENT_SECRET}"'", + "protocol": "openid-connect", + "publicClient": false, + "serviceAccountsEnabled": true, + "standardFlowEnabled": false, + "directAccessGrantsEnabled": false, + "fullScopeAllowed": true, + "protocolMappers": [ + { + "name": "participantContextId", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "claim.name": "participant_context_id", + "claim.value": "issuer", + "jsonType.label": "String", + "access.token.claim": "true", + "id.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "name": "role", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "claim.name": "role", + "claim.value": "participant", + "jsonType.label": "String", + "access.token.claim": "true", + "id.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }'; then + echo "✓ Vault Access Token created" + else + echo "⚠ Vault Access Client creation failed (may already exist)" + fi + + echo "" + echo "================================================" + echo "Step 2: Create Issuer Tenant in IssuerService" + echo "================================================" + + # Get provisioner token + PROVISIONER_TOKEN=$(curl -sfv -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=provisioner" \ + -d "client_secret=provisioner-secret" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$PROVISIONER_TOKEN" ]; then + echo "Failed to get provisioner token" + exit 1 + fi + + # Create issuer tenant + TENANT_RESPONSE=$(curl -sfv -X POST "http://issuerservice.issuer.svc.cluster.local:10015/api/identity/v1alpha/participants" \ + -H "Authorization: Bearer ${PROVISIONER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "roles": ["admin"], + "serviceEndpoints": [ + { + "type": "IssuerService", + "serviceEndpoint": "http://issuerservice.issuer.svc.cluster.local:10012/api/issuance/v1alpha/participants/issuer", + "id": "issuer-service-1" + } + ], + "active": true, + "participantContextId": "issuer", + "did": "did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer", + "key": { + "keyId": "did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer#key-1", + "privateKeyAlias": "did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer#key-1", + "keyGeneratorParams": { + "algorithm": "EdDSA" + } + }, + "additionalProperties": { + "edc.vault.hashicorp.config": { + "credentials": { + "clientId": "'"${ISSUER_CLIENT_ID}"'", + "clientSecret": "'"${ISSUER_CLIENT_SECRET}"'", + "tokenUrl": "http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/protocol/openid-connect/token" + }, + "config": { + "secretPath": "v1/participants", + "folderPath": "'"${ISSUER_CLIENT_ID}"'", + "vaultUrl": "http://vault.issuer.svc.cluster.local:8200" + } + } + } + }') + + echo "✓ Issuer tenant created" + + echo "" + echo "================================================" + echo "Step 3: Create AttestationDefinitions" + echo "================================================" + + # Get issuer token + ISSUER_TOKEN=$(curl -sfv -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=issuer" \ + -d "client_secret=issuer-secret" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$ISSUER_TOKEN" ]; then + echo "Failed to get issuer token" + exit 1 + fi + + # Create attestation definitions + echo "Creating Membership AttestationDefinition" + curl -sfS -w "\nHTTP_STATUS:%{http_code}\n" -X POST "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha/participants/issuer/attestations" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "attestationType": "membership", + "configuration": {}, + "id": "membership-attestation-def-1" + }' + + echo "Creating Manufacturer AttestationDefinition" + curl -sfS -w "\nHTTP_STATUS:%{http_code}\n" -X POST "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha/participants/issuer/attestations" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "attestationType": "manufacturer", + "configuration": {}, + "id": "manufacturer-attestation-def-1" + }' + + echo "✓ AttestationDefinitions created" + + echo "" + echo "================================================" + echo "Step 4: Create CredentialDefinitions" + echo "================================================" + + # Create credential definitions + echo "Creating Membership CredentialDefinition" + curl -sfS -w "\nHTTP_STATUS:%{http_code}\n" -X POST "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha/participants/issuer/credentialdefinitions" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "attestations": ["membership-attestation-def-1"], + "credentialType": "MembershipCredential", + "id": "membership-credential-def", + "jsonSchema": "{}", + "jsonSchemaUrl": "https://example.com/schema/membership-credential.json", + "mappings": [ + { + "input": "membership", + "output": "credentialSubject.membership", + "required": true + }, + { + "input": "membershipType", + "output": "credentialSubject.membershipType", + "required": "true" + }, + { + "input": "membershipStartDate", + "output": "credentialSubject.membershipStartDate", + "required": true + } + ], + "rules": [], + "format": "VC1_0_JWT", + "validity": "604800" + }' + + echo "Creating Manufacturer CredentialDefinition" + curl -sfS -w "\nHTTP_STATUS:%{http_code}\n" -X POST "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha/participants/issuer/credentialdefinitions" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "attestations": ["manufacturer-attestation-def-1"], + "credentialType": "ManufacturerCredential", + "id": "manufacturer-credential-def", + "jsonSchema": "{}", + "jsonSchemaUrl": "https://example.com/schema/manufacturer-credential.json", + "mappings": [ + { + "input": "contractVersion", + "output": "credentialSubject.contractVersion", + "required": true + }, + { + "input": "component_types", + "output": "credentialSubject.part_types", + "required": "true" + }, + { + "input": "since", + "output": "credentialSubject.since", + "required": true + } + ], + "rules": [], + "format": "VC1_0_JWT", + "validity": "604800" + }' + + echo "✓ CredentialDefinition created" + echo "" + echo "================================================" + echo "IssuerService seeding completed successfully!" + echo "================================================" diff --git a/k8s/issuer/application/issuerservice.yaml b/k8s/issuer/application/issuerservice.yaml new file mode 100644 index 000000000..6a0a57905 --- /dev/null +++ b/k8s/issuer/application/issuerservice.yaml @@ -0,0 +1,155 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: issuerservice + namespace: issuer + labels: + app: issuerservice + type: edc-app +spec: + replicas: 1 + selector: + matchLabels: + app: issuerservice + template: + metadata: + name: issuerservice + labels: + app: issuerservice + type: edc-app + spec: + containers: + - name: issuerservice + image: ghcr.io/eclipse-edc/mvd/issuerservice:latest + imagePullPolicy: Never + ports: + - containerPort: 80 + protocol: TCP + envFrom: + - configMapRef: { name: issuerservice-config } + livenessProbe: + httpGet: + path: /api/check/liveness + port: 10010 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + readinessProbe: + httpGet: + path: /api/check/readiness + port: 10010 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + startupProbe: + httpGet: + path: /api/check/startup + port: 10010 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + restartPolicy: Always + + +--- +apiVersion: v1 +kind: Service +metadata: + name: issuerservice + namespace: issuer +spec: + type: ClusterIP + selector: + app: issuerservice + ports: + - port: 10010 + targetPort: 10010 + name: web + - port: 10011 + targetPort: 10011 + name: sts + - port: 10012 + targetPort: 10012 + name: issuance + - port: 10013 + targetPort: 10013 + name: issueradmin + - port: 10015 + targetPort: 10015 + name: identity + - port: 10016 + targetPort: 10016 + name: did + - port: 9999 + targetPort: 9999 + name: statuslist + + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: issuerservice + namespace: issuer +spec: + parentRefs: + - name: edcv-gateway + kind: Gateway + sectionName: http + hostnames: + - issuer.localhost + rules: + # Issuer Admin API + - matches: + - path: + type: PathPrefix + value: /admin + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + backendRefs: + - name: issuerservice + port: 10013 + weight: 1 + + # Credential Service API + - matches: + - path: + type: PathPrefix + value: /cs + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + backendRefs: + - name: issuerservice + port: 10015 + weight: 1 + + # Web DID Resolution endpoint + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: issuerservice + port: 10016 + weight: 1 \ No newline at end of file diff --git a/k8s/issuer/base/gateway.yaml b/k8s/issuer/base/gateway.yaml new file mode 100644 index 000000000..1d17b316a --- /dev/null +++ b/k8s/issuer/base/gateway.yaml @@ -0,0 +1,31 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: issuer-gateway + namespace: issuer +spec: + gatewayClassName: traefik + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All #or Same or Selector +# kinds: +# - kind: HTTPRoute +# group: gateway.networking.k8s.io \ No newline at end of file diff --git a/k8s/issuer/base/namespace.yaml b/k8s/issuer/base/namespace.yaml new file mode 100644 index 000000000..e8b967f3f --- /dev/null +++ b/k8s/issuer/base/namespace.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: v1 +kind: Namespace +metadata: + name: issuer diff --git a/k8s/issuer/base/postgres.yaml b/k8s/issuer/base/postgres.yaml new file mode 100644 index 000000000..0da789428 --- /dev/null +++ b/k8s/issuer/base/postgres.yaml @@ -0,0 +1,81 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: issuer + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + platform: edcv + type: edc-infra + spec: + containers: + - name: postgres + image: postgres:17.7-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: "issuerservice" + - name: POSTGRES_USER + value: "issuer" + - name: POSTGRES_PASSWORD + value: "issuer" + volumeMounts: + - name: init-script + mountPath: /docker-entrypoint-initdb.d + volumes: + - name: init-script + configMap: + name: postgres-init +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: issuer +spec: + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init + namespace: issuer +data: + init.sql: | + GRANT ALL PRIVILEGES ON DATABASE issuerservice TO issuer; + \c issuerservice + GRANT ALL ON SCHEMA public TO issuer; + + CREATE DATABASE keycloak; + CREATE USER kc WITH PASSWORD 'kc'; + GRANT ALL PRIVILEGES ON DATABASE keycloak TO kc; + \c keycloak + GRANT ALL ON SCHEMA public TO kc; \ No newline at end of file diff --git a/k8s/issuer/base/vault.yaml b/k8s/issuer/base/vault.yaml new file mode 100644 index 000000000..c1416a6c3 --- /dev/null +++ b/k8s/issuer/base/vault.yaml @@ -0,0 +1,211 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vault + namespace: issuer + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: vault + template: + metadata: + labels: + app: vault + type: edc-infra + spec: + containers: + - name: vault + image: hashicorp/vault:latest + ports: + - containerPort: 8200 + env: + - name: VAULT_DEV_ROOT_TOKEN_ID + value: "root" + - name: VAULT_DEV_LISTEN_ADDRESS + value: "0.0.0.0:8200" + args: + - "server" + - "-dev" + securityContext: + capabilities: + add: + - IPC_LOCK + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vault-auth + namespace: issuer + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: vault-bootstrap + namespace: issuer +spec: + backoffLimit: 10 + template: + metadata: + labels: + type: edc-job + spec: + serviceAccountName: vault-auth + containers: + - name: vault-cli + image: hashicorp/vault:latest + env: + - name: VAULT_ADDR + value: "http://vault.issuer.svc.cluster.local:8200" + - name: VAULT_TOKEN + value: "root" + command: [ "sh", "-ec" ] + args: + - | + # Wait for vault to be ready + echo "Waiting for Vault to be ready..." + until vault status > /dev/null 2>&1; do + echo "Vault not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Vault is ready!" + + # Wait for Keycloak to be ready + echo "Waiting for Keycloak to be ready..." + until wget -q --spider http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/.well-known/openid-configuration > /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + + # Enable JWT auth method + vault auth enable jwt || true + + # Configure JWT auth (example: using Keycloak as JWT backend) + vault write auth/jwt/config \ + jwks_url="http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/protocol/openid-connect/certs" \ + default_role="participant" || { echo "Failed to configure JWT auth"; exit 1; } + + # create mount for participants, each stores their secrets in a subdirectory + vault secrets enable -path=participants -version=2 kv || { echo "Failed to enable secrets engine"; exit 1; } + + # get accessor for entity aliases + ACCESSOR=$(vault auth list | grep 'jwt/' | awk '{print $3}') + if [ -z "$ACCESSOR" ]; then + echo "Failed to get JWT accessor" + exit 1 + fi + echo "Using JWT accessor: $ACCESSOR" + + + # Allow full CRUD + list on the participant's own data path + + cat < /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + containers: + + - name: seed-identityhub + image: curlimages/curl:latest + env: + - name: KC_HOST + value: "http://keycloak.mvd-common.svc.cluster.local:8080" + - name: PROVISIONER_CLIENT_ID + value: "provisioner" + - name: PROVISIONER_CLIENT_SECRET + value: "provisioner-secret" + - name: ADMIN_CLIENT_ID + value: "admin" + - name: ADMIN_CLIENT_SECRET + value: "edc-v-admin-secret" + - name: IH_URL + value: "http://identityhub.provider.svc.cluster.local:7081/api/identity/v1alpha/participants/" + - name: PARTICIPANT_DID + value: "did:web:identityhub.provider.svc.cluster.local%3A7083:provider" + - name: PARTICIPANT_ID + value: "provider-participant" + - name: ISSUER_CLIENT_ID + value: "issuer" + - name: ISSUER_CLIENT_SECRET + value: "issuer-secret" + - name: ISSUER_ADMIN_URL + value: "http://issuerservice.issuer.svc.cluster.local:10013/api/admin/v1alpha" + command: + - sh + - -c + - | + set -e + + echo "" + echo "================================================" + echo "Step 1: Create provider Holder in IssuerService" + echo "================================================" + + ISSUER_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${ISSUER_CLIENT_ID}" \ + -d "client_secret=${ISSUER_CLIENT_SECRET}" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$ISSUER_TOKEN" ]; then + echo "Failed to get issuer token" + exit 1 + fi + + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${ISSUER_ADMIN_URL}/participants/issuer/holders" \ + -H "Authorization: Bearer ${ISSUER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"did\": \"${PARTICIPANT_DID}\", + \"holderId\": \"${PARTICIPANT_DID}\", + \"name\": \"MVD provider Participant\" + }") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -eq 200 ] || [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ provider holder created in IssuerService" + elif [ "${HTTP_STATUS}" -eq 409 ]; then + echo "⚠ provider holder already exists (HTTP 409), skipping." + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + + echo "================================================" + echo "Step 2: Create provider Participant Context in IdentityHub" + echo "================================================" + + PROVISIONER_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${PROVISIONER_CLIENT_ID}" \ + -d "client_secret=${PROVISIONER_CLIENT_SECRET}" \ + -d "scope=issuer-admin-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$PROVISIONER_TOKEN" ]; then + echo "Failed to get issuer token" + exit 1 + fi + + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${IH_URL}" \ + -H "Authorization: Bearer ${PROVISIONER_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"roles\": [], + \"serviceEndpoints\": [ + { + \"type\": \"CredentialService\", + \"serviceEndpoint\": \"http://identityhub.provider.svc.cluster.local:7082/api/credentials/v1/participants/${PARTICIPANT_ID}\", + \"id\": \"provider-credentialservice-1\" + }, + { + \"type\": \"ProtocolEndpoint\", + \"serviceEndpoint\": \"http://controlplane.provider.svc.cluster.local:8082/api/dsp/2025-1\", + \"id\": \"provider-dsp\" + } + ], + \"active\": true, + \"participantId\": \"${PARTICIPANT_DID}\", + \"participantContextId\": \"${PARTICIPANT_ID}\", + \"did\": \"${PARTICIPANT_DID}\", + \"key\": { + \"keyId\": \"${PARTICIPANT_DID}#key-1\", + \"privateKeyAlias\": \"${PARTICIPANT_DID}#key-1\", + \"keyGeneratorParams\": { + \"algorithm\": \"EC\" + } + } + }") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -eq 200 ] || [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ provider participant context created" + elif [ "${HTTP_STATUS}" -eq 409 ]; then + echo "⚠ provider participant context already exists (HTTP 409), skipping." + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + + echo "================================================" + echo "Step 3: Requesting credential issuance" + echo "================================================" + + ADMIN_TOKEN=$(curl -sf -X POST "${KC_HOST}/realms/mvd/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${ADMIN_CLIENT_ID}" \ + -d "client_secret=${ADMIN_CLIENT_SECRET}" \ + -d "scope=identity-api:write" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') + + if [ -z "$ADMIN_TOKEN" ]; then + echo "Failed to get OAuth2 token" + exit 1 + fi + + HOLDER_PID="credential-request-1" + RESPONSE=$(curl -sS -w "\n%{http_code}" -X POST "${IH_URL}${PARTICIPANT_ID}/credentials/request" \ + -H "Authorization: Bearer ${ADMIN_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"issuerDid\": \"did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer\", + \"holderPid\": \"${HOLDER_PID}\", + \"credentials\": [{ + \"format\": \"VC1_0_JWT\", + \"type\": \"MembershipCredential\", + \"id\": \"membership-credential-def\" + }, + { + \"format\": \"VC1_0_JWT\", + \"type\": \"ManufacturerCredential\", + \"id\": \"manufacturer-credential-def\" + }] + }") + + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + if [ "${HTTP_STATUS}" -eq 201 ]; then + echo "✓ provider participant context created" + else + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${RESPONSE}" + exit 1 + fi + + echo "================================================" + echo "Step 4: Wait for credentials to be issued" + echo "================================================" + + STATUS="" + MAX_RETRIES=30 + RETRY=0 + while [ "${STATUS}" != "ISSUED" ]; do + if [ "${RETRY}" -ge "${MAX_RETRIES}" ]; then + echo "✗ Credentials not ISSUED after ${MAX_RETRIES} attempts" + exit 1 + fi + RESPONSE=$(curl -sS -w "\n%{http_code}" "${IH_URL}${PARTICIPANT_ID}/credentials/request/${HOLDER_PID}" \ + -H "Authorization: Bearer ${ADMIN_TOKEN}") + HTTP_STATUS=$(echo "${RESPONSE}" | tail -n1) + BODY=$(echo "${RESPONSE}" | sed '$d') + if [ "${HTTP_STATUS}" -ne 200 ]; then + echo "✗ Unexpected HTTP status: ${HTTP_STATUS}" + echo "Response body: ${BODY}" + exit 1 + fi + STATUS=$(echo "${BODY}" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p') + echo "Credential status: ${STATUS}" + RETRY=$((RETRY + 1)) + sleep 5 + done + echo "✓ Credentials are ISSUED" + + echo "" + echo "================================================" + echo "IdentityHub seeding completed successfully!" + echo "================================================" \ No newline at end of file diff --git a/k8s/provider/application/identityhub.yaml b/k8s/provider/application/identityhub.yaml new file mode 100644 index 000000000..fdd976020 --- /dev/null +++ b/k8s/provider/application/identityhub.yaml @@ -0,0 +1,131 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: identityhub + namespace: provider + labels: + app: identityhub + type: edc-app +spec: + replicas: 1 + selector: + matchLabels: + app: identityhub + template: + metadata: + labels: + app: identityhub + type: edc-app + spec: + containers: + - name: identityhub + image: ghcr.io/eclipse-edc/mvd/identity-hub:latest + imagePullPolicy: Never + envFrom: + - configMapRef: + name: ih-config + ports: + - containerPort: 1044 + name: debug + livenessProbe: + httpGet: + path: /api/check/liveness + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + readinessProbe: + httpGet: + path: /api/check/readiness + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + startupProbe: + httpGet: + path: /api/check/startup + port: 7080 + failureThreshold: 10 + periodSeconds: 5 + timeoutSeconds: 120 + +--- +apiVersion: v1 +kind: Service +metadata: + name: identityhub + namespace: provider +spec: + type: ClusterIP + selector: + app: identityhub + ports: + - port: 1044 + targetPort: 1044 + name: debug + - port: 7080 + targetPort: 7080 + name: web + - port: 7081 + targetPort: 7081 + name: identity-api + - port: 7082 + targetPort: 7082 + name: creds-port + - port: 7083 + targetPort: 7083 + name: did + - port: 7084 + targetPort: 7084 + name: sts + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: identityhub + namespace: provider +spec: + parentRefs: + - name: provider-gateway + kind: Gateway + sectionName: http + hostnames: + - ih.provider.localhost + rules: + - matches: + - path: + type: PathPrefix + value: /cs + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + backendRefs: + - name: identityhub + port: 7081 + + # DID Route + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: identityhub + port: 7083 \ No newline at end of file diff --git a/k8s/provider/base/gateway.yaml b/k8s/provider/base/gateway.yaml new file mode 100644 index 000000000..061855133 --- /dev/null +++ b/k8s/provider/base/gateway.yaml @@ -0,0 +1,31 @@ +# +# Copyright (c) 2026 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 +# + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: provider-gateway + namespace: provider +spec: + gatewayClassName: traefik + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All #or Same or Selector +# kinds: +# - kind: HTTPRoute +# group: gateway.networking.k8s.io \ No newline at end of file diff --git a/k8s/provider/base/namespace.yaml b/k8s/provider/base/namespace.yaml new file mode 100644 index 000000000..12d6276e0 --- /dev/null +++ b/k8s/provider/base/namespace.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: v1 +kind: Namespace +metadata: + name: provider diff --git a/k8s/provider/base/postgres.yaml b/k8s/provider/base/postgres.yaml new file mode 100644 index 000000000..fa468906a --- /dev/null +++ b/k8s/provider/base/postgres.yaml @@ -0,0 +1,83 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: provider + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + platform: edcv + type: edc-infra + spec: + containers: + - name: postgres + image: postgres:17.7-alpine + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: "controlplane" + - name: POSTGRES_USER + value: "cp" + - name: POSTGRES_PASSWORD + value: "cp" + volumeMounts: + - name: init-script + mountPath: /docker-entrypoint-initdb.d + volumes: + - name: init-script + configMap: + name: postgres-init +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: provider +spec: + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432 + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init + namespace: provider +data: + init.sql: | + CREATE DATABASE identityhub; + CREATE USER ih WITH PASSWORD 'ih'; + GRANT ALL PRIVILEGES ON DATABASE identityhub TO ih; + \c identityhub + GRANT ALL ON SCHEMA public TO ih; + + CREATE DATABASE dataplane; + CREATE USER dp WITH PASSWORD 'dp'; + GRANT ALL PRIVILEGES ON DATABASE dataplane TO dp; + \c dataplane + GRANT ALL ON SCHEMA public TO dp; \ No newline at end of file diff --git a/k8s/provider/base/vault.yaml b/k8s/provider/base/vault.yaml new file mode 100644 index 000000000..e8b2b5e2e --- /dev/null +++ b/k8s/provider/base/vault.yaml @@ -0,0 +1,211 @@ +# +# Copyright (c) 2026 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 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vault + namespace: provider + labels: + type: edc-infra +spec: + replicas: 1 + selector: + matchLabels: + app: vault + template: + metadata: + labels: + app: vault + type: edc-infra + spec: + containers: + - name: vault + image: hashicorp/vault:latest + ports: + - containerPort: 8200 + env: + - name: VAULT_DEV_ROOT_TOKEN_ID + value: "root" + - name: VAULT_DEV_LISTEN_ADDRESS + value: "0.0.0.0:8200" + args: + - "server" + - "-dev" + securityContext: + capabilities: + add: + - IPC_LOCK + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vault-auth + namespace: provider + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: vault-bootstrap + namespace: provider +spec: + backoffLimit: 10 + template: + metadata: + labels: + type: edc-job + spec: + serviceAccountName: vault-auth + containers: + - name: vault-cli + image: hashicorp/vault:latest + env: + - name: VAULT_ADDR + value: "http://vault.provider.svc.cluster.local:8200" + - name: VAULT_TOKEN + value: "root" + command: [ "sh", "-ec" ] + args: + - | + # Wait for vault to be ready + echo "Waiting for Vault to be ready..." + until vault status > /dev/null 2>&1; do + echo "Vault not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Vault is ready!" + + # Wait for Keycloak to be ready + echo "Waiting for Keycloak to be ready..." + until wget -q --spider http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/.well-known/openid-configuration > /dev/null 2>&1; do + echo "Keycloak not ready yet, retrying in 2 seconds..." + sleep 2 + done + echo "Keycloak is ready!" + + # Enable JWT auth method + vault auth enable jwt || true + + # Configure JWT auth (example: using Keycloak as JWT backend) + vault write auth/jwt/config \ + jwks_url="http://keycloak.mvd-common.svc.cluster.local:8080/realms/mvd/protocol/openid-connect/certs" \ + default_role="participant" || { echo "Failed to configure JWT auth"; exit 1; } + + # create mount for participants, each stores their secrets in a subdirectory + vault secrets enable -path=participants -version=2 kv || { echo "Failed to enable secrets engine"; exit 1; } + + # get accessor for entity aliases + ACCESSOR=$(vault auth list | grep 'jwt/' | awk '{print $3}') + if [ -z "$ACCESSOR" ]; then + echo "Failed to get JWT accessor" + exit 1 + fi + echo "Using JWT accessor: $ACCESSOR" + + + # Allow full CRUD + list on the participant's own data path + + cat < f.getName().endsWith(".json")).forEach(p -> { - try { - store.create(objectMapper.readValue(p, VerifiableCredentialResource.class)); - monitor.debug("Stored VC from file '%s'".formatted(p.getAbsolutePath())); - } catch (IOException e) { - monitor.severe("Error storing VC", e); - } - }); - } -} diff --git a/launchers/identity-hub/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/launchers/identity-hub/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 5e7628e85..000000000 --- a/launchers/identity-hub/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,15 +0,0 @@ -# -# 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 -# -# - -org.eclipse.edc.demo.dcp.ih.IdentityHubExtension \ No newline at end of file diff --git a/launchers/issuerservice/build.gradle.kts b/launchers/issuerservice/build.gradle.kts index 8a1126053..785a25f9b 100644 --- a/launchers/issuerservice/build.gradle.kts +++ b/launchers/issuerservice/build.gradle.kts @@ -21,15 +21,13 @@ plugins { dependencies { implementation(libs.edc.issuance.spi) // for seeding the attestations - runtimeOnly(project(":extensions:superuser-seed")) runtimeOnly(libs.edc.bom.issuerservice) runtimeOnly(libs.edc.ih.api.did) runtimeOnly(libs.edc.ih.api.participants) - if (project.properties.getOrDefault("persistence", "false") == "true") { - runtimeOnly(libs.edc.vault.hashicorp) - runtimeOnly(libs.edc.bom.issuerservice.sql) - println("This runtime compiles with a remote STS client, Hashicorp Vault and PostgreSQL. You will need properly configured Postgres and HCV instances.") - } + runtimeOnly(libs.edc.vault.hashicorp) + runtimeOnly(libs.edc.bom.issuerservice.sql) + runtimeOnly(libs.edc.core.participantcontext.config) + runtimeOnly(libs.edc.store.participantcontext.config.sql) } tasks.shadowJar { diff --git a/launchers/issuerservice/src/main/docker/Dockerfile b/launchers/issuerservice/src/main/docker/Dockerfile index 7d81d066e..b903209ef 100644 --- a/launchers/issuerservice/src/main/docker/Dockerfile +++ b/launchers/issuerservice/src/main/docker/Dockerfile @@ -14,9 +14,6 @@ COPY ${JAR} issuerservice.jar EXPOSE 8188 -ENV WEB_HTTP_PORT="8080" -ENV WEB_HTTP_PATH="/api" - HEALTHCHECK --interval=5s --timeout=5s --retries=10 CMD curl --fail http://localhost:8080/api/check/health # Use "exec" for graceful termination (SIGINT) to reach JVM. diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSource.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSource.java similarity index 93% rename from launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSource.java rename to launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSource.java index e3dd3defb..159819a16 100644 --- a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSource.java +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSource.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.issuerservice.seed.attestation; +package org.eclipse.edc.issuerservice.seed.attestation.demo; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationContext; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSourceFactory.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSourceFactory.java similarity index 93% rename from launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSourceFactory.java rename to launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSourceFactory.java index 284d87e5d..84768293a 100644 --- a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationSourceFactory.java +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationSourceFactory.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.issuerservice.seed.attestation; +package org.eclipse.edc.issuerservice.seed.attestation.demo; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactory; diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationsExtension.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationsExtension.java similarity index 89% rename from launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationsExtension.java rename to launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationsExtension.java index 444dae853..052336003 100644 --- a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestationsExtension.java +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestationsExtension.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.issuerservice.seed.attestation; +package org.eclipse.edc.issuerservice.seed.attestation.demo; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationDefinitionValidatorRegistry; import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactoryRegistry; @@ -21,7 +21,7 @@ import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import static org.eclipse.edc.issuerservice.seed.attestation.DemoAttestationsExtension.NAME; +import static org.eclipse.edc.issuerservice.seed.attestation.demo.DemoAttestationsExtension.NAME; @Extension(value = NAME) diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestatonSourceValidator.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestatonSourceValidator.java similarity index 92% rename from launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestatonSourceValidator.java rename to launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestatonSourceValidator.java index 4d6b85d6a..1a2c37365 100644 --- a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/DemoAttestatonSourceValidator.java +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/demo/DemoAttestatonSourceValidator.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.issuerservice.seed.attestation; +package org.eclipse.edc.issuerservice.seed.attestation.demo; import org.eclipse.edc.issuerservice.spi.issuance.model.AttestationDefinition; import org.eclipse.edc.validator.spi.ValidationResult; diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationExtension.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationExtension.java new file mode 100644 index 000000000..439cb13c9 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationExtension.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.manufacturer; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationDefinitionValidatorRegistry; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactoryRegistry; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; + +import static org.eclipse.edc.issuerservice.seed.attestation.manufacturer.ManufacturerAttestationExtension.NAME; + +@Extension(NAME) +public class ManufacturerAttestationExtension implements ServiceExtension { + public static final String NAME = "Manufacturer Attestations Extension"; + + @Inject + private AttestationSourceFactoryRegistry registry; + + @Inject + private AttestationDefinitionValidatorRegistry validatorRegistry; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + registry.registerFactory("manufacturer", new ManufacturerAttestationSourceFactory()); + validatorRegistry.registerValidator("manufacturer", new ManufacturerAttestationSourceValidator()); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSource.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSource.java new file mode 100644 index 000000000..b659fad83 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSource.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.manufacturer; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationContext; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; +import org.eclipse.edc.spi.result.Result; + +import java.time.Instant; +import java.util.Map; + +public record ManufacturerAttestationSource(Map config) implements AttestationSource { + private static final String DEFAULT_CONTRACT_VERSION = "1.0.0"; + + @Override + public Result> execute(AttestationContext context) { + var contractVersion = config.getOrDefault("contractVersion", DEFAULT_CONTRACT_VERSION); + + return Result.success(Map.of( + "contractVersion", contractVersion, + "component_types", "all", + "since", Instant.now().toString(), + "id", context.participantContextId() + )); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceFactory.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceFactory.java new file mode 100644 index 000000000..29047ce5b --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.manufacturer; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactory; +import org.eclipse.edc.issuerservice.spi.issuance.model.AttestationDefinition; + +public class ManufacturerAttestationSourceFactory implements AttestationSourceFactory { + @Override + public AttestationSource createSource(AttestationDefinition definition) { + var config = definition.getConfiguration(); + return new ManufacturerAttestationSource(config); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceValidator.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceValidator.java new file mode 100644 index 000000000..13518c836 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/manufacturer/ManufacturerAttestationSourceValidator.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.manufacturer; + +import org.eclipse.edc.issuerservice.spi.issuance.model.AttestationDefinition; +import org.eclipse.edc.validator.spi.ValidationResult; +import org.eclipse.edc.validator.spi.Validator; + +public class ManufacturerAttestationSourceValidator implements Validator { + @Override + public ValidationResult validate(AttestationDefinition input) { + return ValidationResult.success(); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSource.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSource.java new file mode 100644 index 000000000..cbfa7f394 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSource.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.membership; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationContext; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; +import org.eclipse.edc.spi.result.Result; + +import java.time.Instant; +import java.util.Map; + +public class MembershipAttestationSource implements AttestationSource { + @Override + public Result> execute(AttestationContext attestationContext) { + return Result.success(Map.of( + "membership", Map.of("since", Instant.now().toString()), + "membershipType", "full-member", + "membershipStartDate", Instant.now().toString(), + "id", attestationContext.participantContextId())); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceFactory.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceFactory.java new file mode 100644 index 000000000..3e2573375 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceFactory.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.membership; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSource; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactory; +import org.eclipse.edc.issuerservice.spi.issuance.model.AttestationDefinition; + +public class MembershipAttestationSourceFactory implements AttestationSourceFactory { + @Override + public AttestationSource createSource(AttestationDefinition definition) { + var config = definition.getConfiguration(); + return new MembershipAttestationSource(); + } + +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceValidator.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceValidator.java new file mode 100644 index 000000000..fd40c41e4 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationSourceValidator.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.membership; + +import org.eclipse.edc.issuerservice.spi.issuance.model.AttestationDefinition; +import org.eclipse.edc.validator.spi.ValidationResult; +import org.eclipse.edc.validator.spi.Validator; + +public class MembershipAttestationSourceValidator implements Validator { + @Override + public ValidationResult validate(AttestationDefinition attestationDefinition) { + return ValidationResult.success(); + } +} diff --git a/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationsExtension.java b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationsExtension.java new file mode 100644 index 000000000..86884aa00 --- /dev/null +++ b/launchers/issuerservice/src/main/java/org/eclipse/edc/issuerservice/seed/attestation/membership/MembershipAttestationsExtension.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 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 + * + */ + +package org.eclipse.edc.issuerservice.seed.attestation.membership; + +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationDefinitionValidatorRegistry; +import org.eclipse.edc.issuerservice.spi.issuance.attestation.AttestationSourceFactoryRegistry; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; + +import static org.eclipse.edc.issuerservice.seed.attestation.membership.MembershipAttestationsExtension.NAME; + + +@Extension(value = NAME) +public class MembershipAttestationsExtension implements ServiceExtension { + + public static final String NAME = "Membership Attestations Extension"; + + @Inject + private AttestationSourceFactoryRegistry registry; + + @Inject + private AttestationDefinitionValidatorRegistry validatorRegistry; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + registry.registerFactory("membership", new MembershipAttestationSourceFactory()); + validatorRegistry.registerValidator("membership", new MembershipAttestationSourceValidator()); + } +} diff --git a/launchers/issuerservice/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/launchers/issuerservice/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index e5057b13a..0c6d46b9a 100644 --- a/launchers/issuerservice/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/launchers/issuerservice/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -11,4 +11,6 @@ # Cofinity-X - initial API and implementation # # -org.eclipse.edc.issuerservice.seed.attestation.DemoAttestationsExtension \ No newline at end of file +org.eclipse.edc.issuerservice.seed.attestation.demo.DemoAttestationsExtension +org.eclipse.edc.issuerservice.seed.attestation.manufacturer.ManufacturerAttestationExtension +org.eclipse.edc.issuerservice.seed.attestation.membership.MembershipAttestationsExtension diff --git a/launchers/runtime-embedded/build.gradle.kts b/launchers/runtime-embedded/build.gradle.kts deleted file mode 100644 index 272a45c97..000000000 --- a/launchers/runtime-embedded/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -* -* 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: -* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - Initial API and Implementation -* -*/ - -plugins { - `java-library` - id("application") - alias(libs.plugins.shadow) -} - -dependencies { - runtimeOnly(project(":launchers:controlplane")) { - // this will remove the RemoteDataPlaneSelectorService - exclude(group = "org.eclipse.edc", "data-plane-selector-client") - } - runtimeOnly(project(":launchers:dataplane")) { - // this will remove the RemoteDataPlaneSelectorService - exclude(group = "org.eclipse.edc", "data-plane-selector-client") - } -} - -tasks.shadowJar { - duplicatesStrategy = DuplicatesStrategy.INCLUDE - mergeServiceFiles() - archiveFileName.set("${project.name}.jar") -} - -application { - mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") -} - -edcBuild { - publish.set(false) -} diff --git a/seed.sh b/seed.sh deleted file mode 100755 index 133170d1e..000000000 --- a/seed.sh +++ /dev/null @@ -1,182 +0,0 @@ -#!/bin/bash - -# -# 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 -# -# - -## This script must be executed when running the dataspace from IntelliJ. Neglecting to do that will render the connectors -## inoperable! - -## Seed asset/policy/contract-def data to both "provider-qna" and "provider-manufacturing" -for url in 'http://127.0.0.1:8191' 'http://127.0.0.1:8291' -do - newman run \ - --folder "Seed" \ - --env-var "HOST=$url" \ - ./deployment/postman/MVD.postman_collection.json > /dev/null -done - -## Seed linked assets to Catalog Server -newman run \ - --folder "Seed Catalog Server" \ - --env-var "HOST=http://127.0.0.1:8091" \ - --env-var "PROVIDER_QNA_DSP_URL=http://localhost:8192" \ - --env-var "PROVIDER_MF_DSP_URL=http://localhost:8292" \ - ./deployment/postman/MVD.postman_collection.json > /dev/null - - -## Seed identity data to identityhubs -API_KEY="c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=" - -# add participant "consumer" -echo -echo -echo "Create consumer participant context in IdentityHub" -PEM_CONSUMER=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' deployment/assets/consumer_public.pem) -DATA_CONSUMER=$(jq -n --arg pem "$PEM_CONSUMER" '{ - "roles":[], - "serviceEndpoints":[ - { - "type": "CredentialService", - "serviceEndpoint": "http://localhost:7081/api/credentials/v1/participants/ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDgz", - "id": "consumer-credentialservice-1" - }, - { - "type": "ProtocolEndpoint", - "serviceEndpoint": "http://localhost:8082/api/dsp", - "id": "consumer-dsp" - } - ], - "active": true, - "participantId": "did:web:localhost%3A7083", - "did": "did:web:localhost%3A7083", - "key":{ - "keyId": "did:web:localhost%3A7083#key-1", - "privateKeyAlias": "key-1", - "publicKeyPem":"\($pem)" - } - }') - -# the consumer runtime will need to have the client_secret in its vault as well, so we store it in a variable -# and use the Secrets API (part of Management API) to insert it. -clientSecret=$(curl -s --location 'http://localhost:7082/api/identity/v1alpha/participants/' \ ---header 'Content-Type: application/json' \ ---header "x-api-key: $API_KEY" \ ---data "$DATA_CONSUMER" | jq -r '.clientSecret') - -# add client secret to the consumer runtime -SECRETS_DATA=$(jq -n --arg secret "$clientSecret" \ -'{ - "@context" : { - "edc" : "https://w3id.org/edc/v0.0.1/ns/" - }, - "@type" : "https://w3id.org/edc/v0.0.1/ns/Secret", - "@id" : "did:web:localhost%3A7083-sts-client-secret", - "https://w3id.org/edc/v0.0.1/ns/value": "\($secret)" -}') - -curl -sL -X POST http://localhost:8081/api/management/v3/secrets -H "x-api-key: password" -H "Content-Type: application/json" -d "$SECRETS_DATA" - -# add participant "provider" -echo -echo -echo "Create provider participant context in IdentityHub" -PEM_PROVIDER=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' deployment/assets/provider_public.pem) -DATA_PROVIDER=$(jq -n --arg pem "$PEM_PROVIDER" '{ - "roles":[], - "serviceEndpoints":[ - { - "type": "CredentialService", - "serviceEndpoint": "http://localhost:7091/api/credentials/v1/participants/ZGlkOndlYjpsb2NhbGhvc3QlM0E3MDkz", - "id": "provider-credentialservice-1" - }, - { - "type": "ProtocolEndpoint", - "serviceEndpoint": "http://localhost:8092/api/dsp", - "id": "provider-catalogserver-dsp" - } - ], - "active": true, - "participantId": "did:web:localhost%3A7093", - "did": "did:web:localhost%3A7093", - "key":{ - "keyId": "did:web:localhost%3A7093#key-1", - "privateKeyAlias": "key-1", - "publicKeyPem":"\($pem)" - } - }') - -# the provider runtime will need to have the client_secret in its vault as well, so we store it in a variable -# and use the Secrets API (part of Management API) to insert it. -clientSecret=$(curl -s --location 'http://localhost:7092/api/identity/v1alpha/participants/' \ ---header 'Content-Type: application/json' \ ---header "x-api-key: $API_KEY" \ ---data "$DATA_PROVIDER" | jq -r '.clientSecret') - -# add client secret to the provider runtimes -SECRETS_DATA=$(jq -n --arg secret "$clientSecret" \ -'{ - "@context" : { - "edc" : "https://w3id.org/edc/v0.0.1/ns/" - }, - "@type" : "https://w3id.org/edc/v0.0.1/ns/Secret", - "@id" : "did:web:localhost%3A7093-sts-client-secret", - "https://w3id.org/edc/v0.0.1/ns/value": "\($secret)" -}') - -curl -sL -X POST http://localhost:8091/api/management/v3/secrets -H "x-api-key: password" -H "Content-Type: application/json" -d "$SECRETS_DATA" -curl -sL -X POST http://localhost:8191/api/management/v3/secrets -H "x-api-key: password" -H "Content-Type: application/json" -d "$SECRETS_DATA" -curl -sL -X POST http://localhost:8291/api/management/v3/secrets -H "x-api-key: password" -H "Content-Type: application/json" -d "$SECRETS_DATA" - -############################################### -# SEED ISSUER SERVICE -############################################### - -echo -echo -echo "Create dataspace issuer" -PEM_ISSUER=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' deployment/assets/issuer_public.pem) -DATA_ISSUER=$(jq -n --arg pem "$PEM_ISSUER" '{ - "roles":["admin"], - "serviceEndpoints":[ - { - "type": "IssuerService", - "serviceEndpoint": "http://localhost:10012/api/issuance/v1alpha/participants/ZGlkOndlYjpsb2NhbGhvc3QlM0ExMDEwMA==", - "id": "issuer-service-1" - } - ], - "active": true, - "participantId": "did:web:localhost%3A10100", - "did": "did:web:localhost%3A10100", - "key":{ - "keyId": "did:web:localhost%3A10100#key-1", - "privateKeyAlias": "key-1", - "keyGeneratorParams":{ - "algorithm": "EdDSA" - } - } - }') - -curl -s --location 'http://localhost:10015/api/identity/v1alpha/participants/' \ ---header 'Content-Type: application/json' \ ---data "$DATA_ISSUER" - -## Seed participant data to the issuer service -newman run \ - --folder "Seed Issuer" \ - --env-var "ISSUER_ADMIN_URL=http://localhost:10013" \ - --env-var "CONSUMER_ID=did:web:localhost%3A7083" \ - --env-var "CONSUMER_NAME=MVD Consumer Participant" \ - --env-var "PROVIDER_ID=did:web:localhost%3A7093" \ - --env-var "PROVIDER_NAME=MVD Provider Participant" \ - ./deployment/postman/MVD.postman_collection.json \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 14941bd15..750069f62 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,17 +25,13 @@ pluginManagement { } rootProject.name = "mvd" -include(":extensions:did-example-resolver") -include(":extensions:catalog-node-resolver") -include(":extensions:dcp-impl") -include(":extensions:superuser-seed") -//include(":tests:performance") include(":tests:end2end") +include(":extensions:data-plane-public-api-v2") +include(":extensions:data-plane-registration") + // launcher modules include(":launchers:identity-hub") include(":launchers:controlplane") include(":launchers:dataplane") -include(":launchers:runtime-embedded") -include(":launchers:catalog-server") include(":launchers:issuerservice") diff --git a/tests/end2end/build.gradle.kts b/tests/end2end/build.gradle.kts index 56713b03c..2781eac85 100644 --- a/tests/end2end/build.gradle.kts +++ b/tests/end2end/build.gradle.kts @@ -23,10 +23,7 @@ dependencies { testImplementation(libs.parsson) testImplementation(libs.restAssured) testImplementation(libs.awaitility) - testImplementation(libs.edc.fc.core) // todo: use 2025 once it is used everywhere - // testImplementation(libs.edc.fc.core2025) - testImplementation(libs.edc.fc.core08) testImplementation(libs.edc.lib.transform) testImplementation(libs.edc.lib.jsonld) testImplementation(libs.edc.controlplane.transform) diff --git a/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/issuance/CredentialIssuanceEndToEndTest.java b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/issuance/CredentialIssuanceEndToEndTest.java index 447f1b9f3..85052d491 100644 --- a/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/issuance/CredentialIssuanceEndToEndTest.java +++ b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/issuance/CredentialIssuanceEndToEndTest.java @@ -20,7 +20,6 @@ import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; -import java.util.Base64; import java.util.List; import java.util.UUID; @@ -38,19 +37,33 @@ @EndToEndTest public class CredentialIssuanceEndToEndTest { - private static final String CONSUMER_IDENTITYHUB_IDENTITY_URL = "http://127.0.0.1/consumer/cs/"; - private static final String PARTICIPANT_CONTEXT_ID = "did:web:consumer-identityhub%3A7083:consumer"; - private static final String ISSUER_DID = "did:web:dataspace-issuer-service%3A10016:issuer"; + private static final String CONSUMER_IDENTITYHUB_IDENTITY_URL = "http://ih.consumer.localhost:8080/cs/"; + private static final String PARTICIPANT_CONTEXT_ID = "consumer-participant"; + private static final String ISSUER_DID = "did:web:issuerservice.issuer.svc.cluster.local%3A10016:issuer"; private static final String HOLDER_PID = UUID.randomUUID().toString(); + private static final String KEYCLOAK_URL = "http://keycloak.localhost:8080"; private static RequestSpecification baseRequest() { return given() - .header("X-Api-Key", "c3VwZXItdXNlcg==.c3VwZXItc2VjcmV0LWtleQo=") + .header("Authorization", "Bearer " + adminToken()) .contentType(JSON) .baseUri(CONSUMER_IDENTITYHUB_IDENTITY_URL) .when(); } + private static String adminToken() { + return given() + .contentType("application/x-www-form-urlencoded") + .formParam("client_id", "admin") + .formParam("client_secret", "edc-v-admin-secret") + .formParam("grant_type", "client_credentials") + .post(KEYCLOAK_URL + "/realms/mvd/protocol/openid-connect/token") + .then() + .log().ifValidationFails() + .statusCode(200) + .extract().jsonPath().getString("access_token"); + } + @Test void makeCredentialRequest_expectCredential() { var location = baseRequest() @@ -59,11 +72,11 @@ void makeCredentialRequest_expectCredential() { "issuerDid": "%s", "holderPid": "%s", "credentials": [ - {"format": "VC1_0_JWT", "type": "FoobarCredential", "id": "demo-credential-def-2"} + {"format": "VC1_0_JWT", "type": "MembershipCredential", "id": "membership-credential-def"} ] } """.formatted(ISSUER_DID, HOLDER_PID)) - .post("/api/identity/v1alpha/participants/%s/credentials/request".formatted(base64(PARTICIPANT_CONTEXT_ID))) + .post("/api/identity/v1alpha/participants/%s/credentials/request".formatted(PARTICIPANT_CONTEXT_ID)) .then() .log().ifValidationFails() .statusCode(201) @@ -78,7 +91,7 @@ void makeCredentialRequest_expectCredential() { .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { baseRequest() - .get("/api/identity/v1alpha/participants/%s/credentials/request/%s".formatted(base64(PARTICIPANT_CONTEXT_ID), requestId)) + .get("/api/identity/v1alpha/participants/%s/credentials/request/%s".formatted(PARTICIPANT_CONTEXT_ID, requestId)) .then() .log().ifValidationFails() .statusCode(200) @@ -91,12 +104,7 @@ void makeCredentialRequest_expectCredential() { .jsonPath() .getList("verifiableCredential.credential.type"); - assertThat(list).anySatisfy(typesList -> assertThat(typesList).containsExactlyInAnyOrder("FoobarCredential", "VerifiableCredential")); - - - } - - private String base64(String input) { - return Base64.getUrlEncoder().encodeToString(input.getBytes()); + assertThat(list).anySatisfy(typesList -> + assertThat(typesList).containsExactlyInAnyOrder("MembershipCredential", "VerifiableCredential")); } } diff --git a/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/CatalogResponse.java b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/CatalogResponse.java new file mode 100644 index 000000000..0c796450b --- /dev/null +++ b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/CatalogResponse.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2026 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 + * + */ + +package org.eclipse.edc.demo.tests.transfer; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CatalogResponse { + + @JsonProperty("@id") + private String id; + + @JsonProperty("participantId") + private String participantId; + + @JsonProperty("dataset") + private List datasets; + + @JsonProperty("service") + private List services; + + public String getId() { + return id; + } + + public String getParticipantId() { + return participantId; + } + + public List getDatasets() { + return datasets; + } + + public List getServices() { + return services; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Dataset { + + @JsonProperty("@id") + private String id; + + @JsonProperty("description") + private String description; + + @JsonProperty("hasPolicy") + private List policies; + + @JsonProperty("distribution") + private List distributions; + + public String getId() { + return id; + } + + public String getDescription() { + return description; + } + + public List getPolicies() { + return policies; + } + + public List getDistributions() { + return distributions; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Offer { + + @JsonProperty("@id") + private String id; + + @JsonProperty("obligation") + private List obligations; + + public String getId() { + return id; + } + + public List getObligations() { + return obligations; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Obligation { + + @JsonProperty("action") + private String action; + + @JsonProperty("constraint") + private List constraints; + + public String getAction() { + return action; + } + + public List getConstraints() { + return constraints; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Constraint { + + @JsonProperty("leftOperand") + private String leftOperand; + + @JsonProperty("operator") + private String operator; + + @JsonProperty("rightOperand") + private String rightOperand; + + public String getLeftOperand() { + return leftOperand; + } + + public String getOperator() { + return operator; + } + + public String getRightOperand() { + return rightOperand; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class DataService { + + @JsonProperty("@id") + private String id; + + @JsonProperty("endpointDescription") + private String endpointDescription; + + @JsonProperty("endpointURL") + private String endpointUrl; + + public String getId() { + return id; + } + + public String getEndpointDescription() { + return endpointDescription; + } + + public String getEndpointUrl() { + return endpointUrl; + } + } +} \ No newline at end of file diff --git a/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/TransferEndToEndTest.java b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/TransferEndToEndTest.java index 0adab1814..e04120b20 100644 --- a/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/TransferEndToEndTest.java +++ b/tests/end2end/src/test/java/org/eclipse/edc/demo/tests/transfer/TransferEndToEndTest.java @@ -14,27 +14,21 @@ package org.eclipse.edc.demo.tests.transfer; +import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.specification.RequestSpecification; import jakarta.json.Json; import jakarta.json.JsonArray; -import org.eclipse.edc.catalog.transform.JsonObjectToCatalogTransformer; -import org.eclipse.edc.catalog.transform.JsonObjectToDataServiceTransformer; -import org.eclipse.edc.catalog.transform.JsonObjectToDatasetTransformer; -import org.eclipse.edc.catalog.transform.JsonObjectToDistributionTransformer; +import jakarta.json.JsonObject; import org.eclipse.edc.connector.controlplane.catalog.spi.Catalog; import org.eclipse.edc.connector.controlplane.catalog.spi.Dataset; -import org.eclipse.edc.connector.controlplane.transform.odrl.OdrlTransformersFactory; -import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.junit.testfixtures.TestUtils; -import org.eclipse.edc.participant.spi.ParticipantIdMapper; import org.eclipse.edc.spi.monitor.ConsoleMonitor; import org.eclipse.edc.transform.TypeTransformerRegistryImpl; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -46,7 +40,6 @@ import static org.awaitility.Awaitility.await; import static org.eclipse.edc.demo.tests.TestConstants.TEST_POLL_DELAY; import static org.eclipse.edc.demo.tests.TestConstants.TEST_TIMEOUT_DURATION; -import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; /** * This test is designed to run against an MVD deployed in a Kubernetes cluster, with an active ingress controller. @@ -55,19 +48,20 @@ @EndToEndTest public class TransferEndToEndTest { // Management API base URL of the consumer connector, goes through Ingress controller - private static final String CONSUMER_MANAGEMENT_URL = "http://127.0.0.1/consumer/cp"; + private static final String CONSUMER_MANAGEMENT_URL = "http://cp.consumer.localhost:8080"; // Catalog Query API URL of the consumer connector, goes through ingress controller private static final String CONSUMER_CATALOG_URL = "http://127.0.0.1/consumer/fc"; // DSP service URL of the provider, not reachable outside the cluster - private static final String PROVIDER_DSP_URL = "http://provider-qna-controlplane:8082"; + private static final String PROVIDER_DSP_URL = "http://controlplane.provider.svc.cluster.local:8082/api/dsp/2025-1"; // DID of the provider company - private static final String PROVIDER_ID = "did:web:provider-identityhub%3A7083:provider"; + private static final String PROVIDER_ID = "did:web:identityhub.provider.svc.cluster.local%3A7083:provider"; // public API endpoint of the provider-qna connector, goes through the ingress controller - private static final String PROVIDER_PUBLIC_URL = "http://127.0.0.1/provider-qna/public"; - private static final String PROVIDER_MANAGEMENT_URL = "http://127.0.0.1/provider-qna/cp"; + private static final String PROVIDER_PUBLIC_URL = "http://dp.provider.localhost:8080/public"; + private static final String PROVIDER_MANAGEMENT_URL = "http://cp.provider.localhost:8080"; private final TypeTransformerRegistry transformerRegistry = new TypeTransformerRegistryImpl(); private final JsonLd jsonLd = new TitaniumJsonLd(new ConsoleMonitor()); + private final ObjectMapper objectMapper = new ObjectMapper(); private static RequestSpecification baseRequest() { return given() @@ -76,27 +70,6 @@ private static RequestSpecification baseRequest() { .when(); } - @BeforeEach - void setup() { - var typeManager = new JacksonTypeManager(); - transformerRegistry.register(new JsonObjectToCatalogTransformer()); - transformerRegistry.register(new JsonObjectToDatasetTransformer()); - transformerRegistry.register(new JsonObjectToDataServiceTransformer()); - transformerRegistry.register(new JsonObjectToDistributionTransformer()); - transformerRegistry.register(new JsonValueToGenericTypeTransformer(typeManager, JSON_LD)); - OdrlTransformersFactory.jsonObjectToOdrlTransformers(new ParticipantIdMapper() { - @Override - public String toIri(String s) { - return s; - } - - @Override - public String fromIri(String s) { - return s; - } - }).forEach(transformerRegistry::register); - } - @DisplayName("Tests a successful End-to-End contract negotiation and data transfer") @Test void transferData_hasPermission_shouldTransferData() { @@ -106,52 +79,45 @@ void transferData_hasPermission_shouldTransferData() { .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { var jp = baseRequest() - .get(PROVIDER_MANAGEMENT_URL + "/api/management/v3/dataplanes") + .get(PROVIDER_MANAGEMENT_URL + "/api/mgmt/v4beta/dataplanes") .then() .statusCode(200) .log().ifValidationFails() .extract().body().jsonPath(); var state = jp.getString("state"); - assertThat(state).isEqualTo("[AVAILABLE]"); + assertThat(state).isEqualTo("[REGISTERED]"); }); System.out.println("Provider dataplane is online, fetching catalog"); - var emptyQueryBody = Json.createObjectBuilder() - .add("@context", Json.createObjectBuilder().add("edc", "https://w3id.org/edc/v0.0.1/ns/")) - .add("@type", "QuerySpec") + var catalogRequestBody = Json.createObjectBuilder() + .add("@context", Json.createObjectBuilder().add("edc", "https://w3id.org/edc/connector/management/v2")) + .add("@type", "CatalogRequest") + .add("counterPartyId", PROVIDER_ID) + .add("counterPartyAddress", "http://controlplane.provider.svc.cluster.local:8082/api/dsp/2025-1") + .add("protocol", "dataspace-protocol-http:2025-1") + .add("querySpec", Json.createObjectBuilder().build()) .build(); var offerId = new AtomicReference(); // get catalog, extract offer ID await().atMost(TEST_TIMEOUT_DURATION) .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { - var jo = baseRequest() - .body(emptyQueryBody) - .post(CONSUMER_CATALOG_URL + "/api/catalog/v1alpha/catalog/query") + var res = baseRequest() + .body(catalogRequestBody) + .post(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/catalog/request") .then() - .log().ifError() + .log().ifValidationFails() .statusCode(200) - .extract().body().as(JsonArray.class); - - var offerIdsFiltered = jo.stream().map(jv -> { - - var expanded = jsonLd.expand(jv.asJsonObject()).orElseThrow(f -> new AssertionError(f.getFailureDetail())); - var cat = transformerRegistry.transform(expanded, Catalog.class).orElseThrow(f -> new AssertionError(f.getFailureDetail())); - return cat.getDatasets().stream().filter(ds -> ds instanceof Catalog) // filter for CatalogAssets - .map(ds -> (Catalog) ds) - .filter(sc -> sc.getDataServices().stream().anyMatch(dataService -> dataService.getEndpointUrl().contains("provider-qna"))) // filter for assets from the Q&A Provider - .flatMap(c -> c.getDatasets().stream()) - .filter(dataset -> dataset.getId().equals("asset-1")) // filter for the asset we're allowed to negotiate - .map(Dataset::getOffers) - .map(offers -> offers.keySet().iterator().next()) - .findFirst() - .orElse(null); - }).toList(); - assertThat(offerIdsFiltered).hasSize(1).doesNotContainNull(); - var oid = offerIdsFiltered.get(0); - assertThat(oid).isNotNull(); + .extract().body().as(JsonObject.class); + + // todo: parse asset offer ID, parse JSON + var cat = objectMapper.readValue(res.toString(), CatalogResponse.class); + var oid = cat.getDatasets().stream().filter(ds -> ds.getId().equals("asset-2")) + .flatMap(ds -> ds.getPolicies().stream()) + .map(CatalogResponse.Offer::getId) + .findFirst().orElseThrow(() -> new AssertionError("No offer found for asset-2")); offerId.set(oid); }); @@ -164,7 +130,7 @@ void transferData_hasPermission_shouldTransferData() { .replace("{{OFFER_ID}}", offerId.get()); var negotiationId = baseRequest() .body(negotiationRequest) - .post(CONSUMER_MANAGEMENT_URL + "/api/management/v3/contractnegotiations") + .post(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/contractnegotiations") .then() .log().ifError() .statusCode(200) @@ -178,7 +144,7 @@ void transferData_hasPermission_shouldTransferData() { .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { var jp = baseRequest() - .get(CONSUMER_MANAGEMENT_URL + "/api/management/v3/contractnegotiations/" + negotiationId) + .get(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/contractnegotiations/" + negotiationId) .then() .statusCode(200) .extract().body().jsonPath(); @@ -196,7 +162,7 @@ void transferData_hasPermission_shouldTransferData() { var transferProcessId = baseRequest() .body(tpRequest) - .post(CONSUMER_MANAGEMENT_URL + "/api/management/v3/transferprocesses") + .post(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/transferprocesses") .then() .log().ifError() .statusCode(200) @@ -208,8 +174,7 @@ void transferData_hasPermission_shouldTransferData() { .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { var jp = baseRequest() - .body(emptyQueryBody) - .post(CONSUMER_MANAGEMENT_URL + "/api/management/v3/transferprocesses/request") + .get(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/transferprocesses/%s/state".formatted(transferProcessId)) .then() .statusCode(200) .extract().body().jsonPath(); @@ -225,7 +190,7 @@ void transferData_hasPermission_shouldTransferData() { .pollDelay(TEST_POLL_DELAY) .untilAsserted(() -> { var jp = baseRequest() - .get(CONSUMER_MANAGEMENT_URL + "/api/management/v3/edrs/%s/dataaddress".formatted(transferProcessId)) + .get(CONSUMER_MANAGEMENT_URL + "/api/mgmt/v4beta/edrs/%s/dataaddress".formatted(transferProcessId)) .then() .log().ifValidationFails() .statusCode(200) @@ -251,6 +216,7 @@ void transferData_hasPermission_shouldTransferData() { assertThat(response).isNotEmpty(); } + @Disabled @DisplayName("Tests a failing End-to-End contract negotiation because of an unfulfilled policy") @Test void transferData_doesNotHavePermission_shouldTerminate() { diff --git a/tests/end2end/src/test/resources/negotiation-request.json b/tests/end2end/src/test/resources/negotiation-request.json index 44c45d01a..7e11ef2d0 100644 --- a/tests/end2end/src/test/resources/negotiation-request.json +++ b/tests/end2end/src/test/resources/negotiation-request.json @@ -1,11 +1,11 @@ { "@context": [ - "https://w3id.org/edc/connector/management/v0.0.1" + "https://w3id.org/edc/connector/management/v2" ], "@type": "ContractRequest", - "counterPartyAddress": "{{PROVIDER_DSP_URL}}/api/dsp", + "counterPartyAddress": "{{PROVIDER_DSP_URL}}", "counterPartyId": "{{PROVIDER_ID}}", - "protocol": "dataspace-protocol-http", + "protocol": "dataspace-protocol-http:2025-1", "policy": { "@type": "Offer", "@id": "{{OFFER_ID}}", @@ -15,12 +15,12 @@ "obligation": { "action": "use", "constraint": { - "leftOperand": "DataAccess.level", + "leftOperand": "ManufacturerCredential", "operator": "eq", - "rightOperand": "processing" + "rightOperand": "active" } }, - "target": "asset-1" + "target": "asset-2" }, "callbackAddresses": [] } \ No newline at end of file diff --git a/tests/end2end/src/test/resources/transfer-request.json b/tests/end2end/src/test/resources/transfer-request.json index aea7297b4..f4806ce21 100644 --- a/tests/end2end/src/test/resources/transfer-request.json +++ b/tests/end2end/src/test/resources/transfer-request.json @@ -2,13 +2,14 @@ "@context": { "odrl": "http://www.w3.org/ns/odrl/2/" }, + "@type": "TransferRequest", "assetId": "asset-1", - "counterPartyAddress": "{{PROVIDER_DSP_URL}}/api/dsp", + "counterPartyAddress": "{{PROVIDER_DSP_URL}}", "connectorId": "{{PROVIDER_ID}}", "contractId": "{{CONTRACT_ID}}", "dataDestination": { "type": "HttpProxy" }, - "protocol": "dataspace-protocol-http", + "protocol": "dataspace-protocol-http:2025-1", "transferType": "HttpData-PULL" } \ No newline at end of file diff --git a/values.yaml b/values.yaml new file mode 100644 index 000000000..2ca8b02ca --- /dev/null +++ b/values.yaml @@ -0,0 +1,46 @@ +# +# Copyright (c) 2025 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 +# + +logs: + access: + enabled: true + format: json + fields: + general: + # full field list + # https://doc.traefik.io/traefik/reference/install-configuration/observability/logs-and-accesslogs/#json-format-fields + names: + RouterName: drop +ports: + web: + port: 80 + websecure: + port: 443 + exposedPort: 443 + +# we enable gateway-api features +providers: + kubernetesGateway: + enabled: true + experimentalChannel: true + kubernetesCRD: + # -- Load Kubernetes IngressRoute provider + enabled: true + +# we disable gateway-api defaults because we want to provide our own +gatewayClass: + enabled: false + +# we disable gateway-api defaults because we want to provide our own +gateway: + enabled: false \ No newline at end of file