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
...@@ -16,7 +16,7 @@ include: ...@@ -16,7 +16,7 @@ include:
- template: 'Workflows/Branch-Pipelines.gitlab-ci.yml' - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
lint: lint:
image: golangci/golangci-lint:v1.44.2 image: golangci/golangci-lint:v1.50.1
stage: test stage: test
tags: tags:
- amd64-docker - amd64-docker
...@@ -28,12 +28,27 @@ lint: ...@@ -28,12 +28,27 @@ lint:
- cd /go/src/gitlab.com/${CI_PROJECT_PATH} - cd /go/src/gitlab.com/${CI_PROJECT_PATH}
unit tests: unit tests:
image: golang:1.17.7 image: golang:1.19.3
extends: .gotest extends: .gotest
stage: test stage: test
tags: tags:
- amd64-docker - amd64-docker
before_script: [] 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: amd64:
extends: .docker-build extends: .docker-build
......
...@@ -12,7 +12,6 @@ linters: ...@@ -12,7 +12,6 @@ linters:
enable: enable:
- megacheck - megacheck
- govet - govet
- deadcode
- errcheck - errcheck
- goconst - goconst
- gocyclo - gocyclo
...@@ -22,10 +21,9 @@ linters: ...@@ -22,10 +21,9 @@ linters:
- ineffassign - ineffassign
- nakedret - nakedret
- staticcheck - staticcheck
- structcheck
- unconvert - unconvert
- varcheck
- vet - vet
- vetshadow - vetshadow
- misspell - misspell
- staticcheck - staticcheck
- unused
...@@ -239,7 +239,7 @@ func exposeMetrics(addr string, logger *zap.Logger) { ...@@ -239,7 +239,7 @@ func exposeMetrics(addr string, logger *zap.Logger) {
promMux := http.NewServeMux() promMux := http.NewServeMux()
promMux.Handle("/metrics", promhttp.Handler()) promMux.Handle("/metrics", promhttp.Handler())
logger.Info(fmt.Sprintf("exposing prometheus metrics at %s/metrics", addr)) 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)) 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 RUN apk add git
......
FROM golang:1.19 FROM golang:1.19.3
ENV GO111MODULE=on ENV GO111MODULE=on
......
...@@ -4,19 +4,16 @@ import ( ...@@ -4,19 +4,16 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/piprate/json-gold/ld" "github.com/piprate/json-gold/ld"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/golib/errors" "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/golib/errors"
) )
const ( const (
presentationProofPath = "/v1/presentation/proof" createPresentationPath = "/v1/presentation"
presentationVerifyPath = "/v1/presentation/verify" presentationVerifyPath = "/v1/presentation/verify"
) )
...@@ -41,13 +38,20 @@ func New(addr string, opts ...ClientOption) *Client { ...@@ -41,13 +38,20 @@ func New(addr string, opts ...ClientOption) *Client {
return c return c
} }
func (c *Client) PresentationProof(ctx context.Context, vp *verifiable.Presentation) (*verifiable.Presentation, error) { func (c *Client) CreatePresentation(ctx context.Context, issuer, namespace, key string, data []map[string]interface{}) (map[string]interface{}, error) {
vpBytes, err := json.Marshal(vp) payload := map[string]interface{}{
"issuer": issuer,
"namespace": namespace,
"key": key,
"data": data,
}
payloadJSON, err := json.Marshal(payload)
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
...@@ -59,19 +63,15 @@ func (c *Client) PresentationProof(ctx context.Context, vp *verifiable.Presentat ...@@ -59,19 +63,15 @@ func (c *Client) PresentationProof(ctx context.Context, vp *verifiable.Presentat
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { 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) var presentation map[string]interface{}
if err != nil { if err := json.NewDecoder(resp.Body).Decode(&presentation); err != nil {
return nil, err return nil, errors.New("error decoding signer response as verifiable presentation", err)
} }
return verifiable.ParsePresentation( return presentation, nil
respBytes,
verifiable.WithPresJSONLDDocumentLoader(c.docLoader),
verifiable.WithPresDisabledProofCheck(),
)
} }
func (c *Client) VerifyPresentation(ctx context.Context, vp []byte) error { func (c *Client) VerifyPresentation(ctx context.Context, vp []byte) error {
...@@ -105,7 +105,7 @@ 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 { 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 { if err != nil {
return "" return ""
} }
......
...@@ -6,125 +6,107 @@ import ( ...@@ -6,125 +6,107 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/piprate/json-gold/ld"
"github.com/stretchr/testify/assert" "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" "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/infohub/internal/clients/signer"
) )
const invalidPresentation = `{"invalid":"verifiable_presentation"}` func TestClient_CreatePresentation(t *testing.T) {
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) {
tests := []struct { tests := []struct {
name string name string
ctx context.Context data []map[string]interface{}
vp *verifiable.Presentation
handler http.HandlerFunc handler http.HandlerFunc
result *verifiable.Presentation result map[string]interface{}
errkind errors.Kind
errtext string errtext string
}{ }{
{ {
name: "error creating http request because of nil context", name: "signer returns error",
errtext: "net/http: nil Context", 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", name: "signer successfully creates verifiable presentation",
ctx: context.Background(), data: []map[string]interface{}{{"hello": "world"}},
handler: func(w http.ResponseWriter, r *http.Request) { 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", name: "signer returns error",
ctx: context.Background(), vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) { 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", name: "signer returns unexpected response",
ctx: context.Background(), vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) { handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) 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", name: "signer returns successfully",
ctx: context.Background(), vp: []byte(`{"id":"did:web:example.com"}`),
handler: func(w http.ResponseWriter, r *http.Request) { handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(validPresentation)) _, _ = w.Write([]byte(`{"id":"did:web:example.com"}`))
}, },
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
signerSrv := httptest.NewServer(test.handler) srv := httptest.NewServer(test.handler)
client := signer.New(signerSrv.URL, signer.WithHTTPClient(http.DefaultClient)) client := signer.New(srv.URL)
result, err := client.PresentationProof(test.ctx, test.vp) err := client.VerifyPresentation(context.Background(), test.vp)
if err != nil { if err != nil {
assert.Nil(t, result)
assert.NotEmpty(t, test.errtext)
assert.Contains(t, err.Error(), test.errtext) assert.Contains(t, err.Error(), test.errtext)
} else { } else {
assert.Empty(t, test.errtext) 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 ( ...@@ -9,36 +9,6 @@ import (
) )
type FakeCredentials struct { 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) ParsePresentationStub func([]byte) (*verifiable.Presentation, error)
parsePresentationMutex sync.RWMutex parsePresentationMutex sync.RWMutex
parsePresentationArgsForCall []struct { parsePresentationArgsForCall []struct {
...@@ -56,148 +26,6 @@ type FakeCredentials struct { ...@@ -56,148 +26,6 @@ type FakeCredentials struct {
invocationsMutex sync.RWMutex 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) { func (fake *FakeCredentials) ParsePresentation(arg1 []byte) (*verifiable.Presentation, error) {
var arg1Copy []byte var arg1Copy []byte
if arg1 != nil { if arg1 != nil {
...@@ -270,10 +98,6 @@ func (fake *FakeCredentials) ParsePresentationReturnsOnCall(i int, result1 *veri ...@@ -270,10 +98,6 @@ func (fake *FakeCredentials) ParsePresentationReturnsOnCall(i int, result1 *veri
func (fake *FakeCredentials) Invocations() map[string][][]interface{} { func (fake *FakeCredentials) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock() fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock() defer fake.invocationsMutex.RUnlock()
fake.newCredentialMutex.RLock()
defer fake.newCredentialMutex.RUnlock()
fake.newPresentationMutex.RLock()
defer fake.newPresentationMutex.RUnlock()
fake.parsePresentationMutex.RLock() fake.parsePresentationMutex.RLock()
defer fake.parsePresentationMutex.RUnlock() defer fake.parsePresentationMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{} copiedInvocations := map[string][][]interface{}{}
......
...@@ -5,23 +5,25 @@ import ( ...@@ -5,23 +5,25 @@ import (
"context" "context"
"sync" "sync"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/infohub/internal/service/infohub" "gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/infohub/internal/service/infohub"
) )
type FakeSigner struct { type FakeSigner struct {
PresentationProofStub func(context.Context, *verifiable.Presentation) (*verifiable.Presentation, error) CreatePresentationStub func(context.Context, string, string, string, []map[string]interface{}) (map[string]interface{}, error)
presentationProofMutex sync.RWMutex createPresentationMutex sync.RWMutex
presentationProofArgsForCall []struct { createPresentationArgsForCall []struct {
arg1 context.Context arg1 context.Context
arg2 *verifiable.Presentation arg2 string
arg3 string
arg4 string
arg5 []map[string]interface{}
} }
presentationProofReturns struct { createPresentationReturns struct {
result1 *verifiable.Presentation result1 map[string]interface{}
result2 error result2 error
} }
presentationProofReturnsOnCall map[int]struct { createPresentationReturnsOnCall map[int]struct {
result1 *verifiable.Presentation result1 map[string]interface{}
result2 error result2 error
} }
VerifyPresentationStub func(context.Context, []byte) error VerifyPresentationStub func(context.Context, []byte) error
...@@ -40,19 +42,27 @@ type FakeSigner struct { ...@@ -40,19 +42,27 @@ type FakeSigner struct {
invocationsMutex sync.RWMutex invocationsMutex sync.RWMutex
} }
func (fake *FakeSigner) PresentationProof(arg1 context.Context, arg2 *verifiable.Presentation) (*verifiable.Presentation, error) { func (fake *FakeSigner) CreatePresentation(arg1 context.Context, arg2 string, arg3 string, arg4 string, arg5 []map[string]interface{}) (map[string]interface{}, error) {
fake.presentationProofMutex.Lock() var arg5Copy []map[string]interface{}
ret, specificReturn := fake.presentationProofReturnsOnCall[len(fake.presentationProofArgsForCall)] if arg5 != nil {
fake.presentationProofArgsForCall = append(fake.presentationProofArgsForCall, struct { 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 arg1 context.Context
arg2 *verifiable.Presentation arg2 string
}{arg1, arg2}) arg3 string
stub := fake.PresentationProofStub arg4 string
fakeReturns := fake.presentationProofReturns arg5 []map[string]interface{}
fake.recordInvocation("PresentationProof", []interface{}{arg1, arg2}) }{arg1, arg2, arg3, arg4, arg5Copy})
fake.presentationProofMutex.Unlock() stub := fake.CreatePresentationStub
fakeReturns := fake.createPresentationReturns
fake.recordInvocation("CreatePresentation", []interface{}{arg1, arg2, arg3, arg4, arg5Copy})
fake.createPresentationMutex.Unlock()
if stub != nil { if stub != nil {
return stub(arg1, arg2) return stub(arg1, arg2, arg3, arg4, arg5)
} }
if specificReturn { if specificReturn {
return ret.result1, ret.result2 return ret.result1, ret.result2
...@@ -60,47 +70,47 @@ func (fake *FakeSigner) PresentationProof(arg1 context.Context, arg2 *verifiable ...@@ -60,47 +70,47 @@ func (fake *FakeSigner) PresentationProof(arg1 context.Context, arg2 *verifiable
return fakeReturns.result1, fakeReturns.result2 return fakeReturns.result1, fakeReturns.result2
} }
func (fake *FakeSigner) PresentationProofCallCount() int { func (fake *FakeSigner) CreatePresentationCallCount() int {
fake.presentationProofMutex.RLock() fake.createPresentationMutex.RLock()
defer fake.presentationProofMutex.RUnlock() defer fake.createPresentationMutex.RUnlock()
return len(fake.presentationProofArgsForCall) return len(fake.createPresentationArgsForCall)
} }
func (fake *FakeSigner) PresentationProofCalls(stub func(context.Context, *verifiable.Presentation) (*verifiable.Presentation, error)) { func (fake *FakeSigner) CreatePresentationCalls(stub func(context.Context, string, string, string, []map[string]interface{}) (map[string]interface{}, error)) {
fake.presentationProofMutex.Lock() fake.createPresentationMutex.Lock()
defer fake.presentationProofMutex.Unlock() defer fake.createPresentationMutex.Unlock()
fake.PresentationProofStub = stub fake.CreatePresentationStub = stub
} }
func (fake *FakeSigner) PresentationProofArgsForCall(i int) (context.Context, *verifiable.Presentation) { func (fake *FakeSigner) CreatePresentationArgsForCall(i int) (context.Context, string, string, string, []map[string]interface{}) {
fake.presentationProofMutex.RLock() fake.createPresentationMutex.RLock()
defer fake.presentationProofMutex.RUnlock() defer fake.createPresentationMutex.RUnlock()
argsForCall := fake.presentationProofArgsForCall[i] argsForCall := fake.createPresentationArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2 return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5
} }
func (fake *FakeSigner) PresentationProofReturns(result1 *verifiable.Presentation, result2 error) { func (fake *FakeSigner) CreatePresentationReturns(result1 map[string]interface{}, result2 error) {
fake.presentationProofMutex.Lock() fake.createPresentationMutex.Lock()
defer fake.presentationProofMutex.Unlock() defer fake.createPresentationMutex.Unlock()
fake.PresentationProofStub = nil fake.CreatePresentationStub = nil
fake.presentationProofReturns = struct { fake.createPresentationReturns = struct {
result1 *verifiable.Presentation result1 map[string]interface{}
result2 error result2 error
}{result1, result2} }{result1, result2}
} }
func (fake *FakeSigner) PresentationProofReturnsOnCall(i int, result1 *verifiable.Presentation, result2 error) { func (fake *FakeSigner) CreatePresentationReturnsOnCall(i int, result1 map[string]interface{}, result2 error) {
fake.presentationProofMutex.Lock() fake.createPresentationMutex.Lock()
defer fake.presentationProofMutex.Unlock() defer fake.createPresentationMutex.Unlock()
fake.PresentationProofStub = nil fake.CreatePresentationStub = nil
if fake.presentationProofReturnsOnCall == nil { if fake.createPresentationReturnsOnCall == nil {
fake.presentationProofReturnsOnCall = make(map[int]struct { fake.createPresentationReturnsOnCall = make(map[int]struct {
result1 *verifiable.Presentation result1 map[string]interface{}
result2 error result2 error
}) })
} }
fake.presentationProofReturnsOnCall[i] = struct { fake.createPresentationReturnsOnCall[i] = struct {
result1 *verifiable.Presentation result1 map[string]interface{}
result2 error result2 error
}{result1, result2} }{result1, result2}
} }
...@@ -175,8 +185,8 @@ func (fake *FakeSigner) VerifyPresentationReturnsOnCall(i int, result1 error) { ...@@ -175,8 +185,8 @@ func (fake *FakeSigner) VerifyPresentationReturnsOnCall(i int, result1 error) {
func (fake *FakeSigner) Invocations() map[string][][]interface{} { func (fake *FakeSigner) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock() fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock() defer fake.invocationsMutex.RUnlock()
fake.presentationProofMutex.RLock() fake.createPresentationMutex.RLock()
defer fake.presentationProofMutex.RUnlock() defer fake.createPresentationMutex.RUnlock()
fake.verifyPresentationMutex.RLock() fake.verifyPresentationMutex.RLock()
defer fake.verifyPresentationMutex.RUnlock() defer fake.verifyPresentationMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{} copiedInvocations := map[string][][]interface{}{}
......
...@@ -35,13 +35,11 @@ type Cache interface { ...@@ -35,13 +35,11 @@ type Cache interface {
} }
type Credentials 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) ParsePresentation(vpBytes []byte) (*verifiable.Presentation, error)
} }
type Signer interface { 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 VerifyPresentation(ctx context.Context, vp []byte) error
} }
...@@ -150,35 +148,26 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter ...@@ -150,35 +148,26 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter
return nil, err return nil, err
} }
// wrap each policy result in a verifiable credential var results []map[string]interface{}
var creds []*verifiable.Credential
for policy, result := range policyResults { for policy, result := range policyResults {
var res map[string]interface{} var res map[string]interface{}
if err := json.Unmarshal(result, &res); err != nil { 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) return nil, errors.New("error creating export", err)
} }
results = append(results, res)
// 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)
} }
// wrap all credentials in a verifiable presentation // create verifiable presentation
vp, err := s.credentials.NewPresentation(exportCfg.Contexts, creds...) vp, err := s.signer.CreatePresentation(
if err != nil { ctx,
logger.Error("failed to create verifiable presentation", zap.Error(err)) exportCfg.Issuer,
return nil, errors.New("error creating export", err) exportCfg.KeyNamespace,
} exportCfg.Key,
results,
// get presentation proof from the signer )
vp, err = s.signer.PresentationProof(ctx, vp)
if err != nil { 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) return nil, errors.New("error creating export", err)
} }
...@@ -190,6 +179,8 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter ...@@ -190,6 +179,8 @@ func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (inter
// is returned. // is returned.
// If all results are found, they are returned as map, where the key is policyName // 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. // 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) { func (s *Service) getExportData(ctx context.Context, exportName string, policyNames []string) (map[string][]byte, error) {
results := make(map[string][]byte) results := make(map[string][]byte)
for _, policy := range policyNames { for _, policy := range policyNames {
......
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"context" "context"
"testing" "testing"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/zap" "go.uber.org/zap"
...@@ -173,7 +172,7 @@ func TestService_Export(t *testing.T) { ...@@ -173,7 +172,7 @@ func TestService_Export(t *testing.T) {
errtext: "error creating export: invalid character", errtext: "error creating export: invalid character",
}, },
{ {
name: "error creating verifiable credential for data", name: "error creating verifiable presentation",
req: &goasigner.ExportRequest{ExportName: "testexport"}, req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{ storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) { ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
...@@ -189,77 +188,16 @@ func TestService_Export(t *testing.T) { ...@@ -189,77 +188,16 @@ func TestService_Export(t *testing.T) {
return []byte(`{"allow":true}`), nil 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{ signer: &infohubfakes.FakeSigner{
PresentationProofStub: func(ctx context.Context, presentation *verifiable.Presentation) (*verifiable.Presentation, error) { CreatePresentationStub: func(ctx context.Context, issuer string, namespace string, key string, data []map[string]interface{}) (map[string]interface{}, error) {
return nil, errors.New(errors.ServiceUnavailable, "service unavailable") return nil, errors.New("some error")
}, },
}, },
errkind: errors.ServiceUnavailable, errkind: errors.Unknown,
errtext: "service unavailable", errtext: "some error",
}, },
{ {
name: "exported data is returned successfully", name: "successfully create verifiable presentation",
req: &goasigner.ExportRequest{ExportName: "testexport"}, req: &goasigner.ExportRequest{ExportName: "testexport"},
storage: &infohubfakes.FakeStorage{ storage: &infohubfakes.FakeStorage{
ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) { ExportConfigurationStub: func(ctx context.Context, s string) (*storage.ExportConfiguration, error) {
...@@ -275,20 +213,12 @@ func TestService_Export(t *testing.T) { ...@@ -275,20 +213,12 @@ func TestService_Export(t *testing.T) {
return []byte(`{"allow":true}`), nil 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{ signer: &infohubfakes.FakeSigner{
PresentationProofStub: func(ctx context.Context, presentation *verifiable.Presentation) (*verifiable.Presentation, error) { CreatePresentationStub: func(ctx context.Context, issuer string, namespace string, key string, data []map[string]interface{}) (map[string]interface{}, error) {
return &verifiable.Presentation{ID: "did:ocm"}, nil 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 ( ...@@ -12,10 +12,13 @@ import (
) )
type ExportConfiguration struct { type ExportConfiguration struct {
ExportName string ExportName string
Contexts []string Contexts []string
Policies map[string]interface{} Policies map[string]interface{}
CacheTTL *int CacheTTL *int
Issuer string // issuer DID
KeyNamespace string // signing key namespace
Key string // signing key name
} }
type Storage struct { type Storage struct {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment