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:
parent
a01936442c
commit
6b1ec05470
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
agent: Give better error when client specifies wrong datacenter when auto-encrypt is enabled.
|
||||||
|
```
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue