2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2022-07-21 12:38:28 +00:00
|
|
|
package proxycfgglue
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"github.com/hashicorp/consul/acl"
|
|
|
|
"github.com/hashicorp/consul/agent/consul/state"
|
|
|
|
"github.com/hashicorp/consul/agent/proxycfg"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
|
|
"github.com/hashicorp/consul/sdk/testutil"
|
|
|
|
)
|
|
|
|
|
2022-07-28 19:01:52 +00:00
|
|
|
func registerService(t *testing.T, index uint64, peerName, serviceName, nodeName string, store *state.Store) {
|
|
|
|
require.NoError(t, store.EnsureRegistration(index, &structs.RegisterRequest{
|
|
|
|
Node: nodeName,
|
|
|
|
Service: &structs.NodeService{Service: serviceName, ID: serviceName},
|
|
|
|
PeerName: peerName,
|
|
|
|
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
|
|
|
}))
|
|
|
|
|
|
|
|
require.NoError(t, store.EnsureRegistration(index, &structs.RegisterRequest{
|
|
|
|
Node: nodeName,
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: fmt.Sprintf("%s-proxy", serviceName),
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
DestinationServiceName: serviceName,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
PeerName: peerName,
|
|
|
|
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2022-07-21 12:38:28 +00:00
|
|
|
func TestServerPeeredUpstreams(t *testing.T) {
|
|
|
|
const (
|
|
|
|
index uint64 = 123
|
|
|
|
nodeName = "node-1"
|
|
|
|
)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
store := state.NewStateStore(nil)
|
|
|
|
enableVirtualIPs(t, store)
|
|
|
|
|
2022-07-28 19:01:52 +00:00
|
|
|
registerService(t, index, "peer-1", "web", nodeName, store)
|
2022-07-21 12:38:28 +00:00
|
|
|
|
|
|
|
eventCh := make(chan proxycfg.UpdateEvent)
|
|
|
|
dataSource := ServerPeeredUpstreams(ServerDataSourceDeps{
|
2022-07-28 19:01:52 +00:00
|
|
|
GetStore: func() Store { return store },
|
|
|
|
ACLResolver: newStaticResolver(acl.ManageAll()),
|
2022-07-21 12:38:28 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, dataSource.Notify(ctx, &structs.PartitionSpecificRequest{EnterpriseMeta: *acl.DefaultEnterpriseMeta()}, "", eventCh))
|
|
|
|
|
|
|
|
testutil.RunStep(t, "initial state", func(t *testing.T) {
|
|
|
|
result := getEventResult[*structs.IndexedPeeredServiceList](t, eventCh)
|
|
|
|
require.Len(t, result.Services, 1)
|
|
|
|
require.Equal(t, "peer-1", result.Services[0].Peer)
|
|
|
|
require.Equal(t, "web", result.Services[0].ServiceName.Name)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "register another service", func(t *testing.T) {
|
2022-07-28 19:01:52 +00:00
|
|
|
registerService(t, index+1, "peer-2", "db", nodeName, store)
|
2022-07-21 12:38:28 +00:00
|
|
|
|
|
|
|
result := getEventResult[*structs.IndexedPeeredServiceList](t, eventCh)
|
|
|
|
require.Len(t, result.Services, 2)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "deregister service", func(t *testing.T) {
|
|
|
|
require.NoError(t, store.DeleteService(index+2, nodeName, "web", acl.DefaultEnterpriseMeta(), "peer-1"))
|
|
|
|
|
|
|
|
result := getEventResult[*structs.IndexedPeeredServiceList](t, eventCh)
|
|
|
|
require.Len(t, result.Services, 1)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-07-28 19:01:52 +00:00
|
|
|
func TestServerPeeredUpstreams_ACLEnforcement(t *testing.T) {
|
|
|
|
const (
|
|
|
|
index uint64 = 123
|
|
|
|
nodeName = "node-1"
|
|
|
|
)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
store := state.NewStateStore(nil)
|
|
|
|
enableVirtualIPs(t, store)
|
|
|
|
|
|
|
|
registerService(t, index, "peer-1", "web", nodeName, store)
|
|
|
|
|
|
|
|
testutil.RunStep(t, "read web", func(t *testing.T) {
|
|
|
|
authz := policyAuthorizer(t, `
|
|
|
|
service "web" { policy = "write" }`)
|
|
|
|
|
|
|
|
eventCh := make(chan proxycfg.UpdateEvent)
|
|
|
|
dataSource := ServerPeeredUpstreams(ServerDataSourceDeps{
|
|
|
|
GetStore: func() Store { return store },
|
|
|
|
ACLResolver: newStaticResolver(authz),
|
|
|
|
})
|
|
|
|
require.NoError(t, dataSource.Notify(ctx, &structs.PartitionSpecificRequest{EnterpriseMeta: *acl.DefaultEnterpriseMeta()}, "", eventCh))
|
|
|
|
|
|
|
|
result := getEventResult[*structs.IndexedPeeredServiceList](t, eventCh)
|
|
|
|
require.Len(t, result.Services, 1)
|
|
|
|
require.Equal(t, "peer-1", result.Services[0].Peer)
|
|
|
|
require.Equal(t, "web", result.Services[0].ServiceName.Name)
|
|
|
|
})
|
|
|
|
|
|
|
|
testutil.RunStep(t, "can't read web", func(t *testing.T) {
|
|
|
|
authz := policyAuthorizer(t, ``)
|
|
|
|
|
|
|
|
eventCh := make(chan proxycfg.UpdateEvent)
|
|
|
|
dataSource := ServerPeeredUpstreams(ServerDataSourceDeps{
|
|
|
|
GetStore: func() Store { return store },
|
|
|
|
ACLResolver: newStaticResolver(authz),
|
|
|
|
})
|
|
|
|
require.NoError(t, dataSource.Notify(ctx, &structs.PartitionSpecificRequest{EnterpriseMeta: *acl.DefaultEnterpriseMeta()}, "", eventCh))
|
|
|
|
|
|
|
|
err := getEventError(t, eventCh)
|
|
|
|
require.Contains(t, err.Error(), "lacks permission 'service:write' on \"any service\"")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-07-21 12:38:28 +00:00
|
|
|
func enableVirtualIPs(t *testing.T, store *state.Store) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
require.NoError(t, store.SystemMetadataSet(0, &structs.SystemMetadataEntry{
|
|
|
|
Key: structs.SystemMetadataVirtualIPsEnabled,
|
|
|
|
Value: "true",
|
|
|
|
}))
|
|
|
|
}
|