Skip to content
Draft
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ LABEL maintainer="[email protected]"
ENV GOPATH=/

RUN mkdir /opt/nuts && cd /opt/nuts
COPY . .
COPY go.mod .
COPY go.sum .
RUN go mod download && go mod verify

COPY . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-w -s -X 'github.com/nuts-foundation/nuts-node/core.GitCommit=${GIT_COMMIT}' -X 'github.com/nuts-foundation/nuts-node/core.GitBranch=${GIT_BRANCH}' -X 'github.com/nuts-foundation/nuts-node/core.GitVersion=${GIT_VERSION}'" -o /opt/nuts/nuts

# alpine
Expand Down
8 changes: 8 additions & 0 deletions e2e-tests/nuts-network/private-transactions/burst.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

set -e

for i in {1..200}; do
echo $REQUESTA | curl -X POST -s --data-binary @- http://localhost:28081/internal/auth/v1/request-access-token -H "Content-Type:application/json" > /dev/null &
echo $REQUESTB | curl -X POST -s --data-binary @- http://localhost:18081/internal/auth/v1/request-access-token -H "Content-Type:application/json" > /dev/null &
done
21 changes: 21 additions & 0 deletions e2e-tests/nuts-network/private-transactions/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
services:
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ] # this makes sure the container only reports healthy it can be connected to
interval: 1s
timeout: 5s
retries: 20
nodeA:
user: "$USER:$USER"
image: "${IMAGE_NODE_A:-nutsfoundation/nuts-node:master}"
depends_on:
db:
condition: service_healthy
environment:
NUTS_CONFIGFILE: /opt/nuts/nuts.yaml
NUTS_NETWORK_NODEDID: "${NODE_A_DID}"
NUTS_STORAGE_SQL_CONNECTION: postgres://postgres:postgres@db:5432/node_a?sslmode=disable
ports:
- "18081:8081"
volumes:
- "./node-A/data:/opt/nuts/data"
- "./node-A/nuts.yaml:/opt/nuts/nuts.yaml:ro"
- "../../tls-certs/nodeA-certificate.pem:/opt/nuts/certificate-and-key.pem:ro"
- "../../tls-certs/truststore.pem:/opt/nuts/truststore.pem:ro"
mem_limit: 512m
healthcheck:
interval: 1s # Make test run quicker by checking health status more often
nodeB:
user: "$USER:$USER"
image: "${IMAGE_NODE_B:-nutsfoundation/nuts-node:master}"
depends_on:
db:
condition: service_healthy
environment:
NUTS_CONFIGFILE: /opt/nuts/nuts.yaml
NUTS_NETWORK_NODEDID: "${NODE_B_DID}"
NUTS_NETWORK_BOOTSTRAPNODES: ${BOOTSTRAP_NODES}
NUTS_STORAGE_SQL_CONNECTION: postgres://postgres:postgres@db:5432/node_b?sslmode=disable
ports:
- "28081:8081"
volumes:
- "./node-B/data:/opt/nuts/data"
- "./node-B/nuts.yaml:/opt/nuts/nuts.yaml:ro"
- "../../tls-certs/nodeB-certificate.pem:/opt/nuts/certificate-and-key.pem:ro"
- "../../tls-certs/truststore.pem:/opt/nuts/truststore.pem:ro"
mem_limit: 512m
healthcheck:
interval: 1s # Make test run quicker by checking health status more often
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
url: https://node-A
verbosity: debug
strictmode: true
verbosity: info
strictmode: false
internalratelimiter: false
datadir: /opt/nuts/data
cpuprofile: /opt/nuts/data/cpu.profile
http:
log: metadata-and-body
internal:
address: :8081
auth:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"means": "dummy",
"payload": "BASE64_CONTRACT"
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
url: https://node-B
verbosity: debug
strictmode: true
verbosity: info
strictmode: false
internalratelimiter: false
datadir: /opt/nuts/data
cpuprofile: /opt/nuts/data/cpu.profile
http:
log: metadata-and-body
internal:
address: :8081
auth:
Expand Down
155 changes: 136 additions & 19 deletions e2e-tests/nuts-network/private-transactions/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ USER=$UID
source ../../util.sh

function searchAuthCredentials() {
ISSUER=$2
printf '{
"query": {
"@context": ["https://www.w3.org/2018/credentials/v1", "https://nuts.nl/credentials/v1"],
"type": ["VerifiableCredential" ,"NutsAuthorizationCredential"],
"issuer": "%s",
"credentialSubject": {
"subject": "urn:oid:2.16.840.1.113883.2.4.6.3:123456780"
}
Expand All @@ -32,6 +34,13 @@ docker compose down
docker compose rm -f -v
rm -rf ./node-*/data

echo "------------------------------------"
echo "Create DB..."
echo "------------------------------------"
docker compose up --wait db
docker compose exec db psql -U postgres -c "CREATE DATABASE node_a"
docker compose exec db psql -U postgres -c "CREATE DATABASE node_b"

echo "------------------------------------"
echo "Starting Docker containers..."
echo "------------------------------------"
Expand All @@ -43,14 +52,43 @@ docker compose up --wait
echo "------------------------------------"
echo "Creating NodeDIDs..."
echo "------------------------------------"
export NODE_A_DID=$(setupNode "http://localhost:18081" "nodeA:5555")
export NODE_A_DID=$(setupNode "http://localhost:18081" "nodeA:5555" "http://nodeA:8080")
printf "NodeDID for node-a: %s\n" "$NODE_A_DID"
# Wait for node B to receive the TXs created by node A, indicating the connection is working
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 2 10
export NODE_B_DID=$(setupNode "http://localhost:28081" "nodeB:5555")
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 3 10
export NODE_B_DID=$(setupNode "http://localhost:28081" "nodeB:5555" "http://nodeB:8080")
printf "NodeDID for node-b: %s\n" "$NODE_B_DID"
# Wait for node A to receive all TXs created by node B
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 4 10
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 6 10

# Issue NutsOrganizationCredential for Vendor B
REQUEST="{\"type\":\"NutsOrganizationCredential\",\"issuer\":\"${NODE_B_DID}\", \"credentialSubject\": {\"id\":\"${NODE_B_DID}\", \"organization\":{\"name\":\"Caresoft B\", \"city\":\"Caretown\"}},\"visibility\": \"public\"}"
RESPONSE=$(echo $REQUEST | curl -X POST --data-binary @- http://localhost:28081/internal/vcr/v2/issuer/vc -H "Content-Type:application/json")
if echo $RESPONSE | grep -q "VerifiableCredential"; then
echo "VC issued"
else
echo "FAILED: Could not issue NutsOrganizationCredential to node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi
# Issue NutsOrganizationCredential for Vendor A
REQUEST="{\"type\":\"NutsOrganizationCredential\",\"issuer\":\"${NODE_A_DID}\", \"credentialSubject\": {\"id\":\"${NODE_A_DID}\", \"organization\":{\"name\":\"Caresoft A\", \"city\":\"Caretown\"}},\"visibility\": \"public\"}"
RESPONSE=$(echo $REQUEST | curl -X POST --data-binary @- http://localhost:18081/internal/vcr/v2/issuer/vc -H "Content-Type:application/json")
if echo $RESPONSE | grep -q "VerifiableCredential"; then
echo "VC issued"
else
echo "FAILED: Could not issue NutsOrganizationCredential to node-A" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 8 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 8 10

# Vendor A must trust 'NutsOrganizationCredential's from Vendor B
docker compose exec nodeA nuts vcr trust "NutsOrganizationCredential" "${NODE_B_DID}"
# Vendor B must trust its own 'NutsOrganizationCredential's since it's self-issued
docker compose exec nodeB nuts vcr trust "NutsOrganizationCredential" "${NODE_A_DID}"

echo "------------------------------------"
echo "Restarting with NodeDID set..."
Expand All @@ -72,40 +110,119 @@ vcNodeB=$(createAuthCredential "http://localhost:28081" "$NODE_B_DID" "$NODE_A_D
printf "VC issued by node B: %s\n" "$vcNodeB"

# Wait for transactions to sync
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 6 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 6 10
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 10 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 10 10

if [ $(searchAuthCredentials "http://localhost:18081" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "2" ]; then
if [ $(searchAuthCredentials "http://localhost:18081" "$NODE_A_DID" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "1" ]; then
echo "failed to find NutsAuthorizationCredentials on Node-A"
exitWithDockerLogs 1
fi

if [ $(searchAuthCredentials "http://localhost:28081" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "2" ]; then
if [ $(searchAuthCredentials "http://localhost:18081" "$NODE_B_DID" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "1" ]; then
echo "failed to find NutsAuthorizationCredentials on Node-A"
exitWithDockerLogs 1
fi

if [ $(searchAuthCredentials "http://localhost:28081" "$NODE_A_DID" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "1" ]; then
echo "failed to find NutsAuthorizationCredentials on Node-B"
exitWithDockerLogs 1
fi

if [ $(searchAuthCredentials "http://localhost:28081" "$NODE_B_DID" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "1" ]; then
echo "failed to find NutsAuthorizationCredentials on Node-B"
exitWithDockerLogs 1
fi


echo "------------------------------------"
echo "Revoking NutsAuthorizationCredential..."
echo "Sign contract..."
echo "------------------------------------"
revokeCredential "http://localhost:18081" "${vcNodeA}"
revokeCredential "http://localhost:28081" "${vcNodeB}"

# Wait for transactions to sync
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 8 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 8 10
# draw up a contract
REQUEST="{\"type\": \"PractitionerLogin\",\"language\": \"EN\",\"version\": \"v3\",\"legalEntity\": \"${NODE_B_DID}\"}"
RESPONSE=$(echo $REQUEST | curl -X PUT --data-binary @- http://localhost:28081/internal/auth/v1/contract/drawup -H "Content-Type:application/json")
if echo $RESPONSE | grep -q "PractitionerLogin"; then
echo $RESPONSE | sed -E 's/.*"message":"([^"]*).*/\1/' > ./node-B/data/contract.txt
echo "Contract stored in ./node-B/data/contract.txt"
else
echo "FAILED: Could not get contract drawn up at node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

if [ $(searchAuthCredentials "http://localhost:18081" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "0" ]; then
echo "NutsAuthorizationCredentials should have been revoked so they can't be resolved on Node-A"
# sign the contract with dummy means
sed "s/BASE64_CONTRACT/$(cat ./node-B/data/contract.txt)/" ./node-B/createsigningsessionrequesttemplate.json > ./node-B/data/createsigningsessionrequest.json
RESPONSE=$(curl -X POST -s --data-binary "@./node-B/data/createsigningsessionrequest.json" http://localhost:28081/internal/auth/v1/signature/session -H "Content-Type:application/json")
if echo $RESPONSE | grep -q "sessionPtr"; then
SESSION=$(echo $RESPONSE | sed -E 's/.*"sessionID":"([^"]*).*/\1/')
echo $SESSION
else
echo "FAILED: Could not get contract signed at node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

if [ $(searchAuthCredentials "http://localhost:28081" | jq ".verifiableCredentials[].verifiableCredential.id" | wc -l) -ne "0" ]; then
echo "NutsAuthorizationCredentials should have been revoked so they can't be resolved on Node-B"
# poll once for status created
RESPONSE=$(curl "http://localhost:28081/internal/auth/v1/signature/session/$SESSION")
if echo $RESPONSE | grep -q "created"; then
echo $RESPONSE
else
echo "FAILED: Could not get session status from node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

# poll twice for status success
RESPONSE=$(curl "http://localhost:28081/internal/auth/v1/signature/session/$SESSION")
if echo $RESPONSE | grep -q "in-progress"; then
echo $RESPONSE
else
echo "FAILED: Could not get session status from node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

# poll three times for status completed
RESPONSE=$(curl "http://localhost:28081/internal/auth/v1/signature/session/$SESSION")
if echo $RESPONSE | grep -q "completed"; then
echo $RESPONSE | sed -E 's/.*"verifiablePresentation":(.*\]}).*/\1/' > ./node-B/data/vp.txt
echo "VP stored in ./node-B/data/vp.txt"
else
echo "FAILED: Could not get session status from node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Add more credentials..."
echo "------------------------------------"
# Create JWT bearer token
VP=$(cat ./node-B/data/vp.txt)
VC1=$(searchAuthCredentials "http://localhost:28081" "${NODE_A_DID}" | jq ".verifiableCredentials[0].verifiableCredential")
VC2=$(searchAuthCredentials "http://localhost:28081" "${NODE_B_DID}" | jq ".verifiableCredentials[1].verifiableCredential")

waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 10 60
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 10 60

echo "------------------------------------"
echo "Perform OAuth 2.0 flow..."
echo "------------------------------------"

echo $VC1
echo $VC2
export REQUESTA="{\"credentials\": [${VC1}],\"authorizer\":\"${NODE_A_DID}\",\"requester\":\"${NODE_B_DID}\",\"identity\":${VP},\"service\":\"test\"}"
export REQUESTB="{\"credentials\": [${VC2}],\"authorizer\":\"${NODE_B_DID}\",\"requester\":\"${NODE_A_DID}\",\"identity\":${VP},\"service\":\"test\"}"
START_DATE=$(date +%s)
for i in {1..10}; do
echo "Starting burst $i"
./burst.sh &
done
echo "Waiting for all requests to finish..."
wait
echo Finished in $(($(date +%s) - $START_DATE)) seconds

echo "------------------------------------"
echo "Stopping Docker containers..."
echo "------------------------------------"
docker compose stop
docker compose stop
#exitWithDockerLogs 0
27 changes: 24 additions & 3 deletions e2e-tests/oauth-flow/rfc002/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ VENDOR_A_DIDDOC=$(echo $VENDOR_A_DIDDOC | jq ". |= . + {assertionMethod: [\"${VE
echo $VENDOR_A_DIDDOC > ./node-A/data/updated-did.json
DIDDOC_HASH=$(docker compose exec nodeA-backend nuts vdr resolve $VENDOR_A_DID --metadata | jq -r .hash)
docker compose exec nodeA-backend nuts vdr update "${VENDOR_A_DID}" "${DIDDOC_HASH}" /opt/nuts/data/updated-did.json
# Add NutsComm
REQUEST="{\"type\": \"NutsComm\",\"endpoint\": \"grpc://nodeA-backend:5555\"}"
RESPONSE=$(echo $REQUEST | curl -X POST --data-binary @- http://localhost:18081/internal/didman/v1/did/${VENDOR_A_DID}/endpoint -H "Content-Type:application/json")

# Wait for NodeB to contain 2 transactions
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 2 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 3 10

# Register Vendor B
VENDOR_B_DIDDOC=$(docker compose exec nodeB nuts vdr create-did)
Expand All @@ -47,6 +50,9 @@ VENDOR_B_DIDDOC=$(echo $VENDOR_B_DIDDOC | jq ". |= . + {assertionMethod: [\"${VE
echo $VENDOR_B_DIDDOC > ./node-B/data/updated-did.json
DIDDOC_HASH=$(docker compose exec nodeB nuts vdr resolve $VENDOR_B_DID --metadata | jq -r .hash)
docker compose exec nodeB nuts vdr update "${VENDOR_B_DID}" "${DIDDOC_HASH}" /opt/nuts/data/updated-did.json
# Add NutsComm
REQUEST="{\"type\": \"NutsComm\",\"endpoint\": \"grpc://nodeB:5555\"}"
RESPONSE=$(echo $REQUEST | curl -X POST --data-binary @- http://localhost:28081/internal/didman/v1/did/${VENDOR_B_DID}/endpoint -H "Content-Type:application/json")

# Issue NutsOrganizationCredential for Vendor B
REQUEST="{\"type\":\"NutsOrganizationCredential\",\"issuer\":\"${VENDOR_B_DID}\", \"credentialSubject\": {\"id\":\"${VENDOR_B_DID}\", \"organization\":{\"name\":\"Caresoft B.V.\", \"city\":\"Caretown\"}},\"visibility\": \"public\"}"
Expand All @@ -60,14 +66,28 @@ else
fi

echo Waiting for updates to be propagated on the network...
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 5 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 5 10
waitForTXCount "NodeA" "http://localhost:18081/status/diagnostics" 7 10
waitForTXCount "NodeB" "http://localhost:28081/status/diagnostics" 7 10

# Vendor A must trust 'NutsOrganizationCredential's from Vendor B
docker compose exec nodeA-backend nuts vcr trust "NutsOrganizationCredential" "${VENDOR_B_DID}"
# Vendor B must trust its own 'NutsOrganizationCredential's since it's self-issued
docker compose exec nodeB nuts vcr trust "NutsOrganizationCredential" "${VENDOR_B_DID}"

echo "------------------------------------"
echo "Issue auth creds..."
echo "------------------------------------"

REQUEST="{\"type\":\"NutsAuthorizationCredential\",\"issuer\":\"${VENDOR_B_DID}\", \"credentialSubject\": {\"id\":\"${VENDOR_A_DID}\", \"purposeOfUse\":\"test\"}, \"visibility\": \"private\"}"
RESPONSE=$(echo $REQUEST | curl -X POST --data-binary @- http://localhost:28081/internal/vcr/v2/issuer/vc -H "Content-Type:application/json")
if echo $RESPONSE | grep -q "VerifiableCredential"; then
echo "VC issued"
else
echo "FAILED: Could not issue NutsAuthorizationCredential to node-B" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Sign contract..."
echo "------------------------------------"
Expand Down Expand Up @@ -160,3 +180,4 @@ echo "------------------------------------"
echo "Stopping Docker containers..."
echo "------------------------------------"
docker compose stop
exitWithDockerLogs 0
Loading
Loading