Skip to content

Commit

Permalink
Merge branch 'master' into discovery/update-clients
Browse files Browse the repository at this point in the history
  • Loading branch information
reinkrul committed Jan 16, 2024
2 parents cac5a03 + 3a3032d commit 5a1ad24
Show file tree
Hide file tree
Showing 53 changed files with 2,651 additions and 502 deletions.
156 changes: 78 additions & 78 deletions README.rst

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion auth/api/iam/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,13 @@ func (auth *Auth) Configure(config core.ServerConfig) error {
return err
}

clientTimeout := time.Duration(auth.config.HTTPTimeout) * time.Second
var clientTimeout time.Duration
if auth.config.HTTPTimeout >= 0 {
clientTimeout = time.Duration(auth.config.HTTPTimeout) * time.Second
} else {
// auth.http.config got deprecated in favor of httpclient.timeout
clientTimeout = config.HTTPClient.Timeout
}
accessTokenLifeSpan := time.Duration(auth.config.AccessTokenLifeSpan) * time.Second
auth.authzServer = oauth.NewAuthorizationServer(auth.vdrInstance.Resolver(), auth.vcr, auth.vcr.Verifier(), auth.serviceResolver,
auth.keyStore, auth.contractNotary, auth.jsonldManager, accessTokenLifeSpan)
Expand Down
28 changes: 20 additions & 8 deletions auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,29 @@ func TestAuth_Configure(t *testing.T) {

require.NoError(t, i.Configure(tlsServerConfig))
})
t.Run("use legacy auth.http.timeout config", func(t *testing.T) {
config := DefaultConfig()
config.HTTPTimeout = 10
config.ContractValidators = []string{"uzi"}
ctrl := gomock.NewController(t)
pkiMock := pki.NewMockProvider(ctrl)
pkiMock.EXPECT().AddTruststore(gomock.Any()) // uzi
pkiMock.EXPECT().CreateTLSConfig(gomock.Any()) // tlsConfig
vdrInstance := vdr.NewMockVDR(ctrl)
vdrInstance.EXPECT().Resolver().AnyTimes()

i := NewAuthInstance(config, vdrInstance, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(), nil, nil, pkiMock)

require.NoError(t, i.Configure(tlsServerConfig))
})

t.Run("error - IRMA config failure", func(t *testing.T) {
authCfg := TestConfig()
authCfg.Irma.SchemeManager = "non-existing"
serverConfig := tlsServerConfig
serverConfig.Strictmode = false
i := testInstance(t, authCfg)
err := i.Configure(tlsServerConfig)
err := i.Configure(serverConfig)
require.NoError(t, err)
})

Expand All @@ -73,19 +90,14 @@ func TestAuth_Configure(t *testing.T) {
authCfg := TestConfig()
authCfg.Irma.SchemeManager = "demo"
i := testInstance(t, authCfg)
serverConfig := core.NewServerConfig()
serverConfig.Strictmode = true
err := i.Configure(*serverConfig)
err := i.Configure(tlsServerConfig)
assert.EqualError(t, err, "in strictmode the only valid irma-scheme-manager is 'pbdf'")
})

t.Run("error - TLS required in strict mode", func(t *testing.T) {
authCfg := TestConfig()
i := testInstance(t, authCfg)
serverConfig := core.NewServerConfig()
serverConfig.Strictmode = true
serverConfig.URL = "https://nuts.nl"
err := i.Configure(*serverConfig)
err := i.Configure(core.TestServerConfig())
assert.EqualError(t, err, "in strictmode TLS must be enabled")
})

Expand Down
1 change: 1 addition & 0 deletions auth/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func FlagSet() *pflag.FlagSet {
flags.StringSlice(ConfContractValidators, defs.ContractValidators, "sets the different contract validators to use")
flags.Bool(ConfV2APIEnabled, defs.V2APIEnabled, "enables experimental v2 API endpoints")
_ = flags.MarkHidden(ConfV2APIEnabled)
_ = flags.MarkDeprecated("auth.http.timeout", "use httpclient.timeout instead")

return flags
}
1 change: 0 additions & 1 deletion auth/cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func TestFlagSet(t *testing.T) {
func TestIrmaConfigInjection(t *testing.T) {
serverCfg := core.NewServerConfig()
serverCfg.Verbosity = "debug"
serverCfg.LoggerFormat = "text"
t.Setenv("NUTS_AUTH_IRMA_SCHEMEMANAGER", "irma-demo")
t.Setenv("NUTS_AUTH_IRMA_AUTOUPDATESCHEMES", "true")
err := serverCfg.Load(FlagSet())
Expand Down
3 changes: 1 addition & 2 deletions auth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ func DefaultConfig() Config {
SchemeManager: "pbdf",
AutoUpdateSchemas: true,
},
HTTPTimeout: 30,
ClockSkew: 5000,
ClockSkew: 5000,
ContractValidators: []string{
string(services.IrmaFormat),
uzi.ContractFormat,
Expand Down
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func CreateSystem(shutdownCallback context.CancelFunc) *core.System {
vdrInstance := vdr.NewVDR(cryptoInstance, networkInstance, didStore, eventManager, storageInstance)
credentialInstance := vcr.NewVCRInstance(cryptoInstance, vdrInstance, networkInstance, jsonld, eventManager, storageInstance, pkiInstance)
didmanInstance := didman.NewDidmanInstance(vdrInstance, credentialInstance, jsonld)
discoveryInstance := discovery.New(storageInstance, credentialInstance)
discoveryInstance := discovery.New(storageInstance, credentialInstance, vdrInstance)
authInstance := auth.NewAuthInstance(auth.DefaultConfig(), vdrInstance, credentialInstance, cryptoInstance, didmanInstance, jsonld, pkiInstance)
statusEngine := status.NewStatusEngine(system)
metricsEngine := core.NewMetricsEngine()
Expand Down Expand Up @@ -224,7 +224,7 @@ func CreateSystem(shutdownCallback context.CancelFunc) *core.System {
system.RegisterRoutes(authIAMAPI.New(authInstance, credentialInstance, vdrInstance, storageInstance, policyInstance))
system.RegisterRoutes(&authMeansAPI.Wrapper{Auth: authInstance})
system.RegisterRoutes(&didmanAPI.Wrapper{Didman: didmanInstance})
system.RegisterRoutes(&discoveryAPI.Wrapper{Server: discoveryInstance})
system.RegisterRoutes(&discoveryAPI.Wrapper{Server: discoveryInstance, Client: discoveryInstance})

// Register engines
// without dependencies
Expand Down
11 changes: 5 additions & 6 deletions core/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ type TestEngineConfig struct {
}

// TestServerConfig returns a new ServerConfig with the given template applied.
func TestServerConfig(template ServerConfig) ServerConfig {
func TestServerConfig(visitors ...func(*ServerConfig)) ServerConfig {
config := NewServerConfig()
// Most commonly used properties
config.Datadir = template.Datadir
config.Strictmode = template.Strictmode
config.InternalRateLimiter = template.InternalRateLimiter
config.URL = template.URL
config.URL = "https://nuts.nl"
for _, visitor := range visitors {
visitor(config)
}
return *config
}

Expand Down
11 changes: 6 additions & 5 deletions crypto/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,18 @@ func TestCrypto_setupBackend(t *testing.T) {

func TestCrypto_Configure(t *testing.T) {
directory := io.TestDirectory(t)
cfg := *core.NewServerConfig()
cfg.Datadir = directory
t.Run("ok", func(t *testing.T) {
cfg := core.TestServerConfig(func(config *core.ServerConfig) {
config.Datadir = directory
})
t.Run("default backend (fs) can be used in non-strictmode", func(t *testing.T) {
e := createCrypto(t)
cfg := cfg
cfg.Strictmode = false
err := e.Configure(cfg)
assert.NoError(t, err)
})
t.Run("error - no backend in strict mode is now allowed", func(t *testing.T) {
client := createCrypto(t)
cfg := cfg
cfg.Strictmode = true
err := client.Configure(cfg)
assert.EqualError(t, err, "backend must be explicitly set in strict mode", "expected error")
})
Expand Down
44 changes: 43 additions & 1 deletion discovery/api/v1/wrapper.go → discovery/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"context"
"errors"
"github.com/labstack/echo/v4"
"github.com/nuts-foundation/go-did/did"
"github.com/nuts-foundation/nuts-node/audit"
"github.com/nuts-foundation/nuts-node/core"
"github.com/nuts-foundation/nuts-node/discovery"
"net/http"
Expand Down Expand Up @@ -56,6 +58,9 @@ func (w *Wrapper) Routes(router core.EchoRouter) {
return f(ctx, request)
}
},
func(f StrictHandlerFunc, operationID string) StrictHandlerFunc {
return audit.StrictMiddleware(f, discovery.ModuleName, operationID)
},
}))
}

Expand All @@ -77,7 +82,7 @@ func (w *Wrapper) GetPresentations(_ context.Context, request GetPresentationsRe
}

func (w *Wrapper) RegisterPresentation(_ context.Context, request RegisterPresentationRequestObject) (RegisterPresentationResponseObject, error) {
err := w.Server.Add(request.ServiceID, *request.Body)
err := w.Server.Register(request.ServiceID, *request.Body)
if err != nil {
return nil, err
}
Expand All @@ -99,3 +104,40 @@ func (w *Wrapper) SearchPresentations(_ context.Context, request SearchPresentat
}
return SearchPresentations200JSONResponse(result), nil
}

func (w *Wrapper) ActivateServiceForDID(ctx context.Context, request ActivateServiceForDIDRequestObject) (ActivateServiceForDIDResponseObject, error) {
subjectDID, err := did.ParseDID(request.Did)
if err != nil {
return nil, err
}
err = w.Client.ActivateServiceForDID(ctx, request.ServiceID, *subjectDID)
if errors.Is(err, discovery.ErrPresentationRegistrationFailed) {
// registration failed, but will be retried
return ActivateServiceForDID202JSONResponse{
Reason: err.Error(),
}, nil
}
if err != nil {
// other error
return nil, err
}
return ActivateServiceForDID200Response{}, nil
}

func (w *Wrapper) DeactivateServiceForDID(ctx context.Context, request DeactivateServiceForDIDRequestObject) (DeactivateServiceForDIDResponseObject, error) {
subjectDID, err := did.ParseDID(request.Did)
if err != nil {
return nil, err
}
err = w.Client.DeactivateServiceForDID(ctx, request.ServiceID, *subjectDID)
if errors.Is(err, discovery.ErrPresentationRegistrationFailed) {
// deactivation succeeded, but Verifiable Presentation couldn't be removed from remote Discovery Server.
return DeactivateServiceForDID202JSONResponse{
Reason: err.Error(),
}, nil
}
if err != nil {
return nil, err
}
return DeactivateServiceForDID200Response{}, nil
}
74 changes: 72 additions & 2 deletions discovery/api/v1/wrapper_test.go → discovery/api/v1/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package v1
import (
"errors"
ssi "github.com/nuts-foundation/go-did"
"github.com/nuts-foundation/go-did/did"
"github.com/nuts-foundation/go-did/vc"
"github.com/nuts-foundation/nuts-node/discovery"
"github.com/nuts-foundation/nuts-node/vcr/credential"
Expand Down Expand Up @@ -80,7 +81,7 @@ func TestWrapper_RegisterPresentation(t *testing.T) {
t.Run("ok", func(t *testing.T) {
test := newMockContext(t)
presentation := vc.VerifiablePresentation{}
test.server.EXPECT().Add(serviceID, presentation).Return(nil)
test.server.EXPECT().Register(serviceID, presentation).Return(nil)

response, err := test.wrapper.RegisterPresentation(nil, RegisterPresentationRequestObject{
ServiceID: serviceID,
Expand All @@ -93,7 +94,7 @@ func TestWrapper_RegisterPresentation(t *testing.T) {
t.Run("error", func(t *testing.T) {
test := newMockContext(t)
presentation := vc.VerifiablePresentation{}
test.server.EXPECT().Add(serviceID, presentation).Return(discovery.ErrInvalidPresentation)
test.server.EXPECT().Register(serviceID, presentation).Return(discovery.ErrInvalidPresentation)

_, err := test.wrapper.RegisterPresentation(nil, RegisterPresentationRequestObject{
ServiceID: serviceID,
Expand All @@ -104,6 +105,75 @@ func TestWrapper_RegisterPresentation(t *testing.T) {
})
}

func TestWrapper_ActivateServiceForDID(t *testing.T) {
t.Run("ok", func(t *testing.T) {
test := newMockContext(t)
expectedDID := "did:web:example.com"
test.client.EXPECT().ActivateServiceForDID(gomock.Any(), serviceID, did.MustParseDID(expectedDID)).Return(nil)

response, err := test.wrapper.ActivateServiceForDID(nil, ActivateServiceForDIDRequestObject{
ServiceID: serviceID,
Did: expectedDID,
})

assert.NoError(t, err)
assert.IsType(t, ActivateServiceForDID200Response{}, response)
})
t.Run("ok, but registration failed", func(t *testing.T) {
test := newMockContext(t)
expectedDID := "did:web:example.com"
test.client.EXPECT().ActivateServiceForDID(gomock.Any(), gomock.Any(), gomock.Any()).Return(discovery.ErrPresentationRegistrationFailed)

response, err := test.wrapper.ActivateServiceForDID(nil, ActivateServiceForDIDRequestObject{
ServiceID: serviceID,
Did: expectedDID,
})

assert.NoError(t, err)
assert.IsType(t, ActivateServiceForDID202JSONResponse{}, response)
})
t.Run("other error", func(t *testing.T) {
test := newMockContext(t)
expectedDID := "did:web:example.com"
test.client.EXPECT().ActivateServiceForDID(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("foo"))

_, err := test.wrapper.ActivateServiceForDID(nil, ActivateServiceForDIDRequestObject{
ServiceID: serviceID,
Did: expectedDID,
})

assert.Error(t, err)
})
}

func TestWrapper_DeactivateServiceForDID(t *testing.T) {
t.Run("ok", func(t *testing.T) {
test := newMockContext(t)
expectedDID := "did:web:example.com"
test.client.EXPECT().DeactivateServiceForDID(gomock.Any(), serviceID, did.MustParseDID(expectedDID)).Return(nil)

response, err := test.wrapper.DeactivateServiceForDID(nil, DeactivateServiceForDIDRequestObject{
ServiceID: serviceID,
Did: expectedDID,
})

assert.NoError(t, err)
assert.IsType(t, DeactivateServiceForDID200Response{}, response)
})
t.Run("error", func(t *testing.T) {
test := newMockContext(t)
expectedDID := "did:web:example.com"
test.client.EXPECT().DeactivateServiceForDID(gomock.Any(), serviceID, did.MustParseDID(expectedDID)).Return(errors.New("foo"))

_, err := test.wrapper.DeactivateServiceForDID(nil, DeactivateServiceForDIDRequestObject{
ServiceID: serviceID,
Did: expectedDID,
})

assert.Error(t, err)
})
}

func TestWrapper_ResolveStatusCode(t *testing.T) {
expected := map[error]int{
discovery.ErrServerModeDisabled: http.StatusBadRequest,
Expand Down
13 changes: 6 additions & 7 deletions discovery/api/v1/client/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ func TestHTTPInvoker_Get(t *testing.T) {
server := httptest.NewServer(handler)
client := New(false, time.Minute, server.TLS)

presentations, tag, err := client.Get(context.Background(), server.URL, nil)
presentations, tag, err := client.Get(context.Background(), server.URL, "")

assert.NoError(t, err)
assert.Len(t, presentations, 1)
assert.Empty(t, handler.RequestQuery.Get("tag"))
assert.Equal(t, serverTag, *tag)
assert.Equal(t, serverTag, tag)
})
t.Run("tag provided by client", func(t *testing.T) {
handler := &testHTTP.Handler{StatusCode: http.StatusOK}
Expand All @@ -88,20 +88,19 @@ func TestHTTPInvoker_Get(t *testing.T) {
server := httptest.NewServer(handler)
client := New(false, time.Minute, server.TLS)

inputTag := clientTag
presentations, tag, err := client.Get(context.Background(), server.URL, &inputTag)
presentations, tag, err := client.Get(context.Background(), server.URL, clientTag)

assert.NoError(t, err)
assert.Len(t, presentations, 1)
assert.Equal(t, clientTag, handler.RequestQuery.Get("tag"))
assert.Equal(t, serverTag, *tag)
assert.Equal(t, serverTag, tag)
})
t.Run("server returns invalid status code", func(t *testing.T) {
handler := &testHTTP.Handler{StatusCode: http.StatusInternalServerError}
server := httptest.NewServer(handler)
client := New(false, time.Minute, server.TLS)

_, _, err := client.Get(context.Background(), server.URL, nil)
_, _, err := client.Get(context.Background(), server.URL, "")

assert.ErrorContains(t, err, "non-OK response from remote Discovery Service")
})
Expand All @@ -111,7 +110,7 @@ func TestHTTPInvoker_Get(t *testing.T) {
server := httptest.NewServer(handler)
client := New(false, time.Minute, server.TLS)

_, _, err := client.Get(context.Background(), server.URL, nil)
_, _, err := client.Get(context.Background(), server.URL, "")

assert.ErrorContains(t, err, "failed to unmarshal response from remote Discovery Service")
})
Expand Down
Loading

0 comments on commit 5a1ad24

Please sign in to comment.