diff --git a/command/agent/agent.go b/command/agent/agent.go index 2d4a6879a..2d45ef5ee 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -811,7 +811,7 @@ func (a *Agent) setupKeyrings(config *nomad.Config) error { goto LOAD } if _, err := os.Stat(file); err != nil { - if err := initKeyring(file, a.config.Server.EncryptKey); err != nil { + if err := initKeyring(file, a.config.Server.EncryptKey, a.logger); err != nil { return err } } diff --git a/command/agent/keyring.go b/command/agent/keyring.go index ca509506b..a8537b9ca 100644 --- a/command/agent/keyring.go +++ b/command/agent/keyring.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" + log "github.com/hashicorp/go-hclog" "github.com/hashicorp/memberlist" "github.com/hashicorp/serf/serf" ) @@ -17,7 +18,7 @@ const ( ) // initKeyring will create a keyring file at a given path. -func initKeyring(path, key string) error { +func initKeyring(path, key string, l log.Logger) error { var keys []string if keyBytes, err := base64.StdEncoding.DecodeString(key); err != nil { @@ -26,6 +27,19 @@ func initKeyring(path, key string) error { return fmt.Errorf("Invalid key: %s", err) } + // Check for AES-256 key size (32-bytes) + if len(key) < 32 { + var encMethod string + switch len(key) { + case 16: + encMethod = "AES-128" + case 24: + encMethod = "AES-192" + } + msg := fmt.Sprintf("given %d-byte gossip key enables %s encryption, generate a 32-byte key to enable AES-256", len(key), encMethod) + l.Info(msg) + } + // Just exit if the file already exists. if _, err := os.Stat(path); err == nil { return nil diff --git a/command/agent/keyring_test.go b/command/agent/keyring_test.go index fc22bc8a0..3408d8df0 100644 --- a/command/agent/keyring_test.go +++ b/command/agent/keyring_test.go @@ -6,6 +6,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/hashicorp/go-hclog" ) func TestAgent_LoadKeyrings(t *testing.T) { @@ -56,8 +58,10 @@ func TestAgent_InitKeyring(t *testing.T) { file := filepath.Join(dir, "keyring") + logger := hclog.NewNullLogger() + // First initialize the keyring - if err := initKeyring(file, key1); err != nil { + if err := initKeyring(file, key1, logger); err != nil { t.Fatalf("err: %s", err) } @@ -70,7 +74,7 @@ func TestAgent_InitKeyring(t *testing.T) { } // Try initializing again with a different key - if err := initKeyring(file, key2); err != nil { + if err := initKeyring(file, key2, logger); err != nil { t.Fatalf("err: %s", err) } diff --git a/command/agent/testagent.go b/command/agent/testagent.go index 1fa14879a..507c76f1c 100644 --- a/command/agent/testagent.go +++ b/command/agent/testagent.go @@ -143,11 +143,15 @@ RETRY: a.Config.NodeName = fmt.Sprintf("Node %d", a.Config.Ports.RPC) } + // Create a null logger before initializing the keyring. This is typically + // done using the agent's logger. However, it hasn't been created yet. + logger := hclog.NewNullLogger() + // write the keyring if a.Key != "" { writeKey := func(key, filename string) { path := filepath.Join(a.Config.DataDir, filename) - if err := initKeyring(path, key); err != nil { + if err := initKeyring(path, key, logger); err != nil { a.T.Fatalf("Error creating keyring %s: %s", path, err) } } diff --git a/command/operator_keygen.go b/command/operator_keygen.go index 62dab3bae..f08a60a06 100644 --- a/command/operator_keygen.go +++ b/command/operator_keygen.go @@ -21,7 +21,7 @@ func (c *OperatorKeygenCommand) Help() string { helpText := ` Usage: nomad operator keygen - Generates a new encryption key that can be used to configure the + Generates a new 32-byte encryption key that can be used to configure the agent to encrypt traffic. The output of this command is already in the proper format that the agent expects. ` @@ -31,13 +31,13 @@ Usage: nomad operator keygen func (c *OperatorKeygenCommand) Name() string { return "operator keygen" } func (c *OperatorKeygenCommand) Run(_ []string) int { - key := make([]byte, 16) + key := make([]byte, 32) n, err := rand.Reader.Read(key) if err != nil { c.Ui.Error(fmt.Sprintf("Error reading random data: %s", err)) return 1 } - if n != 16 { + if n != 32 { c.Ui.Error(fmt.Sprintf("Couldn't read enough entropy. Generate more entropy!")) return 1 } diff --git a/command/operator_keygen_test.go b/command/operator_keygen_test.go index aef615692..22c57bff6 100644 --- a/command/operator_keygen_test.go +++ b/command/operator_keygen_test.go @@ -22,7 +22,7 @@ func TestKeygenCommand(t *testing.T) { t.Fatalf("err: %s", err) } - if len(result) != 16 { + if len(result) != 32 { t.Fatalf("bad: %#v", result) } } diff --git a/website/pages/docs/commands/operator/keygen.mdx b/website/pages/docs/commands/operator/keygen.mdx index 3baf7bfd6..da8e9b649 100644 --- a/website/pages/docs/commands/operator/keygen.mdx +++ b/website/pages/docs/commands/operator/keygen.mdx @@ -24,5 +24,5 @@ nomad operator keygen ```shell-session $ nomad operator keygen -YgZOXLMhC7TtZqeghMT8+w== +6RhfKFZ5uYEaU6RgWzx69ssLcpiIkvnEZs5KBOQxvxA= ``` diff --git a/website/pages/docs/configuration/server.mdx b/website/pages/docs/configuration/server.mdx index 77b2d3aba..5c7cbd05b 100644 --- a/website/pages/docs/configuration/server.mdx +++ b/website/pages/docs/configuration/server.mdx @@ -55,7 +55,7 @@ server { worker threads will dequeue for processing. - `encrypt` `(string: "")` - Specifies the secret key to use for encryption of - Nomad server's gossip network traffic. This key must be 16 bytes that are + Nomad server's gossip network traffic. This key must be 32 bytes that are base64-encoded. The provided key is automatically persisted to the data directory and loaded automatically whenever the agent is restarted. This means that to encrypt Nomad server's gossip protocol, this option only needs to be