You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
consul/agent/proxycfg-glue/peered_upstreams_test.go

139 lines
4.4 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
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"
)
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(),
}))
}
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)
registerService(t, index, "peer-1", "web", nodeName, store)
eventCh := make(chan proxycfg.UpdateEvent)
dataSource := ServerPeeredUpstreams(ServerDataSourceDeps{
GetStore: func() Store { return store },
ACLResolver: newStaticResolver(acl.ManageAll()),
})
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) {
registerService(t, index+1, "peer-2", "db", nodeName, store)
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)
})
}
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\"")
})
}
func enableVirtualIPs(t *testing.T, store *state.Store) {
t.Helper()
require.NoError(t, store.SystemMetadataSet(0, &structs.SystemMetadataEntry{
Key: structs.SystemMetadataVirtualIPsEnabled,
Value: "true",
}))
}