mirror of https://github.com/status-im/consul.git
parent
543c6a30af
commit
fb2b696c0e
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/hashicorp/consul/tlsutil"
|
"github.com/hashicorp/consul/tlsutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const FORWARD_SERVICE_NAME_PREFIX = "hashicorp.consul."
|
const FORWARD_SERVICE_NAME_PREFIX = "/hashicorp.consul."
|
||||||
|
|
||||||
var (
|
var (
|
||||||
metricsLabels = []metrics.Label{{
|
metricsLabels = []metrics.Label{{
|
||||||
|
|
|
@ -160,7 +160,7 @@ func dial(c *GRPCConfig) (*grpc.ClientConn, error) {
|
||||||
func checkCertificates(c *GRPCConfig) error {
|
func checkCertificates(c *GRPCConfig) error {
|
||||||
if c.GRPCTLS {
|
if c.GRPCTLS {
|
||||||
certFileEmpty := c.CertFile == ""
|
certFileEmpty := c.CertFile == ""
|
||||||
keyFileEmpty := c.CertFile == ""
|
keyFileEmpty := c.KeyFile == ""
|
||||||
|
|
||||||
// both files need to be empty or both files need to be provided
|
// both files need to be empty or both files need to be provided
|
||||||
if certFileEmpty != keyFileEmpty {
|
if certFileEmpty != keyFileEmpty {
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (f *GRPCFlags) ClientFlags() *flag.FlagSet {
|
||||||
"127.0.0.1:8502. If you intend to communicate in TLS mode, you have to either "+
|
"127.0.0.1:8502. If you intend to communicate in TLS mode, you have to either "+
|
||||||
"include https:// schema in the address, use grpc-tls flag or set environment variable "+
|
"include https:// schema in the address, use grpc-tls flag or set environment variable "+
|
||||||
"CONSUL_GRPC_TLS = true, otherwise it uses plaintext mode")
|
"CONSUL_GRPC_TLS = true, otherwise it uses plaintext mode")
|
||||||
fs.Var(&f.caFile, "grpc-tls",
|
fs.Var(&f.grpcTLS, "grpc-tls",
|
||||||
"Set to true if you aim to communicate in TLS mode in the GRPC call.")
|
"Set to true if you aim to communicate in TLS mode in the GRPC call.")
|
||||||
fs.Var(&f.certFile, "client-cert",
|
fs.Var(&f.certFile, "client-cert",
|
||||||
"Path to a client cert file to use for TLS when 'verify_incoming' is enabled. This "+
|
"Path to a client cert file to use for TLS when 'verify_incoming' is enabled. This "+
|
||||||
|
|
|
@ -29,6 +29,7 @@ type Agent interface {
|
||||||
GetAgentName() string
|
GetAgentName() string
|
||||||
GetPartition() string
|
GetPartition() string
|
||||||
GetPod() testcontainers.Container
|
GetPod() testcontainers.Container
|
||||||
|
GetConsulContainer() testcontainers.Container
|
||||||
Logs(context.Context) (io.ReadCloser, error)
|
Logs(context.Context) (io.ReadCloser, error)
|
||||||
ClaimAdminPort() (int, error)
|
ClaimAdminPort() (int, error)
|
||||||
GetConfig() Config
|
GetConfig() Config
|
||||||
|
|
|
@ -77,6 +77,10 @@ func (c *consulContainerNode) GetPod() testcontainers.Container {
|
||||||
return c.pod
|
return c.pod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *consulContainerNode) GetConsulContainer() testcontainers.Container {
|
||||||
|
return c.container
|
||||||
|
}
|
||||||
|
|
||||||
func (c *consulContainerNode) Logs(context context.Context) (io.ReadCloser, error) {
|
func (c *consulContainerNode) Logs(context context.Context) (io.ReadCloser, error) {
|
||||||
return c.container.Logs(context)
|
return c.container.Logs(context)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
|
||||||
|
libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RESOURCE_FILE_PATH_ON_HOST = "../../../../../command/resource/testdata/demo.hcl"
|
||||||
|
RESOURCE_FILE_PATH_ON_CONTAINER = "/consul/data/demo.hcl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClientForwardToServer(t *testing.T) {
|
||||||
|
type operation struct {
|
||||||
|
action func(*testing.T, libcluster.Agent, string) (int, string)
|
||||||
|
includeToken bool
|
||||||
|
expectedCode int
|
||||||
|
expectedMsg string
|
||||||
|
}
|
||||||
|
type testCase struct {
|
||||||
|
description string
|
||||||
|
operations []operation
|
||||||
|
aclEnabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []testCase{
|
||||||
|
{
|
||||||
|
description: "The apply request should be forwarded to consul server agent",
|
||||||
|
operations: []operation{
|
||||||
|
{
|
||||||
|
action: applyResource,
|
||||||
|
includeToken: false,
|
||||||
|
expectedCode: 0,
|
||||||
|
expectedMsg: "demo.v2.Artist 'korn' created.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
aclEnabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "The apply request should be denied if missing token when ACL is enabled",
|
||||||
|
operations: []operation{
|
||||||
|
{
|
||||||
|
action: applyResource,
|
||||||
|
includeToken: false,
|
||||||
|
expectedCode: 1,
|
||||||
|
expectedMsg: "failed getting authorizer: ACL not found",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
aclEnabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "The apply request should be allowed if providing token when ACL is enabled",
|
||||||
|
operations: []operation{
|
||||||
|
{
|
||||||
|
action: applyResource,
|
||||||
|
includeToken: true,
|
||||||
|
expectedCode: 0,
|
||||||
|
expectedMsg: "demo.v2.Artist 'korn' created.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
aclEnabled: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var clientAgent libcluster.Agent
|
||||||
|
cluster, clientAgent := setupClusterAndClient(t, tc.aclEnabled)
|
||||||
|
defer terminate(t, cluster)
|
||||||
|
|
||||||
|
// perform actions and validate returned messages
|
||||||
|
for _, op := range tc.operations {
|
||||||
|
token := ""
|
||||||
|
if op.includeToken {
|
||||||
|
token = cluster.TokenBootstrap
|
||||||
|
}
|
||||||
|
code, res := op.action(t, clientAgent, token)
|
||||||
|
require.Equal(t, op.expectedCode, code)
|
||||||
|
require.Contains(t, res, op.expectedMsg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyResource(t *testing.T, clientAgent libcluster.Agent, token string) (int, string) {
|
||||||
|
ctx := context.Background()
|
||||||
|
c := clientAgent.GetConsulContainer()
|
||||||
|
err := c.CopyFileToContainer(ctx, RESOURCE_FILE_PATH_ON_HOST, RESOURCE_FILE_PATH_ON_CONTAINER, 700)
|
||||||
|
require.NoError(t, err)
|
||||||
|
args := []string{"/bin/consul", "resource", "apply", fmt.Sprintf("-f=%s", RESOURCE_FILE_PATH_ON_CONTAINER)}
|
||||||
|
if token != "" {
|
||||||
|
args = append(args, fmt.Sprintf("-token=%s", token))
|
||||||
|
}
|
||||||
|
code, reader, err := c.Exec(ctx, args)
|
||||||
|
require.NoError(t, err)
|
||||||
|
buf, err := io.ReadAll(reader)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return code, string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// passing two cmd args to set up the cluster
|
||||||
|
func setupClusterAndClient(t *testing.T, aclEnabled bool) (*libcluster.Cluster, libcluster.Agent) {
|
||||||
|
clusterConfig := &libtopology.ClusterConfig{
|
||||||
|
NumServers: 1,
|
||||||
|
NumClients: 1,
|
||||||
|
LogConsumer: &libtopology.TestLogConsumer{},
|
||||||
|
BuildOpts: &libcluster.BuildOptions{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
InjectAutoEncryption: true,
|
||||||
|
InjectGossipEncryption: true,
|
||||||
|
ACLEnabled: aclEnabled,
|
||||||
|
},
|
||||||
|
ApplyDefaultProxySettings: false,
|
||||||
|
}
|
||||||
|
cluster, _, _ := libtopology.NewCluster(t, clusterConfig)
|
||||||
|
|
||||||
|
return cluster, cluster.Clients()[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func terminate(t *testing.T, cluster *libcluster.Cluster) {
|
||||||
|
err := cluster.Terminate()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
Loading…
Reference in New Issue