Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
EMAIL=<YOUR-VALID-EMAIL>
DOMAIN=<YOUR-DOMAIN>
ISSUER_DOMAIN=<YOUR_ISSUER_DOMAIN>

DOMAIN_MISSING_MESSAGE="Domain must be set in the .env file"

VAULT_TOKEN=<YOUR-VAULT_TOKEN>
135 changes: 135 additions & 0 deletions edc-controlplane/edc-controlplane-construct-x/local-single/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
## Prerequisites

Make sure you have...
- ...docker installed on your machine (recommended: version>25.0.4)
- ...a domain for your IP-address
- ...copied [.env.example](./.env.example) to `.env` and changed the secrets
- ...the necessary docker images from [controlplane](https://github.com/project-construct-x/constructx-edc/pkgs/container/con-x-controlplane-postgresql-hashicorp-vault), [dataplane](https://github.com/project-construct-x/constructx-edc/pkgs/container/con-x-dataplane-postgresql-hashicorp-vault), [wallet](https://github.com/project-construct-x/wallet/pkgs/container/wallet)
- wallet
- controlplane
- dataplane
- Postgres DB
- HashiCorp Vault


The domain and a valid email must be set in the [.env-file](./.env):

```
EMAIL=<YOUR-VALID-EMAIL>
DOMAIN=<YOUR-DOMAIN>
ISSUER_DOMAIN=<YOUR_ISSUER_DOMAIN>
```


## Steps
### Traefik

#### Create Network

First run the command `docker network create proxy`

Sample output:
```
35c1364363795...
```

#### Start Traefik

Run the following command from the current folder to start the traefik container:
```bash
docker compose -f ./traefik/traefik-compose.yaml --env-file ./.env up -d
```

Wait 30 seconds before proceeding with the next steps.

Sample output:
```
[+] Running 1/1
✔ Container traefik Created
```

## EDC in Memory

### Start EDC-Services in Memory

Run `docker compose -f ./local/docker-compose-memory.yaml --env-file ./.env up -d`

Sample output:
```
[+] Running 7/7
✔ Network network Created
✔ vault Healthy
✔ postgres Healthy
✔ idhub Created
✔ vault-init Exited
✔ dataplane Created
✔ controlplane Created
```


### Stop and Remove in Memory

1. `docker compose -f ./traefik/traefik-compose.yaml down`
2. `docker compose -f ./local/docker-compose-memory.yaml --env-file ./.env down -v`
3. `docker network rm proxy`

## EDC

### Initialize Vault (only once)

`docker compose -f ./local/docker-compose.yaml --env-file ./.env up shared-vault -d`

#### Set the appropriate ownership
The default Vault user inside the Container has the UID `100`.

`sudo chown -R 100:100 ./local/vault/data`

#### Open a Terminal inside the Container

`docker exec -it shared-vault sh`

Run the following command inside the vault container:

`vault operator init -key-shares=1 -key-threshold=1`

Save the unseal key and the root token. Set the root token in the [.env](./.env) file:

```VAULT_TOKEN=<YOUR-VAULT_TOKEN>```

#### Unseal Vault
Run the following command with the unseal key from the previous step.

`vault operator unseal <unseal-key>`

#### Log in with the root token

`export VAULT_TOKEN=<root-token>`

`vault login`

#### Enable secrets
`vault secrets enable -path=secret kv-v2`

#### Stop Vault

`docker compose -f ./local/docker-compose.yaml --env-file ./.env down shared-vault -v`

Your Vault is now initialized.

### Start EDC-Services
`docker compose -f ./local/docker-compose.yaml --env-file ./.env up -d`

#### Open a Terminal inside the Container

`docker exec -it shared-vault sh`

#### Unseal Vault
Run the following command with the unseal key.

`vault operator unseal <unseal-key>`


### Stop and Remove
1. `docker compose -f ./traefik/traefik-compose.yaml --env-file ./.env down`
2. `docker compose -f ./local/docker-compose.yaml --env-file ./.env down -v`
3. `docker network rm proxy`
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1",
"name": "con-x-local-test",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
vars {
ISSUER_DID_API: {{ISSUER_DOMAIN}}
ISSUER_ID_API: {{ISSUER_DOMAIN}}/api/identity
ISSUER_ISS_API: {{ISSUER_DOMAIN}}/api/issuer
CONSUMER_IDHUB_DID_API: {{CONSUMER_DOMAIN}}
CONSUMER_IDHUB_ID_API: {{CONSUMER_DOMAIN}}/api/identity
CONSUMER_IDHUB_STS_API: {{CONSUMER_DOMAIN}}/api/sts
CONSUMER_IDHUB_CREDS_API: {{CONSUMER_DOMAIN}}/api/credentials
ISSUER_APIKEY: ZGlkOndlYjpsb2NhbC1pc3N1ZXItc2VydmljZTpmeC1pc3N1ZXI=.CmYgVcuzneJXqzcbj7vmld5feejy6OguIylflSrz6WTjG1HNQRvO62EafFrQjS/lVlZAwiwz2rwwZgXrbpyhcg==
CONSUMER_IH_APIKEY: ZGlkOndlYjpsb2NhbC11c2VyLWlkaHViOnVzZXI6Y29uc3VtZXI=.ObFly02OtymUNRE43uH9SblWVtsZH0NMddgm1dFYQXRekO3qXX+rHFV7NvM+DUW3lcA2PbILt5rwWYEqm7WNgw==
PROVIDER_IH_APIKEY: ZGlkOndlYjpsb2NhbC11c2VyLWlkaHViOnVzZXI6cHJvdmlkZXI=.Knip+hedL63qedBQfOvZhhrF2ooSCfP2YgjONvtmehofor2ejdw/en0MAXDBZEcXrCwYNppDMNFDsRlG5rB/Mw==
CONSUMER_VAULTURL: {{CONSUMER_DOMAIN}}
CONSUMER_STS_SECRET: VD0q6jOEyslSeFV2
PROVIDER_STS_SECRET: XjDk9ncaJSrSfkQW
PROVIDER_MANAGEMENT: {{PROVIDER_DOMAIN}}/management
CONSUMER_MANAGEMENT: {{CONSUMER_DOMAIN}}/management
PROVIDER_DATAPLANE_PUBLIC: {{PROVIDER_DOMAIN}}/public
PROVIDER_IDHUB_DID_API: {{PROVIDER_DOMAIN}}
PROVIDER_IDHUB_ID_API: {{PROVIDER_DOMAIN}}/api/identity
PROVIDER_IDHUB_STS_API: {{PROVIDER_DOMAIN}}/api/sts
PROVIDER_IDHUB_CREDS_API: {{PROVIDER_DOMAIN}}/api/credentials
ISS_ID: did:web:example.com
CONS_ID: did:web:example.com
PROV_ID: did:web:example.com
cons_access_token: eyJraWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkaHViOnVzZXI6Y29uc3VtZXIja2V5LTEiLCJhbGciOiJFZDI1NTE5In0.eyJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkaHViOnVzZXI6Y29uc3VtZXIiLCJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkaHViOnVzZXI6cHJvdmlkZXIiLCJuYmYiOjE3NzAyNzg5NTQsInNjb3BlIjoib3JnLmVjbGlwc2UudHJhY3R1c3gudmMudHlwZTpNZW1iZXJzaGlwQ3JlZGVudGlhbDpyZWFkIiwiaXNzIjoiZGlkOndlYjpjb25zdW1lci1pZGh1Yjp1c2VyOmNvbnN1bWVyIiwiZXhwIjoxNzcwMjc5MjU0LCJpYXQiOjE3NzAyNzg5NTQsImp0aSI6ImFjY2Vzc3Rva2VuLTcxYThmNTA5LTgwYTktNDMwZC1iMjU0LTMxNGFiYTBkNjY5OSJ9.ipRpdi_Ekh7y4IIqhqLgHU35Fn7NNkv6e6hILXy8pZObdy33y3MKppI61424eyHwqzmh7X2kwV2S5gDy3aOKCQ
prov_access_token: eyJraWQiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkaHViOnVzZXI6cHJvdmlkZXIja2V5LTEiLCJhbGciOiJFZDI1NTE5In0.eyJzdWIiOiJkaWQ6d2ViOnByb3ZpZGVyLWlkaHViOnVzZXI6cHJvdmlkZXIiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkaHViOnVzZXI6Y29uc3VtZXIiLCJuYmYiOjE3NzAyNzg5NTUsImlzcyI6ImRpZDp3ZWI6cHJvdmlkZXItaWRodWI6dXNlcjpwcm92aWRlciIsImV4cCI6MTc3MDI3OTI1NSwiaWF0IjoxNzcwMjc4OTU1LCJqdGkiOiJkNjA0MTVjOS1kMGM0LTRiNWQtYjI4My01ZmNmYjhlMDY2OGQiLCJ0b2tlbiI6ImV5SnJhV1FpT2lKa2FXUTZkMlZpT21OdmJuTjFiV1Z5TFdsa2FIVmlPblZ6WlhJNlkyOXVjM1Z0WlhJamEyVjVMVEVpTENKaGJHY2lPaUpGWkRJMU5URTVJbjAuZXlKaGRXUWlPaUprYVdRNmQyVmlPbU52Ym5OMWJXVnlMV2xrYUhWaU9uVnpaWEk2WTI5dWMzVnRaWElpTENKemRXSWlPaUprYVdRNmQyVmlPbkJ5YjNacFpHVnlMV2xrYUhWaU9uVnpaWEk2Y0hKdmRtbGtaWElpTENKdVltWWlPakUzTnpBeU56ZzVOVFFzSW5OamIzQmxJam9pYjNKbkxtVmpiR2x3YzJVdWRISmhZM1IxYzNndWRtTXVkSGx3WlRwTlpXMWlaWEp6YUdsd1EzSmxaR1Z1ZEdsaGJEcHlaV0ZrSWl3aWFYTnpJam9pWkdsa09uZGxZanBqYjI1emRXMWxjaTFwWkdoMVlqcDFjMlZ5T21OdmJuTjFiV1Z5SWl3aVpYaHdJam94Tnpjd01qYzVNalUwTENKcFlYUWlPakUzTnpBeU56ZzVOVFFzSW1wMGFTSTZJbUZqWTJWemMzUnZhMlZ1TFRjeFlUaG1OVEE1TFRnd1lUa3RORE13WkMxaU1qVTBMVE14TkdGaVlUQmtOalk1T1NKOS5pcFJwZGlfRWtoN3k0SUlxaHFMZ0hVMzVGbjdOTmt2NmU2aElMWHk4cFpPYmR5MzN5M01LcHBJNjE0MjRleUh3cXptaDdYMmt3VjJTNWdEeTNhT0tDUSJ9.42YDTnuzZ0RprqLjFw6hUoAXrgpPxyzKNFrqLdbWz6HXAiujkq32QAFU-M9gtQ0hMNcjshRZUX6DryBWxhGNDw
offerId: MQ==:YXNzZXRJZA==:MDFhN2ZjYWYtODgzOS00N2JmLTllZDAtM2Y0YjliMTFiOWM5
negotiation-id: 3745ad50-6b99-4142-bf1a-509b3d0e313d
contractId: 3345f7f1-f735-4c92-8aa2-6e137203b2f9
transferId: 3ebe55c6-900a-4c03-b213-20c5c3f0274d
pullSecret: eyJraWQiOiJwcm92X3B1YiIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJhbm9ueW1vdXMiLCJhdWQiOiJkaWQ6d2ViOmNvbnN1bWVyLWlkaHViOnVzZXI6Y29uc3VtZXIiLCJzdWIiOiJhbm9ueW1vdXMiLCJpYXQiOjE3NzAyNzg5ODgsImp0aSI6IjUwYWQxMjk3LWZhN2QtNDI0ZC1hNjBhLTg5M2MwMGE4OTZhYyJ9.GkSz0qXhFmqPaLQpfPLkAvODX-iekoAQvLh3Kglhm7DApNF3PsGnv-Qzm7m8eNAqTUTWB9XXkRng_XqWmuAd-FWvzwG8d7ZaAahuykkOgX1W7vHWBMdJa-zvNm0cnzm-TQLWYCU-tDSKk_g_UrDUaFf9Jdq-avCoer3wcZrEmrf0K4o_WWs-l5hZEfDIOYHRsgoCY3P8pMcZYRjV57zdLUDl9SvLuCRR0ex0fKxJ2pb7mlaCL5ooD6fRaqWyrLvrIKZaDYfwKrX7IRJT9ePKyls9VKA9JBakh676L0jBr5-2TYG3uE9Xhyv4CZlqyck-_NyiL4Jao8-lL5FVCbPDVQ
ISS_PART_CONT: did:web:example.com
CONS_PART_CONT: did:web:example.com
PROV_PART_CONT: did:web:example.com
PROVIDER_VAULTURL: {{PROVIDER_DOMAIN}}
CONSUMER_MANAGEMENT_API_KEY: prov-management-api-key
ISSUER_DOMAIN: https://example.com
CONSUMER_DOMAIN: https://example.com
PROVIDER_DOMAIN: https://example.com
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
meta {
name: ShowConsumerCredentials
type: http
seq: 1
}

get {
url: {{CONSUMER_IDHUB_ID_API}}/v1alpha/credentials
body: none
auth: none
}

headers {
x-api-key: YWRtaW4.adminKey
}

script:pre-request {
const t = Date.now();
await new Promise(resolve => setTimeout(resolve, 2500));
console.log("Waited " + (Date.now() - t) + " ms");
}

tests {
test("Got non-empty response", function(){
const body = res.getBody();
expect(body).to.be.an("array").that.is.not.empty;
})
}

settings {
encodeUrl: true
timeout: 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
meta {
name: ShowProviderCredentials
type: http
seq: 2
}

get {
url: {{PROVIDER_IDHUB_ID_API}}/v1alpha/credentials
body: none
auth: none
}

headers {
x-api-key: YWRtaW4.adminKey
}

tests {
test("Got non-empty response", function(){
const body = res.getBody()
expect(body).to.be.an("array").that.is.not.empty;
})
}

settings {
encodeUrl: true
timeout: 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
meta {
name: Inspect Outcome
seq: 4
}

auth {
mode: inherit
}

docs {
Here we are taking a look at the credentials, that the trusted issuer created for the participants.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
meta {
name: CreateConsumerParticipant
type: http
seq: 1
}

post {
url: {{CONSUMER_IDHUB_ID_API}}/v1alpha/participants
body: json
auth: inherit
}

headers {
x-api-key: YWRtaW4.adminKey
}

body:json {
{
"roles": [],
"serviceEndpoints": [
{
"id": "ConsumerCredentialService-ID",
"type": "CredentialService",
"serviceEndpoint": "{{CONSUMER_DOMAIN}}/api/credentials/v1/participants/{{CONS_PART_CONT}}"
},
{
"id": "ConsumerIssuerService-ID",
"type": "IssuerService",
"serviceEndpoint": "{{CONSUMER_DOMAIN}}/api/issuance/v1alpha/participants/{{CONS_PART_CONT}}"
}
],
"active": true,
"participantContextId": "{{CONS_PART_CONT}}",
"did": "{{CONS_ID}}",
"key": {
"keyId": "{{CONS_ID}}#key-1",
"privateKeyAlias": "{{CONS_ID}}-alias",
"keyGeneratorParams": {
"algorithm": "EdDSA",
"curve": "Ed25519"
}
}
}
}

script:pre-request {
const cons_id = bru.getEnvVar("CONS_ID");
//const participantContext = cons_id.split(":").slice(3).join(":").replace(/:/g, "-");
const participantContext = cons_id
bru.setEnvVar("CONS_PART_CONT", participantContext);
}

script:post-response {
const apiKey = res.getBody().apiKey.trim();
if (apiKey) {
bru.setEnvVar("CONSUMER_IH_APIKEY", apiKey);
}
const stsSecret = res.getBody().clientSecret.trim();
if (stsSecret) {
bru.setEnvVar("CONSUMER_STS_SECRET", stsSecret)
}
}

settings {
encodeUrl: true
timeout: 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
meta {
name: Get Consumer DID Doc
type: http
seq: 3
}

get {
url: {{CONSUMER_IDHUB_DID_API}}/did.json
body: none
auth: inherit
}

settings {
encodeUrl: true
timeout: 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
meta {
name: RequestConsumerDevMemCredential
type: http
seq: 2
}

post {
url: {{CONSUMER_IDHUB_ID_API}}/v1alpha/participants/{{CONS_PART_CONT}}/credentials/request
body: json
auth: none
}

body:json {
{
"issuerDid": "{{ISS_ID}}",
"credentials": [{
"format": "VC1_0_JWT",
"type": "MembershipCredential",
"id": "dev-credential-def-1"
}]
}
}

script:pre-request {
const cons_id = bru.getEnvVar("CONS_ID");
//const participantContext = cons_id.split(":").slice(3).join(":").replace(/:/g, "-");
const participantContext = cons_id
bru.setEnvVar("CONS_PART_CONT", participantContext);
req.setHeader("x-api-key", bru.getEnvVar("CONSUMER_IH_APIKEY"));
}

settings {
encodeUrl: true
timeout: 0
}
Loading