peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
package peering_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"path"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-10-10 19:45:30 +00:00
|
|
|
"github.com/google/tcpproxy"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
"github.com/hashicorp/go-hclog"
|
|
|
|
"github.com/hashicorp/go-uuid"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
gogrpc "google.golang.org/grpc"
|
2022-07-22 22:20:21 +00:00
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
grpcstatus "google.golang.org/grpc/status"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-06-10 16:10:46 +00:00
|
|
|
"github.com/hashicorp/consul/acl"
|
2022-09-29 03:27:11 +00:00
|
|
|
"github.com/hashicorp/consul/agent/connect"
|
2022-06-10 16:10:46 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul"
|
2022-05-26 19:24:09 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/state"
|
proxycfg: server-local config entry data sources
This is the OSS portion of enterprise PR 2056.
This commit provides server-local implementations of the proxycfg.ConfigEntry
and proxycfg.ConfigEntryList interfaces, that source data from streaming events.
It makes use of the LocalMaterializer type introduced for peering replication,
adding the necessary support for authorization.
It also adds support for "wildcard" subscriptions (within a topic) to the event
publisher, as this is needed to fetch service-resolvers for all services when
configuring mesh gateways.
Currently, events will be emitted for just the ingress-gateway, service-resolver,
and mesh config entry types, as these are the only entries required by proxycfg
— the events will be emitted on topics named IngressGateway, ServiceResolver,
and MeshConfig topics respectively.
Though these events will only be consumed "locally" for now, they can also be
consumed via the gRPC endpoint (confirmed using grpcurl) so using them from
client agents should be a case of swapping the LocalMaterializer for an
RPCMaterializer.
2022-07-01 15:09:47 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/stream"
|
2022-07-12 23:18:05 +00:00
|
|
|
external "github.com/hashicorp/consul/agent/grpc-external"
|
2022-09-09 14:02:01 +00:00
|
|
|
"github.com/hashicorp/consul/agent/grpc-external/limiter"
|
2022-07-13 15:33:48 +00:00
|
|
|
grpc "github.com/hashicorp/consul/agent/grpc-internal"
|
|
|
|
"github.com/hashicorp/consul/agent/grpc-internal/resolver"
|
2022-10-28 20:34:41 +00:00
|
|
|
agentmiddleware "github.com/hashicorp/consul/agent/grpc-middleware"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
"github.com/hashicorp/consul/agent/pool"
|
|
|
|
"github.com/hashicorp/consul/agent/router"
|
|
|
|
"github.com/hashicorp/consul/agent/rpc/middleware"
|
|
|
|
"github.com/hashicorp/consul/agent/rpc/peering"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
|
|
"github.com/hashicorp/consul/agent/token"
|
2022-06-21 18:04:08 +00:00
|
|
|
"github.com/hashicorp/consul/lib"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
"github.com/hashicorp/consul/proto/pbpeering"
|
2022-06-10 16:10:46 +00:00
|
|
|
"github.com/hashicorp/consul/proto/prototest"
|
2022-05-11 19:20:50 +00:00
|
|
|
"github.com/hashicorp/consul/sdk/freeport"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
"github.com/hashicorp/consul/sdk/testutil"
|
2022-06-14 14:39:23 +00:00
|
|
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
"github.com/hashicorp/consul/testrpc"
|
|
|
|
"github.com/hashicorp/consul/tlsutil"
|
|
|
|
"github.com/hashicorp/consul/types"
|
|
|
|
)
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
const (
|
|
|
|
testTokenPeeringReadSecret = "9a83c138-a0c7-40f1-89fa-6acf9acd78f5"
|
|
|
|
testTokenPeeringWriteSecret = "91f90a41-0840-4afe-b615-68745f9e16c1"
|
|
|
|
testTokenServiceReadSecret = "1ef8e3cf-6e95-49aa-9f73-a0d3ad1a77d4"
|
|
|
|
testTokenServiceWriteSecret = "4a3dc05d-d86c-4f20-be43-8f4f8f045fea"
|
|
|
|
)
|
|
|
|
|
2022-05-09 20:47:37 +00:00
|
|
|
func generateTooManyMetaKeys() map[string]string {
|
|
|
|
// todo -- modularize in structs.go or testing.go
|
|
|
|
tooMuchMeta := make(map[string]string)
|
|
|
|
for i := 0; i < 64+1; i++ {
|
|
|
|
tooMuchMeta[fmt.Sprint(i)] = "value"
|
|
|
|
}
|
|
|
|
|
|
|
|
return tooMuchMeta
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func TestPeeringService_GenerateToken(t *testing.T) {
|
|
|
|
dir := testutil.TempDir(t, "consul")
|
2022-09-29 03:27:11 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
signer, _, _ := tlsutil.GeneratePrivateKey()
|
|
|
|
ca, _, _ := tlsutil.GenerateCA(tlsutil.CAOpts{Signer: signer})
|
|
|
|
cafile := path.Join(dir, "cacert.pem")
|
|
|
|
require.NoError(t, ioutil.WriteFile(cafile, []byte(ca), 0600))
|
|
|
|
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(c *consul.Config) {
|
|
|
|
c.SerfLANConfig.MemberlistConfig.AdvertiseAddr = "127.0.0.1"
|
2022-07-15 18:15:50 +00:00
|
|
|
c.TLSConfig.GRPC.CAFile = cafile
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
c.DataDir = dir
|
|
|
|
})
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-05-09 20:47:37 +00:00
|
|
|
// TODO(peering): for more failure cases, consider using a table test
|
|
|
|
// check meta tags
|
2022-07-12 23:18:05 +00:00
|
|
|
reqE := pbpeering.GenerateTokenRequest{PeerName: "peerB", Meta: generateTooManyMetaKeys()}
|
2022-05-09 20:47:37 +00:00
|
|
|
_, errE := client.GenerateToken(ctx, &reqE)
|
|
|
|
require.EqualError(t, errE, "rpc error: code = Unknown desc = meta tags failed validation: Node metadata cannot contain more than 64 key/value pairs")
|
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
var (
|
|
|
|
peerID string
|
|
|
|
secret string
|
|
|
|
)
|
|
|
|
testutil.RunStep(t, "peering token is generated with data", func(t *testing.T) {
|
2022-10-05 13:10:19 +00:00
|
|
|
req := pbpeering.GenerateTokenRequest{
|
|
|
|
PeerName: "peerB",
|
|
|
|
Meta: map[string]string{"foo": "bar"},
|
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
resp, err := client.GenerateToken(ctx, &req)
|
|
|
|
require.NoError(t, err)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
tokenJSON, err := base64.StdEncoding.DecodeString(resp.PeeringToken)
|
|
|
|
require.NoError(t, err)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
token := &structs.PeeringToken{}
|
|
|
|
require.NoError(t, json.Unmarshal(tokenJSON, token))
|
2022-09-29 03:27:11 +00:00
|
|
|
require.Equal(t, "server.dc1.peering.11111111-2222-3333-4444-555555555555.consul", token.ServerName)
|
2022-08-01 14:33:18 +00:00
|
|
|
require.Len(t, token.ServerAddresses, 1)
|
|
|
|
require.Equal(t, s.PublicGRPCAddr, token.ServerAddresses[0])
|
2022-09-29 03:27:11 +00:00
|
|
|
|
|
|
|
// The roots utilized should be the ConnectCA roots and not the ones manually configured.
|
|
|
|
_, roots, err := s.Server.FSM().State().CARoots(nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, []string{roots.Active().RootCert}, token.CA)
|
2022-10-05 13:10:19 +00:00
|
|
|
require.Equal(t, "dc1", token.Remote.Datacenter)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NotEmpty(t, token.EstablishmentSecret)
|
|
|
|
secret = token.EstablishmentSecret
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NotEmpty(t, token.PeerID)
|
|
|
|
peerID = token.PeerID
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
_, err = uuid.ParseUUID(token.PeerID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "peerings is created by generating a token", func(t *testing.T) {
|
|
|
|
_, peers, err := s.Server.FSM().State().PeeringList(nil, *structs.DefaultEnterpriseMetaInDefaultPartition())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peers, 1)
|
|
|
|
|
|
|
|
peers[0].ModifyIndex = 0
|
|
|
|
peers[0].CreateIndex = 0
|
|
|
|
|
|
|
|
expect := &pbpeering.Peering{
|
|
|
|
Name: "peerB",
|
|
|
|
Partition: acl.DefaultPartitionName,
|
|
|
|
ID: peerID,
|
|
|
|
State: pbpeering.PeeringState_PENDING,
|
|
|
|
Meta: map[string]string{"foo": "bar"},
|
|
|
|
}
|
|
|
|
require.Equal(t, expect, peers[0])
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "generating a token persists establishment secret", func(t *testing.T) {
|
|
|
|
s, err := s.Server.FSM().State().PeeringSecretsRead(nil, peerID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, s)
|
|
|
|
|
|
|
|
require.Equal(t, secret, s.GetEstablishment().GetSecretID())
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "re-generating a peering token re-generates the secret", func(t *testing.T) {
|
|
|
|
req := pbpeering.GenerateTokenRequest{PeerName: "peerB", Meta: map[string]string{"foo": "bar"}}
|
|
|
|
resp, err := client.GenerateToken(ctx, &req)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tokenJSON, err := base64.StdEncoding.DecodeString(resp.PeeringToken)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
token := &structs.PeeringToken{}
|
|
|
|
require.NoError(t, json.Unmarshal(tokenJSON, token))
|
|
|
|
|
|
|
|
// There should be a new establishment secret, different from the past one
|
|
|
|
require.NotEmpty(t, token.EstablishmentSecret)
|
|
|
|
require.NotEqual(t, secret, token.EstablishmentSecret)
|
|
|
|
|
|
|
|
s, err := s.Server.FSM().State().PeeringSecretsRead(nil, peerID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, s)
|
|
|
|
|
|
|
|
// The secret must be persisted on the server that generated it.
|
|
|
|
require.Equal(t, token.EstablishmentSecret, s.GetEstablishment().GetSecretID())
|
|
|
|
})
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_GenerateToken_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.GenerateTokenRequest
|
|
|
|
token string
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.GenerateToken(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.GenerateTokenRequest{PeerName: "foo"},
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "read token lacks permissions",
|
|
|
|
req: &pbpeering.GenerateTokenRequest{
|
|
|
|
PeerName: "foo",
|
|
|
|
},
|
|
|
|
token: testTokenPeeringReadSecret,
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "write token grants permission",
|
|
|
|
req: &pbpeering.GenerateTokenRequest{
|
|
|
|
PeerName: "foo",
|
|
|
|
},
|
|
|
|
token: testTokenPeeringWriteSecret,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
func TestPeeringService_Establish_Validation(t *testing.T) {
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
validToken := peering.TestPeeringToken("83474a06-cca4-4ff4-99a4-4152929c8160")
|
|
|
|
validTokenJSON, _ := json.Marshal(&validToken)
|
|
|
|
validTokenB64 := base64.StdEncoding.EncodeToString(validTokenJSON)
|
|
|
|
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, nil)
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
2022-06-10 16:10:46 +00:00
|
|
|
req *pbpeering.EstablishRequest
|
|
|
|
expectResp *pbpeering.EstablishResponse
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
expectPeering *pbpeering.Peering
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-06-10 16:10:46 +00:00
|
|
|
resp, err := client.Establish(ctx, tc.req)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
prototest.AssertDeepEqual(t, tc.expectResp, resp)
|
|
|
|
|
|
|
|
// if a peering was expected to be written, try to read it back
|
|
|
|
if tc.expectPeering != nil {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
resp, err := client.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: tc.expectPeering.Name})
|
|
|
|
require.NoError(t, err)
|
|
|
|
// check individual values we care about since we don't know exactly
|
|
|
|
// what the create/modify indexes will be
|
|
|
|
require.Equal(t, tc.expectPeering.Name, resp.Peering.Name)
|
|
|
|
require.Equal(t, tc.expectPeering.Partition, resp.Peering.Partition)
|
|
|
|
require.Equal(t, tc.expectPeering.State, resp.Peering.State)
|
|
|
|
require.Equal(t, tc.expectPeering.PeerCAPems, resp.Peering.PeerCAPems)
|
|
|
|
require.Equal(t, tc.expectPeering.PeerServerAddresses, resp.Peering.PeerServerAddresses)
|
|
|
|
require.Equal(t, tc.expectPeering.PeerServerName, resp.Peering.PeerServerName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "invalid peer name",
|
2022-06-10 16:10:46 +00:00
|
|
|
req: &pbpeering.EstablishRequest{PeerName: "--AA--"},
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
expectErr: "--AA-- is not a valid peer name",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid token (base64)",
|
2022-06-10 16:10:46 +00:00
|
|
|
req: &pbpeering.EstablishRequest{
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: "peer1-usw1",
|
|
|
|
PeeringToken: "+++/+++",
|
|
|
|
},
|
|
|
|
expectErr: "illegal base64 data",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid token (JSON)",
|
2022-06-10 16:10:46 +00:00
|
|
|
req: &pbpeering.EstablishRequest{
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: "peer1-usw1",
|
|
|
|
PeeringToken: "Cg==", // base64 of "-"
|
|
|
|
},
|
|
|
|
expectErr: "unexpected end of JSON input",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid token (empty)",
|
2022-06-10 16:10:46 +00:00
|
|
|
req: &pbpeering.EstablishRequest{
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
PeerName: "peer1-usw1",
|
|
|
|
PeeringToken: "e30K", // base64 of "{}"
|
|
|
|
},
|
2022-05-13 19:01:00 +00:00
|
|
|
expectErr: "peering token server addresses value is empty",
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
},
|
2022-05-09 20:47:37 +00:00
|
|
|
{
|
|
|
|
name: "too many meta tags",
|
2022-06-10 16:10:46 +00:00
|
|
|
req: &pbpeering.EstablishRequest{
|
2022-05-09 20:47:37 +00:00
|
|
|
PeerName: "peer1-usw1",
|
|
|
|
PeeringToken: validTokenB64,
|
|
|
|
Meta: generateTooManyMetaKeys(),
|
|
|
|
},
|
|
|
|
expectErr: "meta tags failed validation:",
|
|
|
|
},
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-06-08 22:53:32 +00:00
|
|
|
|
2022-10-07 18:17:11 +00:00
|
|
|
// When tokens have the same name as the dialing cluster, we
|
2022-09-09 21:09:32 +00:00
|
|
|
// should be throwing an error to note the server name conflict.
|
|
|
|
func TestPeeringService_Establish_serverNameConflict(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, nil)
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Manufacture token to have the same server name but a PeerID not in the store.
|
|
|
|
id, err := uuid.GenerateUUID()
|
|
|
|
require.NoError(t, err, "could not generate uuid")
|
2022-09-29 03:27:11 +00:00
|
|
|
|
2022-09-29 21:49:58 +00:00
|
|
|
serverName, _, err := s.Server.GetPeeringBackend().GetTLSMaterials(true)
|
2022-09-29 03:27:11 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-09-09 21:09:32 +00:00
|
|
|
peeringToken := structs.PeeringToken{
|
|
|
|
ServerAddresses: []string{"1.2.3.4:8502"},
|
2022-09-29 03:27:11 +00:00
|
|
|
ServerName: serverName,
|
2022-09-09 21:09:32 +00:00
|
|
|
EstablishmentSecret: "foo",
|
|
|
|
PeerID: id,
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonToken, err := json.Marshal(peeringToken)
|
|
|
|
require.NoError(t, err, "could not marshal peering token")
|
|
|
|
base64Token := base64.StdEncoding.EncodeToString(jsonToken)
|
|
|
|
|
|
|
|
establishReq := &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "peerTwo",
|
|
|
|
PeeringToken: base64Token,
|
|
|
|
}
|
|
|
|
|
|
|
|
respE, errE := client.Establish(ctx, establishReq)
|
|
|
|
require.Error(t, errE)
|
2022-10-07 18:17:11 +00:00
|
|
|
require.Contains(t, errE.Error(), "cannot create a peering within the same cluster")
|
2022-09-09 21:09:32 +00:00
|
|
|
require.Nil(t, respE)
|
|
|
|
}
|
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
func TestPeeringService_Establish(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
2022-09-29 03:27:11 +00:00
|
|
|
s1 := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.NodeName = "s1"
|
2022-10-05 13:10:19 +00:00
|
|
|
conf.Datacenter = "test-dc1"
|
|
|
|
conf.PrimaryDatacenter = "test-dc1"
|
2022-09-29 03:27:11 +00:00
|
|
|
})
|
2022-08-01 14:33:18 +00:00
|
|
|
client1 := pbpeering.NewPeeringServiceClient(s1.ClientConn(t))
|
|
|
|
|
|
|
|
s2 := newTestServer(t, func(conf *consul.Config) {
|
2022-09-29 03:27:11 +00:00
|
|
|
conf.NodeName = "s2"
|
2022-09-09 21:09:32 +00:00
|
|
|
conf.Datacenter = "dc2"
|
2022-09-29 03:27:11 +00:00
|
|
|
conf.PrimaryDatacenter = "dc2"
|
2022-08-01 14:33:18 +00:00
|
|
|
})
|
|
|
|
client2 := pbpeering.NewPeeringServiceClient(s2.ClientConn(t))
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Generate a peering token for s2
|
|
|
|
tokenResp, err := client1.GenerateToken(ctx, &pbpeering.GenerateTokenRequest{PeerName: "my-peer-s2"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
var peerID string
|
|
|
|
testutil.RunStep(t, "peering can be established from token", func(t *testing.T) {
|
2022-09-29 03:27:11 +00:00
|
|
|
retry.Run(t, func(r *retry.R) {
|
|
|
|
_, err = client2.Establish(ctx, &pbpeering.EstablishRequest{PeerName: "my-peer-s1", PeeringToken: tokenResp.PeeringToken})
|
|
|
|
require.NoError(r, err)
|
|
|
|
})
|
2022-08-01 14:33:18 +00:00
|
|
|
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Read the expected peering at s2 to validate it
|
|
|
|
resp, err := client2.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: "my-peer-s1"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
peerID = resp.Peering.ID
|
|
|
|
|
|
|
|
// Check individual values, ignoring the create/modify indexes.
|
|
|
|
tokenJSON, err := base64.StdEncoding.DecodeString(tokenResp.PeeringToken)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
var token structs.PeeringToken
|
|
|
|
require.NoError(t, json.Unmarshal(tokenJSON, &token))
|
|
|
|
|
|
|
|
require.Equal(t, "my-peer-s1", resp.Peering.Name)
|
|
|
|
require.Equal(t, token.CA, resp.Peering.PeerCAPems)
|
|
|
|
require.Equal(t, token.ServerAddresses, resp.Peering.PeerServerAddresses)
|
|
|
|
require.Equal(t, token.ServerName, resp.Peering.PeerServerName)
|
2022-10-05 13:10:19 +00:00
|
|
|
require.Equal(t, "test-dc1", token.Remote.Datacenter)
|
|
|
|
require.Equal(t, "test-dc1", resp.Peering.Remote.Datacenter)
|
|
|
|
require.Equal(t, token.Remote.Partition, resp.Peering.Remote.Partition)
|
2022-08-01 14:33:18 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "stream secret is persisted", func(t *testing.T) {
|
|
|
|
secret, err := s2.Server.FSM().State().PeeringSecretsRead(nil, peerID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, secret.GetStream().GetActiveSecretID())
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "peering tokens cannot be reused after secret exchange", func(t *testing.T) {
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
_, err = client2.Establish(ctx, &pbpeering.EstablishRequest{PeerName: "my-peer-s1", PeeringToken: tokenResp.PeeringToken})
|
|
|
|
require.Contains(t, err.Error(), "invalid peering establishment secret")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-10-10 19:45:30 +00:00
|
|
|
func TestPeeringService_Establish_ThroughMeshGateway(t *testing.T) {
|
|
|
|
// This test is timing-sensitive, must not be run in parallel.
|
|
|
|
// t.Parallel()
|
|
|
|
|
|
|
|
acceptor := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.NodeName = "acceptor"
|
|
|
|
})
|
|
|
|
acceptorClient := pbpeering.NewPeeringServiceClient(acceptor.ClientConn(t))
|
|
|
|
|
|
|
|
dialer := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.NodeName = "dialer"
|
|
|
|
conf.Datacenter = "dc2"
|
|
|
|
conf.PrimaryDatacenter = "dc2"
|
|
|
|
})
|
|
|
|
dialerClient := pbpeering.NewPeeringServiceClient(dialer.ClientConn(t))
|
|
|
|
|
|
|
|
var peeringToken string
|
|
|
|
|
|
|
|
testutil.RunStep(t, "retry until timeout on dial errors", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
testToken := structs.PeeringToken{
|
|
|
|
ServerAddresses: []string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))},
|
|
|
|
PeerID: testUUID(t),
|
|
|
|
}
|
|
|
|
testTokenJSON, _ := json.Marshal(&testToken)
|
|
|
|
testTokenB64 := base64.StdEncoding.EncodeToString(testTokenJSON)
|
|
|
|
|
|
|
|
start := time.Now()
|
|
|
|
_, err := dialerClient.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "my-peer-acceptor",
|
|
|
|
PeeringToken: testTokenB64,
|
|
|
|
})
|
|
|
|
require.Error(t, err)
|
|
|
|
testutil.RequireErrorContains(t, err, "connection refused")
|
|
|
|
|
|
|
|
require.Greater(t, time.Since(start), 5*time.Second)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "peering can be established from token", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Generate a peering token for dialer
|
|
|
|
tokenResp, err := acceptorClient.GenerateToken(ctx, &pbpeering.GenerateTokenRequest{PeerName: "my-peer-dialer"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Capture peering token for re-use later
|
|
|
|
peeringToken = tokenResp.PeeringToken
|
|
|
|
|
|
|
|
// The context timeout is short, it checks that we do not wait the 350ms that we do when peering through mesh gateways
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 300*time.Millisecond)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
_, err = dialerClient.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "my-peer-acceptor",
|
|
|
|
PeeringToken: tokenResp.PeeringToken,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "fail fast on permission denied", func(t *testing.T) {
|
|
|
|
// This test case re-uses the previous token since the establishment secret will have been invalidated.
|
|
|
|
// The context timeout is short, it checks that we do not retry.
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
_, err := dialerClient.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "my-peer-acceptor",
|
|
|
|
PeeringToken: peeringToken,
|
|
|
|
})
|
2022-10-20 23:10:03 +00:00
|
|
|
grpcErr, ok := grpcstatus.FromError(err)
|
|
|
|
require.True(t, ok)
|
|
|
|
require.Equal(t, codes.PermissionDenied, grpcErr.Code())
|
2022-10-10 19:45:30 +00:00
|
|
|
testutil.RequireErrorContains(t, err, "a new peering token must be generated")
|
|
|
|
})
|
|
|
|
|
|
|
|
gatewayPort := freeport.GetOne(t)
|
|
|
|
|
|
|
|
testutil.RunStep(t, "fail past bad mesh gateway", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Generate a new peering token for the dialer.
|
|
|
|
tokenResp, err := acceptorClient.GenerateToken(ctx, &pbpeering.GenerateTokenRequest{PeerName: "my-peer-dialer"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
store := dialer.Server.FSM().State()
|
|
|
|
require.NoError(t, store.EnsureConfigEntry(1, &structs.MeshConfigEntry{
|
|
|
|
Peering: &structs.PeeringMeshConfig{
|
|
|
|
PeerThroughMeshGateways: true,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
// Register a gateway that isn't actually listening.
|
|
|
|
require.NoError(t, store.EnsureRegistration(2, &structs.RegisterRequest{
|
|
|
|
ID: types.NodeID(testUUID(t)),
|
|
|
|
Node: "gateway-node-1",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Kind: structs.ServiceKindMeshGateway,
|
|
|
|
ID: "mesh-gateway-1",
|
|
|
|
Service: "mesh-gateway",
|
|
|
|
Port: gatewayPort,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Call to establish should succeed when we fall back to remote server address.
|
|
|
|
_, err = dialerClient.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "my-peer-acceptor",
|
|
|
|
PeeringToken: tokenResp.PeeringToken,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "route through gateway", func(t *testing.T) {
|
|
|
|
// Spin up a proxy listening at the gateway port registered above.
|
|
|
|
gatewayAddr := fmt.Sprintf("127.0.0.1:%d", gatewayPort)
|
|
|
|
|
|
|
|
// Configure a TCP proxy with an SNI route corresponding to the acceptor cluster.
|
|
|
|
var proxy tcpproxy.Proxy
|
|
|
|
target := &connWrapper{
|
|
|
|
proxy: tcpproxy.DialProxy{
|
|
|
|
Addr: acceptor.PublicGRPCAddr,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
proxy.AddSNIRoute(gatewayAddr, "server.dc1.peering.11111111-2222-3333-4444-555555555555.consul", target)
|
|
|
|
proxy.AddStopACMESearch(gatewayAddr)
|
|
|
|
|
|
|
|
require.NoError(t, proxy.Start())
|
|
|
|
t.Cleanup(func() {
|
|
|
|
proxy.Close()
|
|
|
|
proxy.Wait()
|
|
|
|
})
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// Generate a new peering token for the dialer.
|
|
|
|
tokenResp, err := acceptorClient.GenerateToken(ctx, &pbpeering.GenerateTokenRequest{PeerName: "my-peer-dialer"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
store := dialer.Server.FSM().State()
|
|
|
|
require.NoError(t, store.EnsureConfigEntry(1, &structs.MeshConfigEntry{
|
|
|
|
Peering: &structs.PeeringMeshConfig{
|
|
|
|
PeerThroughMeshGateways: true,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
start := time.Now()
|
|
|
|
|
|
|
|
// Call to establish should succeed through the proxy.
|
|
|
|
_, err = dialerClient.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "my-peer-acceptor",
|
|
|
|
PeeringToken: tokenResp.PeeringToken,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Dialing through a gateway is preceded by a mandatory 350ms sleep.
|
|
|
|
require.Greater(t, time.Since(start), 350*time.Millisecond)
|
|
|
|
|
|
|
|
// target.called is true when the tcproxy's conn handler was invoked.
|
|
|
|
// This lets us know that the "Establish" success flowed through the proxy masquerading as a gateway.
|
|
|
|
require.True(t, target.called)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// connWrapper is a wrapper around tcpproxy.DialProxy to enable tracking whether the proxy handled a connection.
|
|
|
|
type connWrapper struct {
|
|
|
|
proxy tcpproxy.DialProxy
|
|
|
|
called bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *connWrapper) HandleConn(src net.Conn) {
|
|
|
|
w.called = true
|
|
|
|
w.proxy.HandleConn(src)
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_Establish_ACLEnforcement(t *testing.T) {
|
|
|
|
validToken := peering.TestPeeringToken("83474a06-cca4-4ff4-99a4-4152929c8160")
|
|
|
|
validTokenJSON, _ := json.Marshal(&validToken)
|
|
|
|
validTokenB64 := base64.StdEncoding.EncodeToString(validTokenJSON)
|
|
|
|
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.EstablishRequest
|
|
|
|
token string
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.Establish(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NotContains(t, err.Error(), "lacks permission")
|
2022-07-12 23:18:05 +00:00
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "foo",
|
|
|
|
PeeringToken: validTokenB64,
|
|
|
|
},
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "read token lacks permissions",
|
|
|
|
req: &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "foo",
|
|
|
|
PeeringToken: validTokenB64,
|
|
|
|
},
|
|
|
|
token: testTokenPeeringReadSecret,
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "write token grants permission",
|
|
|
|
req: &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "foo",
|
|
|
|
PeeringToken: validTokenB64,
|
|
|
|
},
|
|
|
|
token: testTokenPeeringWriteSecret,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func TestPeeringService_Read(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, nil)
|
|
|
|
|
|
|
|
// insert peering directly to state store
|
|
|
|
p := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "test",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p})
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.PeeringReadRequest
|
|
|
|
expect *pbpeering.PeeringReadResponse
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
resp, err := client.PeeringRead(ctx, tc.req)
|
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
prototest.AssertDeepEqual(t, tc.expect, resp)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "returns foo",
|
|
|
|
req: &pbpeering.PeeringReadRequest{Name: "foo"},
|
|
|
|
expect: &pbpeering.PeeringReadResponse{Peering: p},
|
|
|
|
expectErr: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "bar not found",
|
|
|
|
req: &pbpeering.PeeringReadRequest{Name: "bar"},
|
|
|
|
expect: &pbpeering.PeeringReadResponse{},
|
|
|
|
expectErr: "",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_Read_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
// insert peering directly to state store
|
|
|
|
p := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "test",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
2022-07-12 23:18:05 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p})
|
2022-07-12 23:18:05 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.PeeringReadRequest
|
|
|
|
expect *pbpeering.PeeringReadResponse
|
|
|
|
token string
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
resp, err := client.PeeringRead(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
prototest.AssertDeepEqual(t, tc.expect, resp)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.PeeringReadRequest{Name: "foo"},
|
|
|
|
expect: &pbpeering.PeeringReadResponse{Peering: p},
|
|
|
|
expectErr: "lacks permission 'peering:read'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "read token grants permission",
|
|
|
|
req: &pbpeering.PeeringReadRequest{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
expect: &pbpeering.PeeringReadResponse{Peering: p},
|
|
|
|
token: testTokenPeeringReadSecret,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-08 22:53:32 +00:00
|
|
|
func TestPeeringService_Delete(t *testing.T) {
|
2022-08-26 16:52:47 +00:00
|
|
|
tt := map[string]pbpeering.PeeringState{
|
|
|
|
"active peering": pbpeering.PeeringState_ACTIVE,
|
|
|
|
"terminated peering": pbpeering.PeeringState_TERMINATED,
|
2022-06-08 22:53:32 +00:00
|
|
|
}
|
|
|
|
|
2022-08-26 16:52:47 +00:00
|
|
|
for name, overrideState := range tt {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, nil)
|
|
|
|
|
2022-11-03 21:34:57 +00:00
|
|
|
id := testUUID(t)
|
|
|
|
|
|
|
|
// Write an initial peering
|
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{
|
|
|
|
ID: id,
|
|
|
|
Name: "foo",
|
|
|
|
}}))
|
|
|
|
|
|
|
|
_, p, err := s.Server.FSM().State().PeeringRead(nil, state.Query{Value: "foo"})
|
2022-08-26 16:52:47 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, p.DeletedAt)
|
|
|
|
require.True(t, p.IsActive())
|
2022-06-08 22:53:32 +00:00
|
|
|
|
2022-11-03 21:34:57 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{
|
|
|
|
ID: id,
|
|
|
|
Name: "foo",
|
|
|
|
|
|
|
|
// Update the peering state to simulate deleting from a non-initial state.
|
|
|
|
State: overrideState,
|
|
|
|
}}))
|
2022-06-08 22:53:32 +00:00
|
|
|
|
2022-08-26 16:52:47 +00:00
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
2022-06-08 22:53:32 +00:00
|
|
|
|
2022-08-26 16:52:47 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
2022-06-14 01:50:59 +00:00
|
|
|
|
2022-08-26 16:52:47 +00:00
|
|
|
_, err = client.PeeringDelete(ctx, &pbpeering.PeeringDeleteRequest{Name: "foo"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
retry.Run(t, func(r *retry.R) {
|
|
|
|
_, resp, err := s.Server.FSM().State().PeeringRead(nil, state.Query{Value: "foo"})
|
|
|
|
require.NoError(r, err)
|
|
|
|
|
|
|
|
// Initially the peering will be marked for deletion but eventually the leader
|
|
|
|
// routine will clean it up.
|
|
|
|
require.Nil(r, resp)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2022-06-08 22:53:32 +00:00
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_Delete_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
p := &pbpeering.Peering{
|
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "test",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p})
|
2022-07-12 23:18:05 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, p.DeletedAt)
|
|
|
|
require.True(t, p.IsActive())
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.PeeringDeleteRequest
|
|
|
|
token string
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.PeeringDelete(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.PeeringDeleteRequest{Name: "foo"},
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "read token lacks permissions",
|
|
|
|
req: &pbpeering.PeeringDeleteRequest{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
token: testTokenPeeringReadSecret,
|
|
|
|
expectErr: "lacks permission 'peering:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "write token grants permission",
|
|
|
|
req: &pbpeering.PeeringDeleteRequest{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
token: testTokenPeeringWriteSecret,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
func TestPeeringService_List(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, nil)
|
|
|
|
|
|
|
|
// Insert peerings directly to state store.
|
|
|
|
// Note that the state store holds reference to the underlying
|
|
|
|
// variables; do not modify them after writing.
|
|
|
|
foo := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "fooservername",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: foo}))
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
bar := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "bar",
|
|
|
|
State: pbpeering.PeeringState_ACTIVE,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "barservername",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(15, &pbpeering.PeeringWriteRequest{Peering: bar}))
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
resp, err := client.PeeringList(ctx, &pbpeering.PeeringListRequest{})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
expect := &pbpeering.PeeringListResponse{
|
|
|
|
Peerings: []*pbpeering.Peering{bar, foo},
|
2022-09-26 16:50:17 +00:00
|
|
|
Index: 15,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
prototest.AssertDeepEqual(t, expect, resp)
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_List_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
// insert peering directly to state store
|
|
|
|
foo := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "fooservername",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
2022-07-12 23:18:05 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: foo}))
|
2022-07-12 23:18:05 +00:00
|
|
|
bar := &pbpeering.Peering{
|
2022-09-29 19:37:19 +00:00
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "bar",
|
|
|
|
State: pbpeering.PeeringState_ACTIVE,
|
|
|
|
PeerCAPems: nil,
|
|
|
|
PeerServerName: "barservername",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
2022-07-12 23:18:05 +00:00
|
|
|
}
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(15, &pbpeering.PeeringWriteRequest{Peering: bar}))
|
2022-07-12 23:18:05 +00:00
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
token string
|
|
|
|
expect *pbpeering.PeeringListResponse
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
resp, err := client.PeeringList(ctx, &pbpeering.PeeringListRequest{})
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
prototest.AssertDeepEqual(t, tc.expect, resp)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
expectErr: "lacks permission 'peering:read'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "read token grants permission",
|
|
|
|
token: testTokenPeeringReadSecret,
|
|
|
|
expect: &pbpeering.PeeringListResponse{
|
|
|
|
Peerings: []*pbpeering.Peering{bar, foo},
|
2022-09-26 16:50:17 +00:00
|
|
|
Index: 15,
|
2022-07-12 23:18:05 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-31 15:54:40 +00:00
|
|
|
func TestPeeringService_TrustBundleRead(t *testing.T) {
|
|
|
|
srv := newTestServer(t, nil)
|
|
|
|
store := srv.Server.FSM().State()
|
|
|
|
client := pbpeering.NewPeeringServiceClient(srv.ClientConn(t))
|
|
|
|
|
|
|
|
var lastIdx uint64 = 1
|
|
|
|
_ = setupTestPeering(t, store, "my-peering", lastIdx)
|
|
|
|
|
|
|
|
bundle := &pbpeering.PeeringTrustBundle{
|
|
|
|
TrustDomain: "peer1.com",
|
|
|
|
PeerName: "my-peering",
|
|
|
|
RootPEMs: []string{"peer1-root-1"},
|
|
|
|
}
|
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.PeeringTrustBundleWrite(lastIdx, bundle))
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
resp, err := client.TrustBundleRead(ctx, &pbpeering.TrustBundleReadRequest{
|
|
|
|
Name: "my-peering",
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, lastIdx, resp.Index)
|
|
|
|
require.NotNil(t, resp.Bundle)
|
|
|
|
prototest.AssertDeepEqual(t, bundle, resp.Bundle)
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_TrustBundleRead_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
store := s.Server.FSM().State()
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
// Insert peering and trust bundle directly to state store.
|
|
|
|
_ = setupTestPeering(t, store, "my-peering", 10)
|
|
|
|
|
|
|
|
bundle := &pbpeering.PeeringTrustBundle{
|
|
|
|
TrustDomain: "peer1.com",
|
|
|
|
PeerName: "my-peering",
|
|
|
|
RootPEMs: []string{"peer1-root-1"},
|
|
|
|
}
|
|
|
|
require.NoError(t, store.PeeringTrustBundleWrite(11, bundle))
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.TrustBundleReadRequest
|
|
|
|
token string
|
|
|
|
expect *pbpeering.PeeringTrustBundle
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
resp, err := client.TrustBundleRead(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
prototest.AssertDeepEqual(t, tc.expect, resp.Bundle)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.TrustBundleReadRequest{Name: "foo"},
|
|
|
|
expectErr: "lacks permission 'service:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "service read token lacks permissions",
|
|
|
|
req: &pbpeering.TrustBundleReadRequest{
|
|
|
|
Name: "my-peering",
|
|
|
|
},
|
|
|
|
token: testTokenServiceReadSecret,
|
|
|
|
expectErr: "lacks permission 'service:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with service write token",
|
|
|
|
req: &pbpeering.TrustBundleReadRequest{
|
|
|
|
Name: "my-peering",
|
|
|
|
},
|
|
|
|
token: testTokenServiceWriteSecret,
|
|
|
|
expect: bundle,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
// Setup:
|
|
|
|
// - Peerings "foo" and "bar" with trust bundles saved
|
|
|
|
// - "api" service exported to both "foo" and "bar"
|
|
|
|
// - "web" service exported to "baz"
|
2022-05-12 22:58:22 +00:00
|
|
|
func TestPeeringService_TrustBundleListByService(t *testing.T) {
|
2022-05-23 23:57:42 +00:00
|
|
|
s := newTestServer(t, nil)
|
|
|
|
store := s.Server.FSM().State()
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
var lastIdx uint64 = 10
|
2022-05-23 16:16:39 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{
|
|
|
|
Peering: &pbpeering.Peering{
|
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerServerName: "test",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
|
|
|
},
|
2022-05-23 23:57:42 +00:00
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{
|
|
|
|
Peering: &pbpeering.Peering{
|
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "bar",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerServerName: "test-bar",
|
|
|
|
PeerServerAddresses: []string{"addr2"},
|
|
|
|
},
|
2022-05-23 23:57:42 +00:00
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.PeeringTrustBundleWrite(lastIdx, &pbpeering.PeeringTrustBundle{
|
|
|
|
TrustDomain: "foo.com",
|
|
|
|
PeerName: "foo",
|
|
|
|
RootPEMs: []string{"foo-root-1"},
|
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.PeeringTrustBundleWrite(lastIdx, &pbpeering.PeeringTrustBundle{
|
|
|
|
TrustDomain: "bar.com",
|
|
|
|
PeerName: "bar",
|
|
|
|
RootPEMs: []string{"bar-root-1"},
|
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.EnsureNode(lastIdx, &structs.Node{
|
|
|
|
Node: "my-node", Address: "127.0.0.1",
|
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.EnsureService(lastIdx, "my-node", &structs.NodeService{
|
|
|
|
ID: "api",
|
|
|
|
Service: "api",
|
|
|
|
Port: 8000,
|
|
|
|
}))
|
2022-05-12 22:58:22 +00:00
|
|
|
|
2022-05-23 23:57:42 +00:00
|
|
|
entry := structs.ExportedServicesConfigEntry{
|
|
|
|
Name: "default",
|
|
|
|
Services: []structs.ExportedService{
|
2022-05-12 22:58:22 +00:00
|
|
|
{
|
2022-05-23 23:57:42 +00:00
|
|
|
Name: "api",
|
|
|
|
Consumers: []structs.ServiceConsumer{
|
2022-05-12 22:58:22 +00:00
|
|
|
{
|
2022-10-04 18:46:15 +00:00
|
|
|
Peer: "foo",
|
2022-05-12 22:58:22 +00:00
|
|
|
},
|
|
|
|
{
|
2022-10-04 18:46:15 +00:00
|
|
|
Peer: "bar",
|
2022-05-12 22:58:22 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-05-23 16:16:39 +00:00
|
|
|
{
|
2022-05-23 23:57:42 +00:00
|
|
|
Name: "web",
|
|
|
|
Consumers: []structs.ServiceConsumer{
|
2022-05-23 16:16:39 +00:00
|
|
|
{
|
2022-10-04 18:46:15 +00:00
|
|
|
Peer: "baz",
|
2022-05-23 16:16:39 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-05-23 23:57:42 +00:00
|
|
|
}
|
|
|
|
require.NoError(t, entry.Normalize())
|
|
|
|
require.NoError(t, entry.Validate())
|
2022-05-12 22:58:22 +00:00
|
|
|
|
|
|
|
lastIdx++
|
2022-05-23 23:57:42 +00:00
|
|
|
require.NoError(t, store.EnsureConfigEntry(lastIdx, &entry))
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
req := pbpeering.TrustBundleListByServiceRequest{
|
|
|
|
ServiceName: "api",
|
|
|
|
}
|
|
|
|
resp, err := client.TrustBundleListByService(context.Background(), &req)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, resp.Bundles, 2)
|
2022-06-27 19:37:18 +00:00
|
|
|
require.Equal(t, []string{"bar-root-1"}, resp.Bundles[0].RootPEMs)
|
|
|
|
require.Equal(t, []string{"foo-root-1"}, resp.Bundles[1].RootPEMs)
|
2022-05-12 22:58:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 22:56:25 +00:00
|
|
|
func TestPeeringService_validatePeer(t *testing.T) {
|
2022-09-29 03:27:11 +00:00
|
|
|
s1 := newTestServer(t, nil)
|
2022-08-01 14:33:18 +00:00
|
|
|
client1 := pbpeering.NewPeeringServiceClient(s1.ClientConn(t))
|
|
|
|
|
2022-07-22 22:56:25 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
testutil.RunStep(t, "generate a token", func(t *testing.T) {
|
|
|
|
req := pbpeering.GenerateTokenRequest{PeerName: "peerB"}
|
2022-08-01 14:33:18 +00:00
|
|
|
resp, err := client1.GenerateToken(ctx, &req)
|
2022-07-22 22:56:25 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, resp)
|
|
|
|
})
|
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
s2 := newTestServer(t, func(conf *consul.Config) {
|
2022-09-09 21:09:32 +00:00
|
|
|
conf.Datacenter = "dc2"
|
2022-09-29 03:27:11 +00:00
|
|
|
conf.PrimaryDatacenter = "dc2"
|
2022-07-22 22:56:25 +00:00
|
|
|
})
|
2022-08-01 14:33:18 +00:00
|
|
|
client2 := pbpeering.NewPeeringServiceClient(s2.ClientConn(t))
|
2022-07-22 22:56:25 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
req := pbpeering.GenerateTokenRequest{PeerName: "my-peer-s1"}
|
|
|
|
resp, err := client2.GenerateToken(ctx, &req)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, resp)
|
2022-07-22 22:56:25 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
s2Token := resp.PeeringToken
|
2022-07-22 22:56:25 +00:00
|
|
|
|
2022-08-01 14:33:18 +00:00
|
|
|
testutil.RunStep(t, "send an establish request for a different peer name", func(t *testing.T) {
|
|
|
|
resp, err := client1.Establish(ctx, &pbpeering.EstablishRequest{
|
|
|
|
PeerName: "peerC",
|
|
|
|
PeeringToken: s2Token,
|
2022-07-22 22:56:25 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, resp)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "attempt to generate token with the same name used as dialer", func(t *testing.T) {
|
2022-08-01 14:33:18 +00:00
|
|
|
req := pbpeering.GenerateTokenRequest{PeerName: "peerC"}
|
|
|
|
resp, err := client1.GenerateToken(ctx, &req)
|
2022-07-22 22:56:25 +00:00
|
|
|
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Contains(t, err.Error(),
|
2022-08-01 14:33:18 +00:00
|
|
|
"cannot create peering with name: \"peerC\"; there is already an established peering")
|
2022-07-22 22:56:25 +00:00
|
|
|
require.Nil(t, resp)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "attempt to establish the with the same name used as acceptor", func(t *testing.T) {
|
2022-08-01 14:33:18 +00:00
|
|
|
resp, err := client1.Establish(ctx, &pbpeering.EstablishRequest{
|
2022-07-22 22:56:25 +00:00
|
|
|
PeerName: "peerB",
|
2022-08-01 14:33:18 +00:00
|
|
|
PeeringToken: s2Token,
|
2022-07-22 22:56:25 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Contains(t, err.Error(),
|
|
|
|
"cannot create peering with name: \"peerB\"; there is an existing peering expecting to be dialed")
|
|
|
|
require.Nil(t, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-07-22 22:20:21 +00:00
|
|
|
// Test RPC endpoint responses when peering is disabled. They should all return an error.
|
|
|
|
func TestPeeringService_PeeringDisabled(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(c *consul.Config) { c.PeeringEnabled = false })
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
// assertFailedResponse is a helper function that checks the error from a gRPC
|
|
|
|
// response is what we expect when peering is disabled.
|
|
|
|
assertFailedResponse := func(t *testing.T, err error) {
|
|
|
|
actErr, ok := grpcstatus.FromError(err)
|
|
|
|
require.True(t, ok)
|
|
|
|
require.Equal(t, codes.FailedPrecondition, actErr.Code())
|
|
|
|
require.Equal(t, "peering must be enabled to use this endpoint", actErr.Message())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test all the endpoints.
|
|
|
|
|
|
|
|
t.Run("PeeringWrite", func(t *testing.T) {
|
|
|
|
_, err := client.PeeringWrite(ctx, &pbpeering.PeeringWriteRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("PeeringRead", func(t *testing.T) {
|
|
|
|
_, err := client.PeeringRead(ctx, &pbpeering.PeeringReadRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("PeeringDelete", func(t *testing.T) {
|
|
|
|
_, err := client.PeeringDelete(ctx, &pbpeering.PeeringDeleteRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("PeeringList", func(t *testing.T) {
|
|
|
|
_, err := client.PeeringList(ctx, &pbpeering.PeeringListRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Establish", func(t *testing.T) {
|
|
|
|
_, err := client.Establish(ctx, &pbpeering.EstablishRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("GenerateToken", func(t *testing.T) {
|
|
|
|
_, err := client.GenerateToken(ctx, &pbpeering.GenerateTokenRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("TrustBundleRead", func(t *testing.T) {
|
|
|
|
_, err := client.TrustBundleRead(ctx, &pbpeering.TrustBundleReadRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("TrustBundleListByService", func(t *testing.T) {
|
|
|
|
_, err := client.TrustBundleListByService(ctx, &pbpeering.TrustBundleListByServiceRequest{})
|
|
|
|
assertFailedResponse(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func TestPeeringService_TrustBundleListByService_ACLEnforcement(t *testing.T) {
|
|
|
|
// TODO(peering): see note on newTestServer, refactor to not use this
|
|
|
|
s := newTestServer(t, func(conf *consul.Config) {
|
|
|
|
conf.ACLsEnabled = true
|
|
|
|
conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny
|
|
|
|
})
|
|
|
|
store := s.Server.FSM().State()
|
|
|
|
upsertTestACLs(t, s.Server.FSM().State())
|
|
|
|
|
|
|
|
var lastIdx uint64 = 10
|
|
|
|
|
|
|
|
lastIdx++
|
2022-08-01 14:33:18 +00:00
|
|
|
require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{
|
|
|
|
Peering: &pbpeering.Peering{
|
|
|
|
ID: testUUID(t),
|
|
|
|
Name: "foo",
|
|
|
|
State: pbpeering.PeeringState_ESTABLISHING,
|
|
|
|
PeerServerName: "test",
|
|
|
|
PeerServerAddresses: []string{"addr1"},
|
|
|
|
},
|
2022-07-12 23:18:05 +00:00
|
|
|
}))
|
|
|
|
|
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.PeeringTrustBundleWrite(lastIdx, &pbpeering.PeeringTrustBundle{
|
|
|
|
TrustDomain: "foo.com",
|
|
|
|
PeerName: "foo",
|
|
|
|
RootPEMs: []string{"foo-root-1"},
|
|
|
|
}))
|
|
|
|
|
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.EnsureNode(lastIdx, &structs.Node{
|
|
|
|
Node: "my-node", Address: "127.0.0.1",
|
|
|
|
}))
|
|
|
|
|
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.EnsureService(lastIdx, "my-node", &structs.NodeService{
|
|
|
|
ID: "api",
|
|
|
|
Service: "api",
|
|
|
|
Port: 8000,
|
|
|
|
}))
|
|
|
|
|
|
|
|
entry := structs.ExportedServicesConfigEntry{
|
|
|
|
Name: "default",
|
|
|
|
Services: []structs.ExportedService{
|
|
|
|
{
|
|
|
|
Name: "api",
|
|
|
|
Consumers: []structs.ServiceConsumer{
|
|
|
|
{
|
2022-10-04 18:46:15 +00:00
|
|
|
Peer: "foo",
|
2022-07-12 23:18:05 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
require.NoError(t, entry.Normalize())
|
|
|
|
require.NoError(t, entry.Validate())
|
|
|
|
|
|
|
|
lastIdx++
|
|
|
|
require.NoError(t, store.EnsureConfigEntry(lastIdx, &entry))
|
|
|
|
|
|
|
|
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
|
|
|
|
|
|
|
type testcase struct {
|
|
|
|
name string
|
|
|
|
req *pbpeering.TrustBundleListByServiceRequest
|
|
|
|
token string
|
|
|
|
expect []string
|
|
|
|
expectErr string
|
|
|
|
}
|
|
|
|
run := func(t *testing.T, tc testcase) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-09-28 16:56:59 +00:00
|
|
|
options := structs.QueryOptions{Token: tc.token}
|
|
|
|
ctx, err := external.ContextWithQueryOptions(ctx, options)
|
|
|
|
require.NoError(t, err)
|
|
|
|
resp, err := client.TrustBundleListByService(ctx, tc.req)
|
2022-07-12 23:18:05 +00:00
|
|
|
if tc.expectErr != "" {
|
|
|
|
require.Contains(t, err.Error(), tc.expectErr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, resp.Bundles, 1)
|
|
|
|
require.Equal(t, tc.expect, resp.Bundles[0].RootPEMs)
|
|
|
|
}
|
|
|
|
tcs := []testcase{
|
|
|
|
{
|
|
|
|
name: "anonymous token lacks permissions",
|
|
|
|
req: &pbpeering.TrustBundleListByServiceRequest{ServiceName: "api"},
|
|
|
|
expectErr: "lacks permission 'service:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "service read token lacks permission",
|
|
|
|
req: &pbpeering.TrustBundleListByServiceRequest{
|
|
|
|
ServiceName: "api",
|
|
|
|
},
|
|
|
|
token: testTokenServiceReadSecret,
|
|
|
|
expectErr: "lacks permission 'service:write'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with service write token",
|
|
|
|
req: &pbpeering.TrustBundleListByServiceRequest{
|
|
|
|
ServiceName: "api",
|
|
|
|
},
|
|
|
|
token: testTokenServiceWriteSecret,
|
|
|
|
expect: []string{"foo-root-1"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
run(t, tc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
// newTestServer is copied from partition/service_test.go, with the addition of certs/cas.
|
|
|
|
// TODO(peering): these are endpoint tests and should live in the agent/consul
|
|
|
|
// package. Instead, these can be written around a mock client (see testing.go)
|
|
|
|
// and a mock backend (future)
|
|
|
|
func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer {
|
|
|
|
t.Helper()
|
|
|
|
conf := consul.DefaultConfig()
|
|
|
|
dir := testutil.TempDir(t, "consul")
|
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
ports := freeport.GetN(t, 4) // {rpc, serf_lan, serf_wan, grpc}
|
2022-05-11 19:20:50 +00:00
|
|
|
|
2022-08-01 19:22:36 +00:00
|
|
|
conf.PeeringEnabled = true
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
conf.Bootstrap = true
|
|
|
|
conf.Datacenter = "dc1"
|
|
|
|
conf.DataDir = dir
|
2022-05-11 19:20:50 +00:00
|
|
|
conf.RPCAddr = &net.TCPAddr{IP: []byte{127, 0, 0, 1}, Port: ports[0]}
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
conf.RaftConfig.ElectionTimeout = 200 * time.Millisecond
|
|
|
|
conf.RaftConfig.LeaderLeaseTimeout = 100 * time.Millisecond
|
|
|
|
conf.RaftConfig.HeartbeatTimeout = 200 * time.Millisecond
|
|
|
|
conf.TLSConfig.Domain = "consul"
|
|
|
|
|
2022-05-11 19:20:50 +00:00
|
|
|
conf.SerfLANConfig.MemberlistConfig.BindAddr = "127.0.0.1"
|
|
|
|
conf.SerfLANConfig.MemberlistConfig.BindPort = ports[1]
|
|
|
|
conf.SerfLANConfig.MemberlistConfig.AdvertisePort = ports[1]
|
|
|
|
conf.SerfWANConfig.MemberlistConfig.BindAddr = "127.0.0.1"
|
|
|
|
conf.SerfWANConfig.MemberlistConfig.BindPort = ports[2]
|
|
|
|
conf.SerfWANConfig.MemberlistConfig.AdvertisePort = ports[2]
|
|
|
|
|
2022-05-25 17:37:44 +00:00
|
|
|
conf.PrimaryDatacenter = "dc1"
|
|
|
|
conf.ConnectEnabled = true
|
|
|
|
|
2022-09-29 03:27:11 +00:00
|
|
|
ca := connect.TestCA(t, nil)
|
|
|
|
conf.CAConfig = &structs.CAConfiguration{
|
|
|
|
ClusterID: connect.TestClusterID,
|
|
|
|
Provider: structs.ConsulCAProvider,
|
|
|
|
Config: map[string]interface{}{
|
|
|
|
"PrivateKey": ca.SigningKey,
|
|
|
|
"RootCert": ca.RootCert,
|
|
|
|
"LeafCertTTL": "72h",
|
|
|
|
"IntermediateCertTTL": "288h",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
conf.GRPCTLSPort = ports[3]
|
2022-07-08 17:01:13 +00:00
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
nodeID, err := uuid.GenerateUUID()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
conf.NodeID = types.NodeID(nodeID)
|
|
|
|
|
|
|
|
if cb != nil {
|
|
|
|
cb(conf)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply config to copied fields because many tests only set the old
|
|
|
|
// values.
|
|
|
|
conf.ACLResolverSettings.ACLsEnabled = conf.ACLsEnabled
|
|
|
|
conf.ACLResolverSettings.NodeName = conf.NodeName
|
|
|
|
conf.ACLResolverSettings.Datacenter = conf.Datacenter
|
|
|
|
conf.ACLResolverSettings.EnterpriseMeta = *conf.AgentEnterpriseMeta()
|
|
|
|
|
|
|
|
deps := newDefaultDeps(t, conf)
|
2022-10-28 20:34:41 +00:00
|
|
|
externalGRPCServer := external.NewServer(deps.Logger, nil, deps.TLSConfigurator)
|
2022-09-29 03:27:11 +00:00
|
|
|
|
2022-07-13 15:33:48 +00:00
|
|
|
server, err := consul.NewServer(conf, deps, externalGRPCServer)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
t.Cleanup(func() {
|
|
|
|
require.NoError(t, server.Shutdown())
|
|
|
|
})
|
|
|
|
|
2022-09-29 03:27:11 +00:00
|
|
|
require.NoError(t, deps.TLSConfigurator.UpdateAutoTLSCert(connect.TestServerLeaf(t, conf.Datacenter, ca)))
|
|
|
|
deps.TLSConfigurator.UpdateAutoTLSPeeringServerName(connect.PeeringServerSAN(conf.Datacenter, connect.TestTrustDomain))
|
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
// Normally the gRPC server listener is created at the agent level and
|
|
|
|
// passed down into the Server creation.
|
2022-09-29 03:27:11 +00:00
|
|
|
grpcAddr := fmt.Sprintf("127.0.0.1:%d", conf.GRPCTLSPort)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
ln, err := net.Listen("tcp", grpcAddr)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
require.NoError(t, err)
|
2022-10-28 20:34:41 +00:00
|
|
|
ln = agentmiddleware.LabelledListener{Listener: ln, Protocol: agentmiddleware.ProtocolTLS}
|
2022-09-29 03:27:11 +00:00
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
go func() {
|
2022-07-13 15:33:48 +00:00
|
|
|
_ = externalGRPCServer.Serve(ln)
|
2022-07-08 17:01:13 +00:00
|
|
|
}()
|
2022-07-13 15:33:48 +00:00
|
|
|
t.Cleanup(externalGRPCServer.Stop)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
testrpc.WaitForLeader(t, server.RPC, conf.Datacenter)
|
2022-09-29 03:27:11 +00:00
|
|
|
testrpc.WaitForActiveCARoot(t, server.RPC, conf.Datacenter, nil)
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
|
|
|
|
return testingServer{
|
2022-07-08 17:01:13 +00:00
|
|
|
Server: server,
|
|
|
|
PublicGRPCAddr: grpcAddr,
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s testingServer) ClientConn(t *testing.T) *gogrpc.ClientConn {
|
|
|
|
t.Helper()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
rpcAddr := s.Server.Listener.Addr().String()
|
|
|
|
|
|
|
|
conn, err := gogrpc.DialContext(ctx, rpcAddr,
|
|
|
|
gogrpc.WithContextDialer(newServerDialer(rpcAddr)),
|
2022-11-07 16:34:30 +00:00
|
|
|
//nolint:staticcheck
|
2022-07-08 17:01:13 +00:00
|
|
|
gogrpc.WithInsecure(),
|
|
|
|
gogrpc.WithBlock())
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
t.Cleanup(func() { conn.Close() })
|
|
|
|
return conn
|
|
|
|
}
|
|
|
|
|
2022-07-08 17:01:13 +00:00
|
|
|
func newServerDialer(serverAddr string) func(context.Context, string) (net.Conn, error) {
|
|
|
|
return func(ctx context.Context, addr string) (net.Conn, error) {
|
|
|
|
d := net.Dialer{}
|
|
|
|
conn, err := d.DialContext(ctx, "tcp", serverAddr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = conn.Write([]byte{byte(pool.RPCGRPC)})
|
|
|
|
if err != nil {
|
|
|
|
conn.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
type testingServer struct {
|
2022-07-08 17:01:13 +00:00
|
|
|
Server *consul.Server
|
|
|
|
PublicGRPCAddr string
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(peering): remove duplication between this and agent/consul tests
|
|
|
|
func newDefaultDeps(t *testing.T, c *consul.Config) consul.Deps {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
logger := hclog.NewInterceptLogger(&hclog.LoggerOptions{
|
|
|
|
Name: c.NodeName,
|
|
|
|
Level: hclog.Debug,
|
|
|
|
Output: testutil.NewLogBuffer(t),
|
|
|
|
})
|
|
|
|
|
|
|
|
tls, err := tlsutil.NewConfigurator(c.TLSConfig, logger)
|
|
|
|
require.NoError(t, err, "failed to create tls configuration")
|
|
|
|
|
|
|
|
r := router.NewRouter(logger, c.Datacenter, fmt.Sprintf("%s.%s", c.NodeName, c.Datacenter), nil)
|
|
|
|
builder := resolver.NewServerResolverBuilder(resolver.Config{})
|
|
|
|
resolver.Register(builder)
|
|
|
|
|
|
|
|
connPool := &pool.ConnPool{
|
|
|
|
Server: false,
|
|
|
|
SrcAddr: c.RPCSrcAddr,
|
|
|
|
Logger: logger.StandardLogger(&hclog.StandardLoggerOptions{InferLevels: true}),
|
|
|
|
MaxTime: 2 * time.Minute,
|
|
|
|
MaxStreams: 4,
|
|
|
|
TLSConfigurator: tls,
|
|
|
|
Datacenter: c.Datacenter,
|
|
|
|
}
|
|
|
|
|
|
|
|
return consul.Deps{
|
proxycfg: server-local config entry data sources
This is the OSS portion of enterprise PR 2056.
This commit provides server-local implementations of the proxycfg.ConfigEntry
and proxycfg.ConfigEntryList interfaces, that source data from streaming events.
It makes use of the LocalMaterializer type introduced for peering replication,
adding the necessary support for authorization.
It also adds support for "wildcard" subscriptions (within a topic) to the event
publisher, as this is needed to fetch service-resolvers for all services when
configuring mesh gateways.
Currently, events will be emitted for just the ingress-gateway, service-resolver,
and mesh config entry types, as these are the only entries required by proxycfg
— the events will be emitted on topics named IngressGateway, ServiceResolver,
and MeshConfig topics respectively.
Though these events will only be consumed "locally" for now, they can also be
consumed via the gRPC endpoint (confirmed using grpcurl) so using them from
client agents should be a case of swapping the LocalMaterializer for an
RPCMaterializer.
2022-07-01 15:09:47 +00:00
|
|
|
EventPublisher: stream.NewEventPublisher(10 * time.Second),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
Logger: logger,
|
|
|
|
TLSConfigurator: tls,
|
|
|
|
Tokens: new(token.Store),
|
|
|
|
Router: r,
|
|
|
|
ConnPool: connPool,
|
|
|
|
GRPCConnPool: grpc.NewClientConnPool(grpc.ClientConnPoolConfig{
|
|
|
|
Servers: builder,
|
|
|
|
TLSWrapper: grpc.TLSWrapper(tls.OutgoingRPCWrapper()),
|
|
|
|
UseTLSForDC: tls.UseTLS,
|
|
|
|
DialingFromServer: true,
|
|
|
|
DialingFromDatacenter: c.Datacenter,
|
|
|
|
}),
|
|
|
|
LeaderForwarder: builder,
|
|
|
|
EnterpriseDeps: newDefaultDepsEnterprise(t, logger, c),
|
|
|
|
NewRequestRecorderFunc: middleware.NewRequestRecorder,
|
|
|
|
GetNetRPCInterceptorFunc: middleware.GetNetRPCInterceptor,
|
2022-09-09 14:02:01 +00:00
|
|
|
XDSStreamLimiter: limiter.NewSessionLimiter(),
|
peering: initial sync (#12842)
- Add endpoints related to peering: read, list, generate token, initiate peering
- Update node/service/check table indexing to account for peers
- Foundational changes for pushing service updates to a peer
- Plumb peer name through Health.ServiceNodes path
see: ENT-1765, ENT-1280, ENT-1283, ENT-1283, ENT-1756, ENT-1739, ENT-1750, ENT-1679,
ENT-1709, ENT-1704, ENT-1690, ENT-1689, ENT-1702, ENT-1701, ENT-1683, ENT-1663,
ENT-1650, ENT-1678, ENT-1628, ENT-1658, ENT-1640, ENT-1637, ENT-1597, ENT-1634,
ENT-1613, ENT-1616, ENT-1617, ENT-1591, ENT-1588, ENT-1596, ENT-1572, ENT-1555
Co-authored-by: R.B. Boyer <rb@hashicorp.com>
Co-authored-by: freddygv <freddy@hashicorp.com>
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
Co-authored-by: Evan Culver <eculver@hashicorp.com>
Co-authored-by: Nitya Dhanushkodi <nitya@hashicorp.com>
2022-04-21 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-31 15:54:40 +00:00
|
|
|
|
2022-07-12 23:18:05 +00:00
|
|
|
func upsertTestACLs(t *testing.T, store *state.Store) {
|
|
|
|
var (
|
|
|
|
testPolicyPeeringReadID = "43fed171-ad1d-4d3b-9df3-c99c1c835c37"
|
|
|
|
testPolicyPeeringWriteID = "cddb0821-e720-4411-bbdd-cc62ce417eac"
|
|
|
|
|
|
|
|
testPolicyServiceReadID = "0e054136-f5d3-4627-a7e6-198f1df923d3"
|
|
|
|
testPolicyServiceWriteID = "b55e03f4-c9dd-4210-8d24-f7ea8e2a1918"
|
|
|
|
)
|
|
|
|
policies := structs.ACLPolicies{
|
|
|
|
{
|
|
|
|
ID: testPolicyPeeringReadID,
|
|
|
|
Name: "peering-read",
|
|
|
|
Rules: `peering = "read"`,
|
|
|
|
Syntax: acl.SyntaxCurrent,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: testPolicyPeeringWriteID,
|
|
|
|
Name: "peering-write",
|
|
|
|
Rules: `peering = "write"`,
|
|
|
|
Syntax: acl.SyntaxCurrent,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: testPolicyServiceReadID,
|
|
|
|
Name: "service-read",
|
|
|
|
Rules: `service "api" { policy = "read" }`,
|
|
|
|
Syntax: acl.SyntaxCurrent,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: testPolicyServiceWriteID,
|
|
|
|
Name: "service-write",
|
|
|
|
Rules: `service "api" { policy = "write" }`,
|
|
|
|
Syntax: acl.SyntaxCurrent,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
require.NoError(t, store.ACLPolicyBatchSet(100, policies))
|
|
|
|
|
|
|
|
tokens := structs.ACLTokens{
|
|
|
|
&structs.ACLToken{
|
|
|
|
AccessorID: "22500c91-723c-4335-be8a-6697417dc35b",
|
|
|
|
SecretID: testTokenPeeringReadSecret,
|
|
|
|
Description: "peering read",
|
|
|
|
Policies: []structs.ACLTokenPolicyLink{
|
|
|
|
{
|
|
|
|
ID: testPolicyPeeringReadID,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.ACLToken{
|
|
|
|
AccessorID: "de924f93-cfec-404c-9a7e-c1c9b96b8cae",
|
|
|
|
SecretID: testTokenPeeringWriteSecret,
|
|
|
|
Description: "peering write",
|
|
|
|
Policies: []structs.ACLTokenPolicyLink{
|
|
|
|
{
|
|
|
|
ID: testPolicyPeeringWriteID,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.ACLToken{
|
|
|
|
AccessorID: "53c54f79-ffed-47d4-904e-e2e0e40c0a01",
|
|
|
|
SecretID: testTokenServiceReadSecret,
|
|
|
|
Description: "service read",
|
|
|
|
Policies: []structs.ACLTokenPolicyLink{
|
|
|
|
{
|
|
|
|
ID: testPolicyServiceReadID,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&structs.ACLToken{
|
|
|
|
AccessorID: "a100fa5f-db72-49f0-8f61-aa1f9f92f657",
|
|
|
|
SecretID: testTokenServiceWriteSecret,
|
|
|
|
Description: "service write",
|
|
|
|
Policies: []structs.ACLTokenPolicyLink{
|
|
|
|
{
|
|
|
|
ID: testPolicyServiceWriteID,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
require.NoError(t, store.ACLTokenBatchSet(101, tokens, state.ACLTokenSetOptions{}))
|
|
|
|
}
|
|
|
|
|
2022-10-24 16:48:02 +00:00
|
|
|
//nolint:unparam
|
2022-05-31 15:54:40 +00:00
|
|
|
func setupTestPeering(t *testing.T, store *state.Store, name string, index uint64) string {
|
2022-06-21 18:04:08 +00:00
|
|
|
t.Helper()
|
2022-08-01 14:33:18 +00:00
|
|
|
err := store.PeeringWrite(index, &pbpeering.PeeringWriteRequest{
|
|
|
|
Peering: &pbpeering.Peering{
|
|
|
|
ID: testUUID(t),
|
|
|
|
Name: name,
|
|
|
|
},
|
2022-05-31 15:54:40 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, p, err := store.PeeringRead(nil, state.Query{Value: name})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, p)
|
|
|
|
|
|
|
|
return p.ID
|
|
|
|
}
|
2022-06-21 18:04:08 +00:00
|
|
|
|
|
|
|
func testUUID(t *testing.T) string {
|
|
|
|
v, err := lib.GenerateUUID(nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
return v
|
|
|
|
}
|