Skip to content
Snippets Groups Projects
Commit c2ab4b5b authored by Lyuben Penkovski's avatar Lyuben Penkovski
Browse files

Merge branch '3-export-cfg-signing-key' into 'main'

Export configuration to include signing namespace and key name

Closes #3

See merge request gaia-x/data-infrastructure-federation-services/tsa/infohub!3
parents 2d22f6a2 a5b40872
No related branches found
No related tags found
No related merge requests found
Pipeline #54879 passed with stages
in 3 minutes and 1 second
......@@ -16,7 +16,7 @@ include:
- template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
lint:
image: golangci/golangci-lint:v1.44.2
image: golangci/golangci-lint:v1.50.1
stage: test
tags:
- amd64-docker
......@@ -28,12 +28,27 @@ lint:
- cd /go/src/gitlab.com/${CI_PROJECT_PATH}
unit tests:
image: golang:1.17.7
image: golang:1.19.3
extends: .gotest
stage: test
tags:
- amd64-docker
before_script: []
coverage: '/total:\s+\(statements\)\s+(\d+.\d+\%)/'
govulncheck:
image: golang:1.19.3
stage: test
tags:
- amd64-docker
before_script:
- ln -s /builds /go/src/gitlab.com
- cd /go/src/gitlab.com/${CI_PROJECT_PATH}
script:
- go version
- go install golang.org/x/vuln/cmd/govulncheck@latest
- govulncheck ./...
amd64:
extends: .docker-build
......
......@@ -12,7 +12,6 @@ linters:
enable:
- megacheck
- govet
- deadcode
- errcheck
- goconst
- gocyclo
......@@ -22,10 +21,9 @@ linters:
- ineffassign
- nakedret
- staticcheck
- structcheck
- unconvert
- varcheck
- vet
- vetshadow
- misspell
- staticcheck
- unused
......@@ -239,7 +239,7 @@ func exposeMetrics(addr string, logger *zap.Logger) {
promMux := http.NewServeMux()
promMux.Handle("/metrics", promhttp.Handler())
logger.Info(fmt.Sprintf("exposing prometheus metrics at %s/metrics", addr))
if err := http.ListenAndServe(addr, promMux); err != nil {
if err := http.ListenAndServe(addr, promMux); err != nil { //nolint:gosec
logger.Error("error exposing prometheus metrics", zap.Error(err))
}
}
FROM golang:1.19-alpine3.15 as builder
FROM golang:1.19.3-alpine3.15 as builder
RUN apk add git
......
FROM golang:1.19
FROM golang:1.19.3
ENV GO111MODULE=on
......
......@@ -4,19 +4,16 @@ import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/piprate/json-gold/ld"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/golib/errors"
)
const (
presentationProofPath = "/v1/presentation/proof"
createPresentationPath = "/v1/presentation"
presentationVerifyPath = "/v1/presentation/verify"
)
......@@ -41,13 +38,20 @@ func New(addr string, opts ...ClientOption) *Client {
return c
}
func (c *Client) PresentationProof(ctx context.Context, vp *verifiable.Presentation) (*verifiable.Presentation, error) {
vpBytes, err := json.Marshal(vp)
func (c *Client) CreatePresentation(ctx context.Context, issuer, namespace, key string, data []map[string]interface{}) (map[string]interface{}, error) {
payload := map[string]interface{}{
"issuer": issuer,
"namespace": namespace,
"key": key,
"data": data,
}
payloadJSON, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequestWithContext(ctx, "POST", c.addr+presentationProofPath, bytes.NewReader(vpBytes))
req, err := http.NewRequestWithContext(ctx, "POST", c.addr+createPresentationPath, bytes.NewReader(payloadJSON))
if err != nil {
return nil, err
}
......@@ -59,19 +63,15 @@ func (c *Client) PresentationProof(ctx context.Context, vp *verifiable.Presentat
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected response from signer: %s", resp.Status)
return nil, errors.New(errors.GetKind(resp.StatusCode), getErrorBody(resp))
}
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
var presentation map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&presentation); err != nil {
return nil, errors.New("error decoding signer response as verifiable presentation", err)
}
return verifiable.ParsePresentation(
respBytes,
verifiable.WithPresJSONLDDocumentLoader(c.docLoader),
verifiable.WithPresDisabledProofCheck(),
)
return presentation, nil
}
func (c *Client) VerifyPresentation(ctx context.Context, vp []byte) error {
......@@ -105,7 +105,7 @@ func (c *Client) VerifyPresentation(ctx context.Context, vp []byte) error {
}
func getErrorBody(resp *http.Response) string {
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 2<<20))
body, err := io.ReadAll(io.LimitReader(resp.Body, 2<<20))
if err != nil {
return ""
}
......
......@@ -6,125 +6,107 @@ import (
"net/http/httptest"
"testing"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/piprate/json-gold/ld"
"github.com/stretchr/testify/assert"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/golib/errors"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/infohub/internal/clients/signer"
)
const invalidPresentation = `{"invalid":"verifiable_presentation"}`
const validPresentation = `{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "did:123",
"type": "VerifiablePresentation",
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"credentialSubject": {
"allow": true,
"id": "example/example/1.0",
"taskID": "0123456789abcdef"
},
"issuanceDate": "2022-06-14T08:43:22.78309334Z",
"issuer": "https://example.com",
"type": "VerifiableCredential"
},
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"credentialSubject": {
"id": "example/example/2.0",
"result": {
"hello": "world"
}
},
"issuanceDate": "2022-06-14T08:43:22.783102173Z",
"issuer": "https://example.com",
"type": "VerifiableCredential"
}
]
}`
func TestClient_PresentationProof(t *testing.T) {
func TestClient_CreatePresentation(t *testing.T) {
tests := []struct {
name string
ctx context.Context
vp *verifiable.Presentation
data []map[string]interface{}
handler http.HandlerFunc
result *verifiable.Presentation
result map[string]interface{}
errkind errors.Kind
errtext string
}{
{
name: "error creating http request because of nil context",
errtext: "net/http: nil Context",
name: "signer returns error",
data: []map[string]interface{}{{"hello": "world"}},
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("some error"))
},
errkind: errors.Internal,
errtext: "some error",
},
{
name: "signer server returns unexpected response code",
ctx: context.Background(),
name: "signer successfully creates verifiable presentation",
data: []map[string]interface{}{{"hello": "world"}},
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusServiceUnavailable)
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"id":"did:web:example.com"}`))
},
errtext: "unexpected response from signer: 503 Service Unavailable",
result: map[string]interface{}{"id": "did:web:example.com"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
srv := httptest.NewServer(test.handler)
client := signer.New(srv.URL)
result, err := client.CreatePresentation(context.Background(), "issuer", "namespace", "key", test.data)
if test.errtext != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), test.errtext)
assert.Nil(t, result)
} else {
assert.NotNil(t, result)
assert.Equal(t, test.result, result)
}
})
}
}
func TestClient_VerifyPresentation(t *testing.T) {
tests := []struct {
name string
vp []byte
handler http.HandlerFunc
errkind errors.Kind
errtext string
}{
{
name: "signer server returns empty response",
ctx: context.Background(),
name: "signer returns error",
vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("some error"))
},
errtext: "JSON unmarshalling of verifiable presentation: unexpected end of JSON input",
errkind: errors.Internal,
errtext: "some error",
},
{
name: "signer server returns invalid verifiable presentation",
ctx: context.Background(),
name: "signer returns unexpected response",
vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(invalidPresentation))
_, _ = w.Write([]byte("invalid json"))
},
errtext: "verifiable presentation is not valid",
errkind: errors.Unknown,
errtext: "failed to decode response",
},
{
name: "signer server returns valid presentation",
ctx: context.Background(),
name: "signer returns successfully",
vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(validPresentation))
_, _ = w.Write([]byte(`{"id":"did:web:example.com"}`))
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
signerSrv := httptest.NewServer(test.handler)
client := signer.New(signerSrv.URL, signer.WithHTTPClient(http.DefaultClient))
result, err := client.PresentationProof(test.ctx, test.vp)
srv := httptest.NewServer(test.handler)
client := signer.New(srv.URL)
err := client.VerifyPresentation(context.Background(), test.vp)
if err != nil {
assert.Nil(t, result)
assert.NotEmpty(t, test.errtext)
assert.Contains(t, err.Error(), test.errtext)
} else {
assert.Empty(t, test.errtext)
assert.NotNil(t, result)
// parse the string representation to compare with the returned result
vp, err := verifiable.ParsePresentation(
[]byte(validPresentation),
verifiable.WithPresJSONLDDocumentLoader(ld.NewDefaultDocumentLoader(http.DefaultClient)),
verifiable.WithPresDisabledProofCheck(),
)
assert.NoError(t, err)
assert.Equal(t, vp, result)
}
})
}
......
......@@ -9,36 +9,6 @@ import (
)
type FakeCredentials struct {
NewCredentialStub func([]string, string, map[string]interface{}, bool) (*verifiable.Credential, error)
newCredentialMutex sync.RWMutex
newCredentialArgsForCall []struct {
arg1 []string
arg2 string
arg3 map[string]interface{}
arg4 bool
}
newCredentialReturns struct {
result1 *verifiable.Credential
result2 error
}
newCredentialReturnsOnCall map[int]struct {
result1 *verifiable.Credential
result2 error
}
NewPresentationStub func([]string, ...*verifiable.Credential) (*verifiable.Presentation, error)
newPresentationMutex sync.RWMutex
newPresentationArgsForCall []struct {
arg1 []string
arg2 []*verifiable.Credential
}
newPresentationReturns struct {
result1 *verifiable.Presentation
result2 error
}
newPresentationReturnsOnCall map[int]struct {
result1 *verifiable.Presentation
result2 error
}
ParsePresentationStub func([]byte) (*verifiable.Presentation, error)
parsePresentationMutex sync.RWMutex
parsePresentationArgsForCall []struct {
......@@ -56,148 +26,6 @@ type FakeCredentials struct {
invocationsMutex sync.RWMutex
}
func (fake *FakeCredentials) NewCredential(arg1 []string, arg2 string, arg3 map[string]interface{}, arg4 bool) (*verifiable.Credential, error) {
var arg1Copy []string
if arg1 != nil {
arg1Copy = make([]string, len(arg1))
copy(arg1Copy, arg1)
}
fake.newCredentialMutex.Lock()
ret, specificReturn := fake.newCredentialReturnsOnCall[len(fake.newCredentialArgsForCall)]
fake.newCredentialArgsForCall = append(fake.newCredentialArgsForCall, struct {
arg1 []string
arg2 string
arg3 map[string]interface{}
arg4 bool
}{arg1Copy, arg2, arg3, arg4})
stub := fake.NewCredentialStub
fakeReturns := fake.newCredentialReturns
fake.recordInvocation("NewCredential", []interface{}{arg1Copy, arg2, arg3, arg4})
fake.newCredentialMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeCredentials) NewCredentialCallCount() int {
fake.newCredentialMutex.RLock()
defer fake.newCredentialMutex.RUnlock()
return len(fake.newCredentialArgsForCall)
}
func (fake *FakeCredentials) NewCredentialCalls(stub func([]string, string, map[string]interface{}, bool) (*verifiable.Credential, error)) {
fake.newCredentialMutex.Lock()
defer fake.newCredentialMutex.Unlock()
fake.NewCredentialStub = stub
}
func (fake *FakeCredentials) NewCredentialArgsForCall(i int) ([]string, string, map[string]interface{}, bool) {
fake.newCredentialMutex.RLock()
defer fake.newCredentialMutex.RUnlock()
argsForCall := fake.newCredentialArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
}
func (fake *FakeCredentials) NewCredentialReturns(result1 *verifiable.Credential, result2 error) {
fake.newCredentialMutex.Lock()
defer fake.newCredentialMutex.Unlock()
fake.NewCredentialStub = nil
fake.newCredentialReturns = struct {
result1 *verifiable.Credential
result2 error
}{result1, result2}
}
func (fake *FakeCredentials) NewCredentialReturnsOnCall(i int, result1 *verifiable.Credential, result2 error) {
fake.newCredentialMutex.Lock()
defer fake.newCredentialMutex.Unlock()
fake.NewCredentialStub = nil
if fake.newCredentialReturnsOnCall == nil {
fake.newCredentialReturnsOnCall = make(map[int]struct {
result1 *verifiable.Credential
result2 error
})
}
fake.newCredentialReturnsOnCall[i] = struct {
result1 *verifiable.Credential
result2 error
}{result1, result2}
}
func (fake *FakeCredentials) NewPresentation(arg1 []string, arg2 ...*verifiable.Credential) (*verifiable.Presentation, error) {
var arg1Copy []string
if arg1 != nil {
arg1Copy = make([]string, len(arg1))
copy(arg1Copy, arg1)
}
fake.newPresentationMutex.Lock()
ret, specificReturn := fake.newPresentationReturnsOnCall[len(fake.newPresentationArgsForCall)]
fake.newPresentationArgsForCall = append(fake.newPresentationArgsForCall, struct {
arg1 []string
arg2 []*verifiable.Credential
}{arg1Copy, arg2})
stub := fake.NewPresentationStub
fakeReturns := fake.newPresentationReturns
fake.recordInvocation("NewPresentation", []interface{}{arg1Copy, arg2})
fake.newPresentationMutex.Unlock()
if stub != nil {
return stub(arg1, arg2...)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeCredentials) NewPresentationCallCount() int {
fake.newPresentationMutex.RLock()
defer fake.newPresentationMutex.RUnlock()
return len(fake.newPresentationArgsForCall)
}
func (fake *FakeCredentials) NewPresentationCalls(stub func([]string, ...*verifiable.Credential) (*verifiable.Presentation, error)) {
fake.newPresentationMutex.Lock()
defer fake.newPresentationMutex.Unlock()
fake.NewPresentationStub = stub
}
func (fake *FakeCredentials) NewPresentationArgsForCall(i int) ([]string, []*verifiable.Credential) {
fake.newPresentationMutex.RLock()
defer fake.newPresentationMutex.RUnlock()
argsForCall := fake.newPresentationArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeCredentials) NewPresentationReturns(result1 *verifiable.Presentation, result2 error) {
fake.newPresentationMutex.Lock()
defer fake.newPresentationMutex.Unlock()
fake.NewPresentationStub = nil
fake.newPresentationReturns = struct {
result1 *verifiable.Presentation
result2 error
}{result1, result2}
}
func (fake *FakeCredentials) NewPresentationReturnsOnCall(i int, result1 *verifiable.Presentation, result2 error) {
fake.newPresentationMutex.Lock()
defer fake.newPresentationMutex.Unlock()
fake.NewPresentationStub = nil
if fake.newPresentationReturnsOnCall == nil {
fake.newPresentationReturnsOnCall = make(map[int]struct {
result1 *verifiable.Presentation
result2 error
})
}
fake.newPresentationReturnsOnCall[i] = struct {
result1 *verifiable.Presentation
result2 error
}{result1, result2}
}
func (fake *FakeCredentials) ParsePresentation(arg1 []byte) (*verifiable.Presentation, error) {
var arg1Copy []byte
if arg1 != nil {
......@@ -270,10 +98,6 @@ func (fake *FakeCredentials) ParsePresentationReturnsOnCall(i int, result1 *veri
func (fake *FakeCredentials) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.newCredentialMutex.RLock()
defer fake.newCredentialMutex.RUnlock()
fake.newPresentationMutex.RLock()
defer fake.newPresentationMutex.RUnlock()
fake.parsePresentationMutex.RLock()
defer fake.parsePresentationMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
......
......@@ -5,23 +5,25 @@ import (
"context"
"sync"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/infohub/internal/service/infohub"
)
type FakeSigner struct {
PresentationProofStub func(context.Context, *verifiable.Presentation) (*verifiable.Presentation, error)
presentationProofMutex sync.RWMutex
presentationProofArgsForCall []struct {
CreatePresentationStub func(context.Context, string, string, string, []map[string]interface{}) (map[string]interface{}, error)
createPresentationMutex sync.RWMutex
createPresentationArgsForCall []struct {
arg1 context.Context
arg2 *verifiable.Presentation
arg2 string
arg3 string
arg4 string
arg5 []map[string]interface{}
}
presentationProofReturns struct {
result1 *verifiable.Presentation
createPresentationReturns struct {
result1 map[string]interface{}
result2 error
}
presentationProofReturnsOnCall map[int]struct {
result1 *verifiable.Presentation
createPresentationReturnsOnCall map[int]struct {
result1 map[string]interface{}
result2 error
}
VerifyPresentationStub func(context.Context, []byte) error
......@@ -40,19 +42,27 @@ type FakeSigner struct {
invocationsMutex sync.RWMutex
}
func (fake *FakeSigner) PresentationProof(arg1 context.Context, arg2 *verifiable.Presentation) (*verifiable.Presentation, error) {
fake.presentationProofMutex.Lock()
ret, specificReturn := fake.presentationProofReturnsOnCall[len(fake.presentationProofArgsForCall)]
fake.presentationProofArgsForCall = append(fake.presentationProofArgsForCall, struct {
func (fake *FakeSigner) CreatePresentation(arg1 context.Context, arg2 string, arg3 string, arg4 string, arg5 []map[string]interface{}) (map[string]interface{}, error) {
var arg5Copy []map[string]interface{}
if arg5 != nil {
arg5Copy = make([]map[string]interface{}, len(arg5))
copy(arg5Copy, arg5)
}
fake.createPresentationMutex.Lock()
ret, specificReturn := fake.createPresentationReturnsOnCall[len(fake.createPresentationArgsForCall)]
fake.createPresentationArgsForCall = append(fake.createPresentationArgsForCall, struct {
arg1 context.Context
arg2 *verifiable.Presentation
}{arg1, arg2})
stub := fake.PresentationProofStub
fakeReturns := fake.presentationProofReturns
fake.recordInvocation("PresentationProof", []interface{}{arg1, arg2})
fake.presentationProofMutex.Unlock()
arg2 string
arg3 string
arg4 string
arg5 []map[string]interface{}
}{arg1, arg2, arg3, arg4, arg5Copy})
stub := fake.CreatePresentationStub
fakeReturns := fake.createPresentationReturns
fake.recordInvocation("CreatePresentation", []interface{}{arg1, arg2, arg3, arg4, arg5Copy})
fake.createPresentationMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
return stub(arg1, arg2, arg3, arg4, arg5)
}
if specificReturn {
return ret.result1, ret.result2
......@@ -60,47 +70,47 @@ func (fake *FakeSigner) PresentationProof(arg1 context.Context, arg2 *verifiable
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeSigner) PresentationProofCallCount() int {
fake.presentationProofMutex.RLock()
defer fake.presentationProofMutex.RUnlock()
return len(fake.presentationProofArgsForCall)
func (fake *FakeSigner) CreatePresentationCallCount() int {
fake.createPresentationMutex.RLock()
defer fake.createPresentationMutex.RUnlock()
return len(fake.createPresentationArgsForCall)
}
func (fake *FakeSigner) PresentationProofCalls(stub func(context.Context, *verifiable.Presentation) (*verifiable.Presentation, error)) {
fake.presentationProofMutex.Lock()
defer fake.presentationProofMutex.Unlock()
fake.PresentationProofStub = stub
func (fake *FakeSigner) CreatePresentationCalls(stub func(context.Context, string, string, string, []map[string]interface{}) (map[string]interface{}, error)) {
fake.createPresentationMutex.Lock()
defer fake.createPresentationMutex.Unlock()
fake.CreatePresentationStub = stub
}
func (fake *FakeSigner) PresentationProofArgsForCall(i int) (context.Context, *verifiable.Presentation) {
fake.presentationProofMutex.RLock()
defer fake.presentationProofMutex.RUnlock()
argsForCall := fake.presentationProofArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
func (fake *FakeSigner) CreatePresentationArgsForCall(i int) (context.Context, string, string, string, []map[string]interface{}) {
fake.createPresentationMutex.RLock()
defer fake.createPresentationMutex.RUnlock()
argsForCall := fake.createPresentationArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5
}
func (fake *FakeSigner) PresentationProofReturns(result1 *verifiable.Presentation, result2 error) {
fake.presentationProofMutex.Lock()
defer fake.presentationProofMutex.Unlock()
fake.PresentationProofStub = nil
fake.presentationProofReturns = struct {
result1 *verifiable.Presentation
func (fake *FakeSigner) CreatePresentationReturns(result1 map[string]interface{}, result2 error) {
fake.createPresentationMutex.Lock()
defer fake.createPresentationMutex.Unlock()
fake.CreatePresentationStub = nil
fake.createPresentationReturns = struct {
result1 map[string]interface{}
result2 error
}{result1, result2}
}
func (fake *FakeSigner) PresentationProofReturnsOnCall(i int, result1 *verifiable.Presentation, result2 error) {
fake.presentationProofMutex.Lock()
defer fake.presentationProofMutex.Unlock()
fake.PresentationProofStub = nil
if fake.presentationProofReturnsOnCall == nil {
fake.presentationProofReturnsOnCall = make(map[int]struct {
result1 *verifiable.Presentation
func (fake *FakeSigner) CreatePresentationReturnsOnCall(i int, result1 map[string]interface{}, result2 error) {
fake.createPresentationMutex.Lock()
defer fake.createPresentationMutex.Unlock()
fake.CreatePresentationStub = nil
if fake.createPresentationReturnsOnCall == nil {
fake.createPresentationReturnsOnCall = make(map[int]struct {
result1 map[string]interface{}
result2 error
})
}
fake.presentationProofReturnsOnCall[i] = struct {
result1 *verifiable.Presentation
fake.createPresentationReturnsOnCall[i] = struct {
result1 map[string]interface{}
result2 error
}{result1, result2}
}
......@@ -175,8 +185,8 @@ func (fake *FakeSigner) VerifyPresentationReturnsOnCall(i int, result1 error) {
func (fake *FakeSigner) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.presentationProofMutex.RLock()
defer fake.presentationProofMutex.RUnlock()
fake.createPresentationMutex.RLock()
defer fake.createPresentationMutex.RUnlock()
fake.verifyPresentationMutex.RLock()
defer fake.verifyPresentationMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
......
......@@ -35,13 +35,11 @@ type Cache interface {
}
type Credentials interface {
NewCredential(contexts []string, subjectID string, subject map[string]interface{}, proof bool) (*verifiable.Credential, error)
NewPresentation(contexts []string, credentials ...*verifiable.Credential) (*verifiable.Presentation, error)
ParsePresentation(vpBytes []byte) (*verifiable.Presentation, error)
}
type Signer interface {
PresentationProof(ctx context.Context, vp *verifiable.Presentation) (*verifiable.Presentation, error)
CreatePresentation(ctx context.Context, issuer, namespace, key string, data []map[string]interface{}) (map[string]interface{}, error)
VerifyPresentation(ctx context.Context, vp []byte) error
}
......@@ -150,35 +148,26 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter
return nil, err
}
// wrap each policy result in a verifiable credential
var creds []*verifiable.Credential
var results []map[string]interface{}
for policy, result := range policyResults {
var res map[string]interface{}
if err := json.Unmarshal(result, &res); err != nil {
logger.Error("error decoding policy result as json", zap.Error(err))
logger.Error("error decoding policy result as json", zap.Error(err), zap.String("policy", policy))
return nil, errors.New("error creating export", err)
}
// credentials do not include proof, because the final VP will include a proof for all
cred, err := s.credentials.NewCredential(exportCfg.Contexts, policy, res, false)
if err != nil {
logger.Error("failed to create verifiable credential", zap.Error(err))
return nil, errors.New("error creating export", err)
}
creds = append(creds, cred)
results = append(results, res)
}
// wrap all credentials in a verifiable presentation
vp, err := s.credentials.NewPresentation(exportCfg.Contexts, creds...)
if err != nil {
logger.Error("failed to create verifiable presentation", zap.Error(err))
return nil, errors.New("error creating export", err)
}
// get presentation proof from the signer
vp, err = s.signer.PresentationProof(ctx, vp)
// create verifiable presentation
vp, err := s.signer.CreatePresentation(
ctx,
exportCfg.Issuer,
exportCfg.KeyNamespace,
exportCfg.Key,
results,
)
if err != nil {
logger.Error("fail to get presentation proof", zap.Error(err))
logger.Error("error creating verifiable presentation", zap.Error(err))
return nil, errors.New("error creating export", err)
}
......@@ -190,6 +179,8 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter
// is returned.
// If all results are found, they are returned as map, where the key is policyName
// and the value is the JSON serialized bytes of the policy result.
//
// policyNames are formatted as 'group/policy/version' string, e.g. 'example/example/1.0'
func (s *Service) getExportData(ctx context.Context, exportName string, policyNames []string) (map[string][]byte, error) {
results := make(map[string][]byte)
for _, policy := range policyNames {
......
......@@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
......@@ -173,7 +172,7 @@ func TestService_Export(t *testing.T) {
errtext: "error creating export: invalid character",
},
{
name: "error creating verifiable credential for data",
name: "error creating verifiable presentation",
req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
......@@ -189,77 +188,16 @@ func TestService_Export(t *testing.T) {
return []byte(`{"allow":true}`), nil
},
},
cred: &infohubfakes.FakeCredentials{
NewCredentialStub: func(contexts []string, policy string, data map[string]interface{}, proof bool) (*verifiable.Credential, error) {
return nil, errors.New("cannot create credential")
},
},
errkind: errors.Unknown,
errtext: "cannot create credential",
},
{
name: "error creating verifiable presentation for data",
req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
return &storage.ExportConfiguration{
ExportName: "testexport",
Contexts: []string{"https://www.w3.org/2018/credentials/examples/v1"},
Policies: map[string]interface{}{"test/test/1.0": map[string]interface{}{"hello": "test world"}},
}, nil
},
},
cache: &infohubfakes.FakeCache{
GetStub: func(ctx context.Context, key string, namespace string, scope string) ([]byte, error) {
return []byte(`{"allow":true}`), nil
},
},
cred: &infohubfakes.FakeCredentials{
NewCredentialStub: func(contexts []string, policy string, data map[string]interface{}, proof bool) (*verifiable.Credential, error) {
return &verifiable.Credential{}, nil
},
NewPresentationStub: func(contexts []string, credentials ...*verifiable.Credential) (*verifiable.Presentation, error) {
return nil, errors.New("cannot create presentation")
},
},
errkind: errors.Unknown,
errtext: "cannot create presentation",
},
{
name: "error getting verifiable presentation proof",
req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
return &storage.ExportConfiguration{
ExportName: "testexport",
Contexts: []string{"https://www.w3.org/2018/credentials/examples/v1"},
Policies: map[string]interface{}{"test/test/1.0": map[string]interface{}{"hello": "test world"}},
}, nil
},
},
cache: &infohubfakes.FakeCache{
GetStub: func(ctx context.Context, key string, namespace string, scope string) ([]byte, error) {
return []byte(`{"allow":true}`), nil
},
},
cred: &infohubfakes.FakeCredentials{
NewCredentialStub: func(contexts []string, policy string, data map[string]interface{}, proof bool) (*verifiable.Credential, error) {
return &verifiable.Credential{}, nil
},
NewPresentationStub: func(contexts []string, credentials ...*verifiable.Credential) (*verifiable.Presentation, error) {
return &verifiable.Presentation{}, nil
},
},
signer: &infohubfakes.FakeSigner{
PresentationProofStub: func(ctx context.Context, presentation *verifiable.Presentation) (*verifiable.Presentation, error) {
return nil, errors.New(errors.ServiceUnavailable, "service unavailable")
CreatePresentationStub: func(ctx context.Context, issuer string, namespace string, key string, data []map[string]interface{}) (map[string]interface{}, error) {
return nil, errors.New("some error")
},
},
errkind: errors.ServiceUnavailable,
errtext: "service unavailable",
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "exported data is returned successfully",
name: "successfully create verifiable presentation",
req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
......@@ -275,20 +213,12 @@ func TestService_Export(t *testing.T) {
return []byte(`{"allow":true}`), nil
},
},
cred: &infohubfakes.FakeCredentials{
NewCredentialStub: func(contexts []string, policy string, data map[string]interface{}, proof bool) (*verifiable.Credential, error) {
return &verifiable.Credential{}, nil
},
NewPresentationStub: func(contexts []string, credentials ...*verifiable.Credential) (*verifiable.Presentation, error) {
return &verifiable.Presentation{}, nil
},
},
signer: &infohubfakes.FakeSigner{
PresentationProofStub: func(ctx context.Context, presentation *verifiable.Presentation) (*verifiable.Presentation, error) {
return &verifiable.Presentation{ID: "did:ocm"}, nil
CreatePresentationStub: func(ctx context.Context, issuer string, namespace string, key string, data []map[string]interface{}) (map[string]interface{}, error) {
return map[string]interface{}{"id": "did:web:example.com"}, nil
},
},
res: &verifiable.Presentation{ID: "did:ocm"},
res: map[string]interface{}{"id": "did:web:example.com"},
},
}
......
......@@ -12,10 +12,13 @@ import (
)
type ExportConfiguration struct {
ExportName string
Contexts []string
Policies map[string]interface{}
CacheTTL *int
ExportName string
Contexts []string
Policies map[string]interface{}
CacheTTL *int
Issuer string // issuer DID
KeyNamespace string // signing key namespace
Key string // signing key name
}
type Storage struct {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment