Skip to content

Commit

Permalink
Add statuslist revocation to e2e-test and fix failing code (#3497)
Browse files Browse the repository at this point in the history
  • Loading branch information
gerardsn authored Oct 18, 2024
1 parent b1e0119 commit 7d8da8c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 22 deletions.
29 changes: 28 additions & 1 deletion e2e-tests/oauth-flow/rfc021/do-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ echo "Status list credential: $STATUS_LIST_CREDENTIAL"
# Get status list credential
RESPONSE=$($db_dc exec nodeB-backend curl -s -k $STATUS_LIST_CREDENTIAL)
# Check response HTTP 200 OK
if [ $? -eq 0 ]; then
if echo $RESPONSE | grep -q "\"id\":\"$STATUS_LIST_CREDENTIAL\"" ; then
echo "Status list credential retrieved"
else
echo "FAILED: Could not retrieve status list credential" 1>&2
Expand Down Expand Up @@ -195,6 +195,33 @@ else
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Revoking credential..."
echo "------------------------------------"
# revoke credential
VENDOR_B_CREDENTIAL_ID=$(echo $VENDOR_B_CREDENTIAL | jq -r .id)
echo $VENDOR_B_CREDENTIAL_ID
RESPONSE=$(curl -s -X DELETE "http://localhost:28081/internal/vcr/v2/issuer/vc/${VENDOR_B_CREDENTIAL_ID//#/%23}")
if [ -z "${RESPONSE}" ]; then
echo "VendorB NutsOrganizationCredential revoked"
else
echo "FAILED: NutsOrganizationCredential not revoked" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Retrieving data fails..."
echo "------------------------------------"
RESPONSE=$($db_dc exec nodeB curl --http1.1 --insecure --cert /etc/nginx/ssl/server.pem --key /etc/nginx/ssl/key.pem https://nodeA:443/resource -H "Authorization: DPoP $ACCESS_TOKEN" -H "DPoP: $DPOP")
if [ "${RESPONSE}" == "Unauthorized" ]; then
echo "Access denied!"
else
echo "FAILED: Retrieved data with revoked credential" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Stopping Docker containers..."
echo "------------------------------------"
Expand Down
11 changes: 8 additions & 3 deletions vcr/revocation/bitstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@ func (bs *bitstring) Scan(value any) error {
*bs = nil
return nil
}
asString, ok := value.(string)
if !ok {
return fmt.Errorf("bitstring unmarshal from DB: expected []uint8, got %T", value)
var asString string
switch v := value.(type) {
case string: // sqlite, postgress, sqlserver
asString = v
case []uint8: // mysql
asString = string(v)
default:
return fmt.Errorf("bitstring unmarshal from DB: expected []uint8 or string, got %T", value)
}
expanded, err := expand(asString)
if err != nil {
Expand Down
33 changes: 15 additions & 18 deletions vcr/revocation/statuslist2021_issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,7 @@ func (cs *StatusList2021) Credential(ctx context.Context, issuerDID did.DID, pag
var cred *vc.VerifiableCredential // is nil, so if this panics outside this method the var name is probably shadowed in the db.Transaction.
err = cs.db.Transaction(func(tx *gorm.DB) error {
// lock credentialRecord row for statusListCredentialURL since it will be updated.
// Revoke does the same to guarantee the DB always contains all revocations.
// Microsoft SQL server does not support the locking clause, so we have to use a raw query instead.
// See https://github.com/nuts-foundation/nuts-node/issues/3393
if tx.Dialector.Name() == "sqlserver" {
err = tx.Raw("SELECT * FROM status_list_credential WITH (UPDLOCK, ROWLOCK) WHERE subject_id = ?", statusListCredentialURL).
Scan(new(credentialRecord)).
Error
} else {
err = tx.Clauses(clause.Locking{Strength: clause.LockingStrengthUpdate}).
Find(new(credentialRecord), "subject_id = ?", statusListCredentialURL).
Error
}
err = lockCredentialRecord(tx, statusListCredentialURL)
if err != nil {
return err
}
Expand Down Expand Up @@ -421,12 +410,7 @@ func (cs *StatusList2021) Revoke(ctx context.Context, credentialID ssi.URI, entr

return cs.db.Transaction(func(tx *gorm.DB) error {
// lock relevant credentialRecord. It was created when the first entry was issued for this StatusList2021Credential.
err = tx.Model(new(credentialRecord)).
Clauses(clause.Locking{Strength: clause.LockingStrengthUpdate}).
Select("subject_id").
Where("subject_id = ?", entry.StatusListCredential).
Find(new([]string)).
Error
err = lockCredentialRecord(tx, entry.StatusListCredential)
if err != nil {
return err
}
Expand Down Expand Up @@ -478,3 +462,16 @@ func (cs *StatusList2021) statusListURL(issuer did.DID, page int) string {
result, _ := url.Parse(cs.baseURL)
return result.JoinPath("statuslist", issuer.String(), strconv.Itoa(page)).String()
}

func lockCredentialRecord(tx *gorm.DB, statusListCredentialURL string) error {
// Microsoft SQL server does not support the locking clause, so we have to use a raw query instead.
// See https://github.com/nuts-foundation/nuts-node/issues/3393
if tx.Dialector.Name() == "sqlserver" {
return tx.Raw("SELECT * FROM status_list_credential WITH (UPDLOCK, ROWLOCK) WHERE subject_id = ?", statusListCredentialURL).
Scan(new(credentialRecord)).
Error
}
return tx.Clauses(clause.Locking{Strength: clause.LockingStrengthUpdate}).
Find(new(credentialRecord), "subject_id = ?", statusListCredentialURL).
Error
}

0 comments on commit 7d8da8c

Please sign in to comment.