Skip to content

Commit

Permalink
Merge branch 'main' into issue_355
Browse files Browse the repository at this point in the history
  • Loading branch information
andresuribe87 authored Jul 12, 2023
2 parents 9dcdc8d + f1c6de7 commit 6c29b66
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 62 deletions.
56 changes: 36 additions & 20 deletions pkg/server/router/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/tbd54566975/ssi-service/pkg/service/credential"
"github.com/tbd54566975/ssi-service/pkg/service/did"
"github.com/tbd54566975/ssi-service/pkg/service/framework"
"github.com/tbd54566975/ssi-service/pkg/service/keystore"
"github.com/tbd54566975/ssi-service/pkg/service/manifest"

"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
presmodel "github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
Expand Down Expand Up @@ -198,38 +201,51 @@ func TestManifestRouter(t *testing.T) {
signed, err := signer.SignJSON(applicationRequest)
assert.NoError(ttt, err)

submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
sar, err := submitApplicationRequest.toServiceRequest()
assert.NoError(ttt, err)
createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(context.Background(), *sar)
assert.NoError(ttt, err)
assert.False(ttt, createdApplicationResponseOp.Done)

createdApplicationResponse, err := manifestService.ReviewApplication(context.Background(), model.ReviewApplicationRequest{
ID: storage.StatusObjectID(createdApplicationResponseOp.ID),
Approved: true,
Reason: "ApprovalMan is here",
CredentialOverrides: map[string]model.CredentialOverride{
"id1": {
Data: map[string]any{"licenseType": "Class D"},
},
"id2": {
Data: map[string]any{"licenseType": "Class D"},
},
},
})
// submit and review application, the key is valid
createdApplicationResponse, err := submitAndReviewApplication(signed, ttt, manifestService)
assert.NoError(ttt, err)
assert.NotEmpty(ttt, createdManifest)
assert.NotEmpty(ttt, createdApplicationResponse.Response.ID)
assert.NotEmpty(ttt, createdApplicationResponse.Response.Fulfillment)
assert.Empty(ttt, createdApplicationResponse.Response.Denial)
assert.Equal(ttt, len(createManifestRequest.OutputDescriptors), len(createdApplicationResponse.Credentials))

// attempt to submit and review application again, this time with the revoked key
err = keyStoreService.RevokeKey(context.Background(), keystore.RevokeKeyRequest{ID: kid})
assert.NoError(ttt, err)
_, err = submitAndReviewApplication(signed, ttt, manifestService)
assert.Error(tt, err)
assert.ErrorContains(tt, err, "cannot use revoked key")
})
})
})
}
}

func submitAndReviewApplication(signed *keyaccess.JWT, ttt *testing.T, manifestService *manifest.Service) (*model.SubmitApplicationResponse, error) {
submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
sar, err := submitApplicationRequest.toServiceRequest()
assert.NoError(ttt, err)
createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(context.Background(), *sar)
assert.NoError(ttt, err)
assert.False(ttt, createdApplicationResponseOp.Done)

createdApplicationResponse, err := manifestService.ReviewApplication(context.Background(), model.ReviewApplicationRequest{
ID: storage.StatusObjectID(createdApplicationResponseOp.ID),
Approved: true,
Reason: "ApprovalMan is here",
CredentialOverrides: map[string]model.CredentialOverride{
"id1": {
Data: map[string]any{"licenseType": "Class D"},
},
"id2": {
Data: map[string]any{"licenseType": "Class D"},
},
},
})
return createdApplicationResponse, err
}

func getValidManifestRequestRequest(issuerDID *did.CreateDIDResponse, kid string, createdManifest *model.CreateManifestResponse) model.CreateRequestRequest {
return model.CreateRequestRequest{
ManifestRequest: model.Request{
Expand Down
107 changes: 65 additions & 42 deletions pkg/server/router/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import (
"testing"

credschema "github.com/TBD54566975/ssi-sdk/credential/schema"
"github.com/TBD54566975/ssi-sdk/crypto"
didsdk "github.com/TBD54566975/ssi-sdk/did"
"github.com/stretchr/testify/assert"

"github.com/tbd54566975/ssi-service/config"
"github.com/tbd54566975/ssi-service/pkg/service/did"
"github.com/tbd54566975/ssi-service/pkg/service/framework"
"github.com/tbd54566975/ssi-service/pkg/service/keystore"
"github.com/tbd54566975/ssi-service/pkg/service/schema"
"github.com/tbd54566975/ssi-service/pkg/testutil"
)
Expand Down Expand Up @@ -58,27 +62,7 @@ func TestSchemaRouter(t *testing.T) {
assert.Contains(tt, err.Error(), "error getting schema")

// create a schema
simpleSchema := map[string]any{
"$schema": "https://json-schema.org/draft-07/schema",
"type": "object",
"properties": map[string]any{
"credentialSubject": map[string]any{
"type": "object",
"properties": map[string]any{
"id": map[string]any{
"type": "string",
},
"firstName": map[string]any{
"type": "string",
},
"lastName": map[string]any{
"type": "string",
},
},
"required": []any{"firstName", "lastName"},
},
},
}
simpleSchema := getSimpleSchema()
createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Issuer: "me", Name: "simple schema", Schema: simpleSchema})
assert.NoError(tt, err)
assert.NotEmpty(tt, createdSchema)
Expand Down Expand Up @@ -148,33 +132,72 @@ func TestSchemaSigning(t *testing.T) {
assert.Equal(tt, framework.StatusReady, schemaService.Status().Status)

// create a schema and don't sign it
simpleSchema := map[string]any{
"$schema": "https://json-schema.org/draft-07/schema",
"type": "object",
"properties": map[string]any{
"credentialSubject": map[string]any{
"type": "object",
"properties": map[string]any{
"id": map[string]any{
"type": "string",
},
"firstName": map[string]any{
"type": "string",
},
"lastName": map[string]any{
"type": "string",
},
},
"required": []any{"firstName", "lastName"},
},
},
}
simpleSchema := getSimpleSchema()
createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Issuer: "me", Name: "simple schema", Schema: simpleSchema})
assert.NoError(tt, err)
assert.NotEmpty(tt, createdSchema)
assert.NotEmpty(tt, createdSchema.ID)
assert.Equal(tt, "simple schema", createdSchema.Schema.Name())
})
})

t.Run("Signing schema with revoked key test", func(tt *testing.T) {
db := test.ServiceStorage(t)
assert.NotEmpty(tt, db)

serviceConfig := config.SchemaServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "schema"}}
keyStoreService := testKeyStoreService(tt, db)
didService := testDIDService(tt, db, keyStoreService)
schemaService, err := schema.NewSchemaService(serviceConfig, db, keyStoreService, didService.GetResolver())
assert.NoError(tt, err)
assert.NotEmpty(tt, schemaService)

// Create a DID
controllerDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{Method: didsdk.KeyMethod, KeyType: crypto.Ed25519})
assert.NoError(tt, err)
assert.NotEmpty(tt, controllerDID)
didID := controllerDID.DID.ID

// Create a key controlled by the DID
keyID := controllerDID.DID.VerificationMethod[0].ID
privateKey := "2dEPd7mA3aiuh2gky8tTPiCkyMwf8tBNUMZwRzeVxVJnJFGTbdLGUBcx51DCNyFWRjTG9bduvyLRStXSCDMFXULY"

err = keyStoreService.StoreKey(context.Background(), keystore.StoreKeyRequest{ID: keyID, Type: crypto.Ed25519, Controller: didID, PrivateKeyBase58: privateKey})
assert.NoError(tt, err)

// Revoke the key
err = keyStoreService.RevokeKey(context.Background(), keystore.RevokeKeyRequest{ID: keyID})
assert.NoError(tt, err)

// create a schema with the revoked key, it fails
_, err = schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Issuer: controllerDID.DID.ID, Name: "schema (revoked key)", Schema: getEmailSchema(), FullyQualifiedVerificationMethodID: keyID})
assert.Error(tt, err)
assert.ErrorContains(tt, err, "cannot use revoked key")
})
}
}

func getSimpleSchema() map[string]any {
simpleSchema := map[string]any{
"$schema": "https://json-schema.org/draft-07/schema",
"type": "object",
"properties": map[string]any{
"credentialSubject": map[string]any{
"type": "object",
"properties": map[string]any{
"id": map[string]any{
"type": "string",
},
"firstName": map[string]any{
"type": "string",
},
"lastName": map[string]any{
"type": "string",
},
},
"required": []any{"firstName", "lastName"},
},
},
}
return simpleSchema
}
3 changes: 3 additions & 0 deletions pkg/service/keystore/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ func (s Service) Sign(ctx context.Context, keyID string, data any) (*keyaccess.J
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "getting key with keyID<%s>", keyID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "creating key access for keyID<%s>", keyID)
Expand Down
5 changes: 5 additions & 0 deletions pkg/service/keystore/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ func TestRevokeKey(t *testing.T) {
assert.Equal(t, privKey, keyResponse.Key)
assert.True(t, keyResponse.Revoked)
assert.Equal(t, "2023-06-23T00:00:00Z", keyResponse.RevokedAt)

// attempt to "Sign()" with the revoked key, ensure it is prohibited
_, err = keyStore.Sign(context.Background(), keyID, "sampleDataAsString")
assert.Error(t, err)
assert.ErrorContains(t, err, "cannot use revoked key")
}

func createKeyStoreService(t *testing.T) (*Service, error) {
Expand Down
3 changes: 3 additions & 0 deletions pkg/service/manifest/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ func (s Service) signCredentialResponse(ctx context.Context, keyStoreID string,
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "getting key for signing response with key<%s>", keyStoreID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "creating key access for signing response with key<%s>", gotKey.ID)
Expand Down
3 changes: 3 additions & 0 deletions pkg/service/schema/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ func (s Service) signCredentialSchema(ctx context.Context, cred credential.Verif
if gotKey.Controller != issuer {
return nil, sdkutil.LoggingNewErrorf("key controller<%s> does not match credential issuer<%s> for key<%s>", gotKey.Controller, issuer, fullyQualifiedVerificationMethodID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(fullyQualifiedVerificationMethodID, gotKey.ID, gotKey.Key)
if err != nil {
return nil, errors.Wrapf(err, "creating key access for signing credential schema with key<%s>", gotKey.ID)
Expand Down

0 comments on commit 6c29b66

Please sign in to comment.