diff --git a/cmd/boulder-wfe2/main.go b/cmd/boulder-wfe2/main.go index 61698d16cfe..d395e67c8ac 100644 --- a/cmd/boulder-wfe2/main.go +++ b/cmd/boulder-wfe2/main.go @@ -71,13 +71,23 @@ type Config struct { // local and remote nonce-service instances. RedeemNonceService *cmd.GRPCClientConfig `validate:"required"` + // NonceHMACKey is a path to a file containing an HMAC key which is a + // secret used for deriving the prefix of each nonce instance. It should + // contain 256 bits (32 bytes) of random data to be suitable as an + // HMAC-SHA256 key (e.g. the output of `openssl rand -hex 32`). In a + // multi-DC deployment this value should be the same across all + // boulder-wfe and nonce-service instances. + NonceHMACKey cmd.HMACKeyConfig `validate:"-"` + // NoncePrefixKey is a secret used for deriving the prefix of each nonce // instance. It should contain 256 bits of random data to be suitable as // an HMAC-SHA256 key (e.g. the output of `openssl rand -hex 32`). In a // multi-DC deployment this value should be the same across all // boulder-wfe and nonce-service instances. // - // TODO(#7632) Update this to use the new HMACKeyConfig. + // TODO(#7632): Remove this. + // + // Deprecated: Use NonceHMACKey instead. NoncePrefixKey cmd.PasswordConfig `validate:"-"` // Chains is a list of lists of certificate filenames. Each inner list is @@ -295,9 +305,15 @@ func main() { } var noncePrefixKey string - if c.WFE.NoncePrefixKey.PasswordFile != "" { + if c.WFE.NonceHMACKey.KeyFile != "" { + keyByte, err := c.WFE.NonceHMACKey.Load() + cmd.FailOnError(err, "Failed to load nonceHMACKey file") + noncePrefixKey = string(keyByte) + } else if c.WFE.NoncePrefixKey.PasswordFile != "" { noncePrefixKey, err = c.WFE.NoncePrefixKey.Pass() - cmd.FailOnError(err, "Failed to load noncePrefixKey") + cmd.FailOnError(err, "Failed to load noncePrefixKey file") + } else { + cmd.Fail("NonceHMACKey KeyFile or NoncePrefixKey PasswordFile must be set") } getNonceConn, err := bgrpc.ClientSetup(c.WFE.GetNonceService, tlsConfig, stats, clk) diff --git a/cmd/config.go b/cmd/config.go index 3264ea1cce2..9aaa6836f52 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -572,7 +572,7 @@ func (hc *HMACKeyConfig) Load() ([]byte, error) { if len(trimmed) != 32 { return nil, fmt.Errorf( - "validating unpauseHMACKey, length must be 32 alphanumeric characters, got %d", + "validating HMAC key, length must be 32 alphanumeric characters, got %d", len(trimmed), ) } diff --git a/cmd/nonce-service/main.go b/cmd/nonce-service/main.go index af90de5ac33..75c9cb94b06 100644 --- a/cmd/nonce-service/main.go +++ b/cmd/nonce-service/main.go @@ -19,14 +19,13 @@ type Config struct { MaxUsed int - // UseDerivablePrefix indicates whether to use a nonce prefix derived - // from the gRPC listening address. If this is false, the nonce prefix - // will be the value of the NoncePrefix field. If this is true, the - // NoncePrefixKey field is required. - // TODO(#6610): Remove this. - // - // Deprecated: this value is ignored, and treated as though it is always true. - UseDerivablePrefix bool `validate:"-"` + // NonceHMACKey is a path to a file containing an HMAC key which is a + // secret used for deriving the prefix of each nonce instance. It should + // contain 256 bits (32 bytes) of random data to be suitable as an + // HMAC-SHA256 key (e.g. the output of `openssl rand -hex 32`). In a + // multi-DC deployment this value should be the same across all + // boulder-wfe and nonce-service instances. + NonceHMACKey cmd.HMACKeyConfig `validate:"required_without_all=NoncePrefixKey,structonly"` // NoncePrefixKey is a secret used for deriving the prefix of each nonce // instance. It should contain 256 bits (32 bytes) of random data to be @@ -34,8 +33,11 @@ type Config struct { // 32`). In a multi-DC deployment this value should be the same across // all boulder-wfe and nonce-service instances. // - // TODO(#7632) Update this to use the new HMACKeyConfig. - NoncePrefixKey cmd.PasswordConfig `validate:"required"` + // TODO(#7632): Remove this and change `NonceHMACKey`'s validation to + // just `required.` + // + // Deprecated: Use NonceHMACKey instead. + NoncePrefixKey cmd.PasswordConfig `validate:"required_without_all=NonceHMACKey,structonly"` Syslog cmd.SyslogConfig OpenTelemetry cmd.OpenTelemetryConfig @@ -84,12 +86,18 @@ func main() { c.NonceService.DebugAddr = *debugAddr } - if c.NonceService.NoncePrefixKey.PasswordFile == "" { - cmd.Fail("NoncePrefixKey PasswordFile must be set") + var key string + if c.NonceService.NonceHMACKey.KeyFile != "" { + keyByte, err := c.NonceService.NonceHMACKey.Load() + cmd.FailOnError(err, "Failed to load 'nonceHMACKey' file.") + key = string(keyByte) + } else if c.NonceService.NoncePrefixKey.PasswordFile != "" { + key, err = c.NonceService.NoncePrefixKey.Pass() + cmd.FailOnError(err, "Failed to load 'noncePrefixKey' file.") + } else { + cmd.Fail("NonceHMACKey KeyFile or NoncePrefixKey PasswordFile must be set") } - key, err := c.NonceService.NoncePrefixKey.Pass() - cmd.FailOnError(err, "Failed to load 'noncePrefixKey' file.") noncePrefix, err := derivePrefix(key, c.NonceService.GRPC.Address) cmd.FailOnError(err, "Failed to derive nonce prefix") diff --git a/test/config-next/nonce-a.json b/test/config-next/nonce-a.json index 75df81b6ed9..d14b44063f2 100644 --- a/test/config-next/nonce-a.json +++ b/test/config-next/nonce-a.json @@ -1,8 +1,8 @@ { "NonceService": { "maxUsed": 131072, - "noncePrefixKey": { - "passwordFile": "test/secrets/nonce_prefix_key" + "nonceHMACKey": { + "keyFile": "test/secrets/nonce_prefix_key" }, "syslog": { "stdoutLevel": 6, diff --git a/test/config-next/nonce-b.json b/test/config-next/nonce-b.json index 75df81b6ed9..d14b44063f2 100644 --- a/test/config-next/nonce-b.json +++ b/test/config-next/nonce-b.json @@ -1,8 +1,8 @@ { "NonceService": { "maxUsed": 131072, - "noncePrefixKey": { - "passwordFile": "test/secrets/nonce_prefix_key" + "nonceHMACKey": { + "keyFile": "test/secrets/nonce_prefix_key" }, "syslog": { "stdoutLevel": 6, diff --git a/test/config-next/wfe2.json b/test/config-next/wfe2.json index 1b697d99376..27ba88ac57b 100644 --- a/test/config-next/wfe2.json +++ b/test/config-next/wfe2.json @@ -68,8 +68,8 @@ "noWaitForReady": true, "hostOverride": "nonce.boulder" }, - "noncePrefixKey": { - "passwordFile": "test/secrets/nonce_prefix_key" + "nonceHMACKey": { + "keyFile": "test/secrets/nonce_prefix_key" }, "chains": [ [ diff --git a/test/config/nonce-a.json b/test/config/nonce-a.json index c2dd9765c85..6bbe2a0c53c 100644 --- a/test/config/nonce-a.json +++ b/test/config/nonce-a.json @@ -1,7 +1,6 @@ { "NonceService": { "maxUsed": 131072, - "useDerivablePrefix": true, "noncePrefixKey": { "passwordFile": "test/secrets/nonce_prefix_key" }, diff --git a/test/config/nonce-b.json b/test/config/nonce-b.json index c2dd9765c85..6bbe2a0c53c 100644 --- a/test/config/nonce-b.json +++ b/test/config/nonce-b.json @@ -1,7 +1,6 @@ { "NonceService": { "maxUsed": 131072, - "useDerivablePrefix": true, "noncePrefixKey": { "passwordFile": "test/secrets/nonce_prefix_key" }, diff --git a/test/integration/nonce_test.go b/test/integration/nonce_test.go index 5df9cb986a6..2aa49ae1438 100644 --- a/test/integration/nonce_test.go +++ b/test/integration/nonce_test.go @@ -24,6 +24,7 @@ type nonceBalancerTestConfig struct { GetNonceService *cmd.GRPCClientConfig RedeemNonceService *cmd.GRPCClientConfig NoncePrefixKey cmd.PasswordConfig + NonceHMACKey cmd.HMACKeyConfig } } @@ -41,8 +42,14 @@ func TestNonceBalancer_NoBackendMatchingPrefix(t *testing.T) { tlsConfig, err := c.NotWFE.TLS.Load(metrics.NoopRegisterer) test.AssertNotError(t, err, "Could not load TLS config") - rncKey, err := c.NotWFE.NoncePrefixKey.Pass() - test.AssertNotError(t, err, "Failed to load noncePrefixKey") + var rncKey string + rncKeyByte, err := c.NotWFE.NonceHMACKey.Load() + if err != nil { + rncKey, err = c.NotWFE.NoncePrefixKey.Pass() + test.AssertNotError(t, err, "Failed to load nonceHMACKey or noncePrefixKey") + } else { + rncKey = string(rncKeyByte) + } clk := clock.New() diff --git a/test/integration/testdata/nonce-client.json b/test/integration/testdata/nonce-client.json index 90e84706b02..a66077e2690 100644 --- a/test/integration/testdata/nonce-client.json +++ b/test/integration/testdata/nonce-client.json @@ -32,8 +32,8 @@ "noWaitForReady": true, "hostOverride": "nonce.boulder" }, - "noncePrefixKey": { - "passwordFile": "test/secrets/nonce_prefix_key" + "nonceHMACKey": { + "keyFile": "test/secrets/nonce_prefix_key" } } } diff --git a/test/secrets/nonce_prefix_key b/test/secrets/nonce_prefix_key index d65802423de..96bb4c2ed30 100644 --- a/test/secrets/nonce_prefix_key +++ b/test/secrets/nonce_prefix_key @@ -1 +1 @@ -3b8c758dd85e113ea340ce0b3a99f389d40a308548af94d1730a7692c1874f1f +3b8c758dd85e113ea340ce0b3a99f389