Skip to content

Commit

Permalink
WFE/nonce: Add NonceHMACKey field
Browse files Browse the repository at this point in the history
  • Loading branch information
jprenken committed Nov 8, 2024
1 parent 2058d98 commit 6c67032
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 31 deletions.
22 changes: 19 additions & 3 deletions cmd/boulder-wfe2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}
Expand Down
36 changes: 22 additions & 14 deletions cmd/nonce-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,25 @@ 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
// 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.
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
Expand Down Expand Up @@ -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")

Expand Down
4 changes: 2 additions & 2 deletions test/config-next/nonce-a.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"NonceService": {
"maxUsed": 131072,
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
"nonceHMACKey": {
"keyFile": "test/secrets/nonce_prefix_key"
},
"syslog": {
"stdoutLevel": 6,
Expand Down
4 changes: 2 additions & 2 deletions test/config-next/nonce-b.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"NonceService": {
"maxUsed": 131072,
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
"nonceHMACKey": {
"keyFile": "test/secrets/nonce_prefix_key"
},
"syslog": {
"stdoutLevel": 6,
Expand Down
4 changes: 2 additions & 2 deletions test/config-next/wfe2.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
"noWaitForReady": true,
"hostOverride": "nonce.boulder"
},
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
"nonceHMACKey": {
"keyFile": "test/secrets/nonce_prefix_key"
},
"chains": [
[
Expand Down
1 change: 0 additions & 1 deletion test/config/nonce-a.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"NonceService": {
"maxUsed": 131072,
"useDerivablePrefix": true,
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
},
Expand Down
1 change: 0 additions & 1 deletion test/config/nonce-b.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"NonceService": {
"maxUsed": 131072,
"useDerivablePrefix": true,
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
},
Expand Down
11 changes: 9 additions & 2 deletions test/integration/nonce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type nonceBalancerTestConfig struct {
GetNonceService *cmd.GRPCClientConfig
RedeemNonceService *cmd.GRPCClientConfig
NoncePrefixKey cmd.PasswordConfig
NonceHMACKey cmd.HMACKeyConfig
}
}

Expand All @@ -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()

Expand Down
4 changes: 2 additions & 2 deletions test/integration/testdata/nonce-client.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"noWaitForReady": true,
"hostOverride": "nonce.boulder"
},
"noncePrefixKey": {
"passwordFile": "test/secrets/nonce_prefix_key"
"nonceHMACKey": {
"keyFile": "test/secrets/nonce_prefix_key"
}
}
}
2 changes: 1 addition & 1 deletion test/secrets/nonce_prefix_key
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3b8c758dd85e113ea340ce0b3a99f389d40a308548af94d1730a7692c1874f1f
3b8c758dd85e113ea340ce0b3a99f389

0 comments on commit 6c67032

Please sign in to comment.