Skip to content

Commit a5febda

Browse files
authored
Config: Add HTTP-client timeout (#2725)
1 parent e4f0635 commit a5febda

File tree

19 files changed

+318
-228
lines changed

19 files changed

+318
-228
lines changed

README.rst

Lines changed: 76 additions & 75 deletions
Large diffs are not rendered by default.

auth/auth.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,13 @@ func (auth *Auth) Configure(config core.ServerConfig) error {
156156
return err
157157
}
158158

159-
clientTimeout := time.Duration(auth.config.HTTPTimeout) * time.Second
159+
var clientTimeout time.Duration
160+
if auth.config.HTTPTimeout >= 0 {
161+
clientTimeout = time.Duration(auth.config.HTTPTimeout) * time.Second
162+
} else {
163+
// auth.http.config got deprecated in favor of httpclient.timeout
164+
clientTimeout = config.HTTPClient.Timeout
165+
}
160166
accessTokenLifeSpan := time.Duration(auth.config.AccessTokenLifeSpan) * time.Second
161167
auth.authzServer = oauth.NewAuthorizationServer(auth.vdrInstance.Resolver(), auth.vcr, auth.vcr.Verifier(), auth.serviceResolver,
162168
auth.keyStore, auth.contractNotary, auth.jsonldManager, accessTokenLifeSpan)

auth/auth_test.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,29 @@ func TestAuth_Configure(t *testing.T) {
5252

5353
require.NoError(t, i.Configure(tlsServerConfig))
5454
})
55+
t.Run("use legacy auth.http.timeout config", func(t *testing.T) {
56+
config := DefaultConfig()
57+
config.HTTPTimeout = 10
58+
config.ContractValidators = []string{"uzi"}
59+
ctrl := gomock.NewController(t)
60+
pkiMock := pki.NewMockProvider(ctrl)
61+
pkiMock.EXPECT().AddTruststore(gomock.Any()) // uzi
62+
pkiMock.EXPECT().CreateTLSConfig(gomock.Any()) // tlsConfig
63+
vdrInstance := vdr.NewMockVDR(ctrl)
64+
vdrInstance.EXPECT().Resolver().AnyTimes()
65+
66+
i := NewAuthInstance(config, vdrInstance, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(), nil, nil, pkiMock)
67+
68+
require.NoError(t, i.Configure(tlsServerConfig))
69+
})
5570

5671
t.Run("error - IRMA config failure", func(t *testing.T) {
5772
authCfg := TestConfig()
5873
authCfg.Irma.SchemeManager = "non-existing"
74+
serverConfig := tlsServerConfig
75+
serverConfig.Strictmode = false
5976
i := testInstance(t, authCfg)
60-
err := i.Configure(tlsServerConfig)
77+
err := i.Configure(serverConfig)
6178
require.NoError(t, err)
6279
})
6380

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

8297
t.Run("error - TLS required in strict mode", func(t *testing.T) {
8398
authCfg := TestConfig()
8499
i := testInstance(t, authCfg)
85-
serverConfig := core.NewServerConfig()
86-
serverConfig.Strictmode = true
87-
serverConfig.URL = "https://nuts.nl"
88-
err := i.Configure(*serverConfig)
100+
err := i.Configure(core.TestServerConfig())
89101
assert.EqualError(t, err, "in strictmode TLS must be enabled")
90102
})
91103

auth/cmd/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func FlagSet() *pflag.FlagSet {
5757
flags.StringSlice(ConfContractValidators, defs.ContractValidators, "sets the different contract validators to use")
5858
flags.Bool(ConfV2APIEnabled, defs.V2APIEnabled, "enables experimental v2 API endpoints")
5959
_ = flags.MarkHidden(ConfV2APIEnabled)
60+
_ = flags.MarkDeprecated("auth.http.timeout", "use httpclient.timeout instead")
6061

6162
return flags
6263
}

auth/cmd/cmd_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ func TestFlagSet(t *testing.T) {
5555
func TestIrmaConfigInjection(t *testing.T) {
5656
serverCfg := core.NewServerConfig()
5757
serverCfg.Verbosity = "debug"
58-
serverCfg.LoggerFormat = "text"
5958
t.Setenv("NUTS_AUTH_IRMA_SCHEMEMANAGER", "irma-demo")
6059
t.Setenv("NUTS_AUTH_IRMA_AUTOUPDATESCHEMES", "true")
6160
err := serverCfg.Load(FlagSet())

auth/config.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ func DefaultConfig() Config {
4747
SchemeManager: "pbdf",
4848
AutoUpdateSchemas: true,
4949
},
50-
HTTPTimeout: 30,
51-
ClockSkew: 5000,
50+
ClockSkew: 5000,
5251
ContractValidators: []string{
5352
string(services.IrmaFormat),
5453
uzi.ContractFormat,

core/server_config.go

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"net/url"
3434
"reflect"
3535
"strings"
36+
"time"
3637
)
3738

3839
const defaultConfigFile = "nuts.yaml"
@@ -58,13 +59,20 @@ type ServerConfig struct {
5859
Strictmode bool `koanf:"strictmode"`
5960
InternalRateLimiter bool `koanf:"internalratelimiter"`
6061
Datadir string `koanf:"datadir"`
62+
HTTPClient HTTPClientConfig `koanf:"httpclient"`
6163
TLS TLSConfig `koanf:"tls"`
6264
LegacyTLS *NetworkTLSConfig `koanf:"network"`
6365
// URL contains the base URL for public-facing HTTP services.
6466
URL string `koanf:"url"`
6567
configMap *koanf.Koanf
6668
}
6769

70+
// HTTPClientConfig contains settings for HTTP clients.
71+
type HTTPClientConfig struct {
72+
// Timeout specifies the timeout for HTTP requests.
73+
Timeout time.Duration `koanf:"timeout"`
74+
}
75+
6876
// TLSConfig specifies how TLS should be configured for connections.
6977
// For v5, network.enabletls, network.truststorefile, network.certfile and network.certkeyfile must be moved to this struct.
7078
type TLSConfig struct {
@@ -177,10 +185,20 @@ const (
177185
func NewServerConfig() *ServerConfig {
178186
legacyTLS := &NetworkTLSConfig{}
179187
return &ServerConfig{
180-
configMap: koanf.New(defaultDelimiter),
181-
LegacyTLS: legacyTLS,
188+
configMap: koanf.New(defaultDelimiter),
189+
LegacyTLS: legacyTLS,
190+
LoggerFormat: "text",
191+
Verbosity: "info",
192+
Strictmode: true,
193+
InternalRateLimiter: true,
194+
Datadir: "./data",
182195
TLS: TLSConfig{
183-
legacyTLS: legacyTLS,
196+
legacyTLS: legacyTLS,
197+
TrustStoreFile: "truststore.pem",
198+
Offload: NoOffloading,
199+
},
200+
HTTPClient: HTTPClientConfig{
201+
Timeout: 30 * time.Second,
184202
},
185203
}
186204
}
@@ -258,20 +276,23 @@ func resolveConfigFilePath(flags *pflag.FlagSet) string {
258276
// FlagSet returns the default server flags
259277
func FlagSet() *pflag.FlagSet {
260278
flagSet := pflag.NewFlagSet("server", pflag.ContinueOnError)
279+
defaultCfg := NewServerConfig()
280+
261281
flagSet.String(configFileFlag, defaultConfigFile, "Nuts config file")
262282
flagSet.String("cpuprofile", "", "When set, a CPU profile is written to the given path. Ignored when strictmode is set.")
263-
flagSet.String("verbosity", "info", "Log level (trace, debug, info, warn, error)")
264-
flagSet.String("loggerformat", "text", "Log format (text, json)")
265-
flagSet.Bool("strictmode", true, "When set, insecure settings are forbidden.")
266-
flagSet.Bool("internalratelimiter", true, "When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode.")
267-
flagSet.String("datadir", "./data", "Directory where the node stores its files.")
268-
flagSet.String("url", "", "Public facing URL of the server (required). Must be HTTPS when strictmode is set.")
269-
flagSet.String("tls.certfile", "", "PEM file containing the certificate for the server (also used as client certificate).")
270-
flagSet.String("tls.certkeyfile", "", "PEM file containing the private key of the server certificate.")
271-
flagSet.String("tls.truststorefile", "truststore.pem", "PEM file containing the trusted CA certificates for authenticating remote servers.")
272-
flagSet.String("tls.offload", string(NoOffloading), fmt.Sprintf("Whether to enable TLS offloading for incoming connections. "+
283+
flagSet.String("verbosity", defaultCfg.Verbosity, "Log level (trace, debug, info, warn, error)")
284+
flagSet.String("loggerformat", defaultCfg.LoggerFormat, "Log format (text, json)")
285+
flagSet.Bool("strictmode", defaultCfg.Strictmode, "When set, insecure settings are forbidden.")
286+
flagSet.Bool("internalratelimiter", defaultCfg.InternalRateLimiter, "When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode.")
287+
flagSet.String("datadir", defaultCfg.Datadir, "Directory where the node stores its files.")
288+
flagSet.String("url", defaultCfg.URL, "Public facing URL of the server (required). Must be HTTPS when strictmode is set.")
289+
flagSet.Duration("httpclient.timeout", defaultCfg.HTTPClient.Timeout, "Request time-out for HTTP clients, such as '10s'. Refer to Golang's 'time.Duration' syntax for a more elaborate description of the syntax.")
290+
flagSet.String("tls.certfile", defaultCfg.TLS.CertFile, "PEM file containing the certificate for the server (also used as client certificate).")
291+
flagSet.String("tls.certkeyfile", defaultCfg.TLS.CertKeyFile, "PEM file containing the private key of the server certificate.")
292+
flagSet.String("tls.truststorefile", defaultCfg.TLS.TrustStoreFile, "PEM file containing the trusted CA certificates for authenticating remote servers.")
293+
flagSet.String("tls.offload", string(defaultCfg.TLS.Offload), fmt.Sprintf("Whether to enable TLS offloading for incoming connections. "+
273294
"Enable by setting it to '%s'. If enabled 'tls.certheader' must be configured as well.", OffloadIncomingTLS))
274-
flagSet.String("tls.certheader", "", "Name of the HTTP header that will contain the client certificate when TLS is offloaded.")
295+
flagSet.String("tls.certheader", defaultCfg.TLS.ClientCertHeaderName, "Name of the HTTP header that will contain the client certificate when TLS is offloaded.")
275296

276297
// Maxvaliditydays has been deprecated in v5.x
277298
flagSet.Int("tls.crl.maxvaliditydays", 0, "The number of days a CRL can be outdated, after that it will hard-fail.")

core/test.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ type TestEngineConfig struct {
3434
}
3535

3636
// TestServerConfig returns a new ServerConfig with the given template applied.
37-
func TestServerConfig(template ServerConfig) ServerConfig {
37+
func TestServerConfig(visitors ...func(*ServerConfig)) ServerConfig {
3838
config := NewServerConfig()
39-
// Most commonly used properties
40-
config.Datadir = template.Datadir
41-
config.Strictmode = template.Strictmode
42-
config.InternalRateLimiter = template.InternalRateLimiter
43-
config.URL = template.URL
39+
config.URL = "https://nuts.nl"
40+
for _, visitor := range visitors {
41+
visitor(config)
42+
}
4443
return *config
4544
}
4645

crypto/crypto_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,18 @@ func TestCrypto_setupBackend(t *testing.T) {
180180

181181
func TestCrypto_Configure(t *testing.T) {
182182
directory := io.TestDirectory(t)
183-
cfg := *core.NewServerConfig()
184-
cfg.Datadir = directory
185-
t.Run("ok", func(t *testing.T) {
183+
cfg := core.TestServerConfig(func(config *core.ServerConfig) {
184+
config.Datadir = directory
185+
})
186+
t.Run("default backend (fs) can be used in non-strictmode", func(t *testing.T) {
186187
e := createCrypto(t)
188+
cfg := cfg
189+
cfg.Strictmode = false
187190
err := e.Configure(cfg)
188191
assert.NoError(t, err)
189192
})
190193
t.Run("error - no backend in strict mode is now allowed", func(t *testing.T) {
191194
client := createCrypto(t)
192-
cfg := cfg
193-
cfg.Strictmode = true
194195
err := client.Configure(cfg)
195196
assert.EqualError(t, err, "backend must be explicitly set in strict mode", "expected error")
196197
})

docs/pages/deployment/cli-reference.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ The following options apply to the server commands below:
4444
--http.default.cors.origin strings When set, enables CORS from the specified origins on the default HTTP interface.
4545
--http.default.log string What to log about HTTP requests. Options are 'nothing', 'metadata' (log request method, URI, IP and response code), and 'metadata-and-body' (log the request and response body, in addition to the metadata). (default "metadata")
4646
--http.default.tls string Whether to enable TLS for the default interface, options are 'disabled', 'server', 'server-client'. Leaving it empty is synonymous to 'disabled',
47+
--httpclient.timeout duration Request time-out for HTTP clients, such as '10s'. Refer to Golang's 'time.Duration' syntax for a more elaborate description of the syntax. (default 30s)
4748
--internalratelimiter When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode. (default true)
48-
--jsonld.contexts.localmapping stringToString This setting allows mapping external URLs to local files for e.g. preventing external dependencies. These mappings have precedence over those in remoteallowlist. (default [https://schema.org=assets/contexts/schema-org-v13.ldjson,https://nuts.nl/credentials/v1=assets/contexts/nuts.ldjson,https://www.w3.org/2018/credentials/v1=assets/contexts/w3c-credentials-v1.ldjson,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json=assets/contexts/lds-jws2020-v1.ldjson,https://w3id.org/vc/status-list/2021/v1=assets/contexts/w3c-statuslist2021.ldjson])
49+
--jsonld.contexts.localmapping stringToString This setting allows mapping external URLs to local files for e.g. preventing external dependencies. These mappings have precedence over those in remoteallowlist. (default [https://nuts.nl/credentials/v1=assets/contexts/nuts.ldjson,https://www.w3.org/2018/credentials/v1=assets/contexts/w3c-credentials-v1.ldjson,https://w3id.org/vc/status-list/2021/v1=assets/contexts/w3c-statuslist2021.ldjson,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json=assets/contexts/lds-jws2020-v1.ldjson,https://schema.org=assets/contexts/schema-org-v13.ldjson])
4950
--jsonld.contexts.remoteallowlist strings In strict mode, fetching external JSON-LD contexts is not allowed except for context-URLs listed here. (default [https://schema.org,https://www.w3.org/2018/credentials/v1,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json,https://w3id.org/vc/status-list/2021/v1])
5051
--loggerformat string Log format (text, json) (default "text")
5152
--network.bootstrapnodes strings List of bootstrap nodes ('<host>:<port>') which the node initially connect to.

0 commit comments

Comments
 (0)