autoencrypt: helpful error for clients with wrong dc (#14832)

* autoencrypt: helpful error for clients with wrong dc

If clients have set a different datacenter than the servers they're
connecting with for autoencrypt, give a helpful error message.
This commit is contained in:
Luke Kysow 2022-10-25 10:13:41 -07:00 committed by GitHub
parent a01936442c
commit 6b1ec05470
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 2 deletions

3
.changelog/14832.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
agent: Give better error when client specifies wrong datacenter when auto-encrypt is enabled.
```

View File

@ -2,6 +2,7 @@ package consul
import ( import (
"errors" "errors"
"fmt"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
) )
@ -24,6 +25,13 @@ func (a *AutoEncrypt) Sign(
if !a.srv.config.AutoEncryptAllowTLS { if !a.srv.config.AutoEncryptAllowTLS {
return ErrAutoEncryptAllowTLSNotEnabled return ErrAutoEncryptAllowTLSNotEnabled
} }
// There's no reason to forward the AutoEncrypt.Sign RPC to a remote datacenter because its certificates
// won't be valid in this datacenter. If the client is requesting a different datacenter, then this is a
// misconfiguration, and we can give them a useful error.
if args.Datacenter != a.srv.config.Datacenter {
return fmt.Errorf("mismatched datacenter (client_dc='%s' server_dc='%s');"+
" check client has same datacenter set as servers", args.Datacenter, a.srv.config.Datacenter)
}
if done, err := a.srv.ForwardRPC("AutoEncrypt.Sign", args, reply); done { if done, err := a.srv.ForwardRPC("AutoEncrypt.Sign", args, reply); done {
return err return err
} }

View File

@ -139,3 +139,58 @@ func TestAutoEncryptSign(t *testing.T) {
}) })
} }
} }
func TestAutoEncryptSign_MismatchedDC(t *testing.T) {
t.Parallel()
cert := "../../test/key/ourdomain.cer"
key := "../../test/key/ourdomain.key"
root := "../../test/ca/root.cer"
dir, s := testServerWithConfig(t, func(c *Config) {
c.AutoEncryptAllowTLS = true
c.PrimaryDatacenter = "dc1"
c.Bootstrap = true
c.TLSConfig.InternalRPC.CAFile = root
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.CertFile = cert
c.TLSConfig.InternalRPC.KeyFile = key
})
defer os.RemoveAll(dir)
defer s.Shutdown()
testrpc.WaitForLeader(t, s.RPC, "dc1")
// Generate a CSR and request signing
id := &connect.SpiffeIDAgent{
Host: strings.TrimSuffix("domain", "."),
Datacenter: "different",
Agent: "uuid",
}
// Create a new private key
pk, _, err := connect.GeneratePrivateKey()
require.NoError(t, err)
// Create a CSR.
dnsNames := []string{"localhost"}
ipAddresses := []net.IP{net.ParseIP("127.0.0.1")}
csr, err := connect.CreateCSR(id, pk, dnsNames, ipAddresses)
require.NoError(t, err)
require.NotEmpty(t, csr)
args := &structs.CASignRequest{
Datacenter: "different",
CSR: csr,
}
cfg := tlsutil.Config{
AutoTLS: true,
Domain: "consul",
}
codec, err := insecureRPCClient(s, cfg)
require.NoError(t, err)
var reply structs.SignedResponse
err = msgpackrpc.CallWithCodec(codec, "AutoEncrypt.Sign", args, &reply)
codec.Close()
require.EqualError(t, err, "mismatched datacenter (client_dc='different' server_dc='dc1'); check client has same datacenter set as servers")
return
}

View File

@ -592,14 +592,14 @@ func (p *ConnPool) rpcInsecure(dc string, addr net.Addr, method string, args int
var codec rpc.ClientCodec var codec rpc.ClientCodec
conn, _, err := p.dial(dc, addr, 0, RPCTLSInsecure) conn, _, err := p.dial(dc, addr, 0, RPCTLSInsecure)
if err != nil { if err != nil {
return fmt.Errorf("rpcinsecure error establishing connection: %w", err) return fmt.Errorf("rpcinsecure: error establishing connection: %w", err)
} }
codec = msgpackrpc.NewCodecFromHandle(true, true, conn, structs.MsgpackHandle) codec = msgpackrpc.NewCodecFromHandle(true, true, conn, structs.MsgpackHandle)
// Make the RPC call // Make the RPC call
err = msgpackrpc.CallWithCodec(codec, method, args, reply) err = msgpackrpc.CallWithCodec(codec, method, args, reply)
if err != nil { if err != nil {
return fmt.Errorf("rpcinsecure error making call: %w", err) return fmt.Errorf("rpcinsecure: error making call: %w", err)
} }
return nil return nil