2019-04-22 16:26:10 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
2020-09-15 14:01:26 +00:00
|
|
|
"context"
|
2019-04-22 16:26:10 +00:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
consulapi "github.com/hashicorp/consul/api"
|
2022-02-17 01:31:08 +00:00
|
|
|
goversion "github.com/hashicorp/go-version"
|
2019-04-22 16:26:10 +00:00
|
|
|
"github.com/hashicorp/vault/helper/testhelpers/docker"
|
|
|
|
)
|
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
type Config struct {
|
|
|
|
docker.ServiceHostPort
|
|
|
|
Token string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Config) APIConfig() *consulapi.Config {
|
|
|
|
apiConfig := consulapi.DefaultConfig()
|
|
|
|
apiConfig.Address = c.Address()
|
|
|
|
apiConfig.Token = c.Token
|
|
|
|
return apiConfig
|
|
|
|
}
|
|
|
|
|
2020-04-30 17:06:24 +00:00
|
|
|
// PrepareTestContainer creates a Consul docker container. If version is empty,
|
|
|
|
// the Consul version used will be given by the environment variable
|
|
|
|
// CONSUL_DOCKER_VERSION, or if that's empty, whatever we've hardcoded as the
|
|
|
|
// the latest Consul version.
|
2022-08-03 18:43:43 +00:00
|
|
|
func PrepareTestContainer(t *testing.T, version string, isEnterprise bool, doBootstrapSetup bool) (func(), *Config) {
|
2022-02-09 21:44:00 +00:00
|
|
|
t.Helper()
|
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
if retAddress := os.Getenv("CONSUL_HTTP_ADDR"); retAddress != "" {
|
|
|
|
shp, err := docker.NewServiceHostPortParse(retAddress)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return func() {}, &Config{ServiceHostPort: *shp, Token: os.Getenv("CONSUL_HTTP_TOKEN")}
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
config := `acl { enabled = true default_policy = "deny" }`
|
2020-04-30 17:06:24 +00:00
|
|
|
if version == "" {
|
|
|
|
consulVersion := os.Getenv("CONSUL_DOCKER_VERSION")
|
|
|
|
if consulVersion != "" {
|
|
|
|
version = consulVersion
|
|
|
|
} else {
|
2022-02-17 01:31:08 +00:00
|
|
|
version = "1.11.3" // Latest Consul version, update as new releases come out
|
2020-04-30 17:06:24 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-22 16:26:10 +00:00
|
|
|
if strings.HasPrefix(version, "1.3") {
|
|
|
|
config = `datacenter = "test" acl_default_policy = "deny" acl_datacenter = "test" acl_master_token = "test"`
|
|
|
|
}
|
|
|
|
|
2022-02-09 21:44:00 +00:00
|
|
|
name := "consul"
|
|
|
|
repo := "consul"
|
|
|
|
var envVars []string
|
|
|
|
// If running the enterprise container, set the appropriate values below.
|
|
|
|
if isEnterprise {
|
|
|
|
version += "-ent"
|
|
|
|
name = "consul-enterprise"
|
2022-11-02 17:33:17 +00:00
|
|
|
repo = "docker.mirror.hashicorp.services/hashicorp/consul-enterprise"
|
2022-02-09 21:44:00 +00:00
|
|
|
license, hasLicense := os.LookupEnv("CONSUL_LICENSE")
|
|
|
|
envVars = append(envVars, "CONSUL_LICENSE="+license)
|
|
|
|
|
|
|
|
if !hasLicense {
|
|
|
|
t.Fatalf("Failed to find enterprise license")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if dockerRepo, hasEnvRepo := os.LookupEnv("CONSUL_DOCKER_REPO"); hasEnvRepo {
|
|
|
|
repo = dockerRepo
|
2020-09-17 17:05:24 +00:00
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
runner, err := docker.NewServiceRunner(docker.RunOptions{
|
2022-02-09 21:44:00 +00:00
|
|
|
ContainerName: name,
|
2020-09-17 17:05:24 +00:00
|
|
|
ImageRepo: repo,
|
|
|
|
ImageTag: version,
|
2022-02-09 21:44:00 +00:00
|
|
|
Env: envVars,
|
2020-09-17 17:05:24 +00:00
|
|
|
Cmd: []string{"agent", "-dev", "-client", "0.0.0.0", "-hcl", config},
|
|
|
|
Ports: []string{"8500/tcp"},
|
|
|
|
AuthUsername: os.Getenv("CONSUL_DOCKER_USERNAME"),
|
|
|
|
AuthPassword: os.Getenv("CONSUL_DOCKER_PASSWORD"),
|
2020-09-15 14:01:26 +00:00
|
|
|
})
|
2019-04-22 16:26:10 +00:00
|
|
|
if err != nil {
|
2020-09-15 14:01:26 +00:00
|
|
|
t.Fatalf("Could not start docker Consul: %s", err)
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
svc, err := runner.StartService(context.Background(), func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
|
|
|
|
shp := docker.NewServiceHostPort(host, port)
|
|
|
|
apiConfig := consulapi.DefaultNonPooledConfig()
|
|
|
|
apiConfig.Address = shp.Address()
|
|
|
|
consul, err := consulapi.NewClient(apiConfig)
|
2019-04-22 16:26:10 +00:00
|
|
|
if err != nil {
|
2020-09-15 14:01:26 +00:00
|
|
|
return nil, err
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
// Make sure Consul is up
|
|
|
|
if _, err = consul.Status().Leader(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-22 16:26:10 +00:00
|
|
|
// For version of Consul < 1.4
|
|
|
|
if strings.HasPrefix(version, "1.3") {
|
2020-09-15 14:01:26 +00:00
|
|
|
consulToken := "test"
|
2019-04-22 16:26:10 +00:00
|
|
|
_, err = consul.KV().Put(&consulapi.KVPair{
|
|
|
|
Key: "setuptest",
|
|
|
|
Value: []byte("setuptest"),
|
|
|
|
}, &consulapi.WriteOptions{
|
|
|
|
Token: consulToken,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2020-09-15 14:01:26 +00:00
|
|
|
return nil, err
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
2020-09-15 14:01:26 +00:00
|
|
|
return &Config{
|
|
|
|
ServiceHostPort: *shp,
|
|
|
|
Token: consulToken,
|
|
|
|
}, nil
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// New default behavior
|
2022-04-20 22:16:15 +00:00
|
|
|
var consulToken string
|
2022-08-03 18:43:43 +00:00
|
|
|
if doBootstrapSetup {
|
2022-04-20 22:16:15 +00:00
|
|
|
aclbootstrap, _, err := consul.ACL().Bootstrap()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
consulToken = aclbootstrap.SecretID
|
|
|
|
policy := &consulapi.ACLPolicy{
|
|
|
|
Name: "test",
|
|
|
|
Description: "test",
|
|
|
|
Rules: `node_prefix "" {
|
|
|
|
policy = "write"
|
2022-02-09 21:44:00 +00:00
|
|
|
}
|
2019-04-22 16:26:10 +00:00
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
service_prefix "" {
|
|
|
|
policy = "read"
|
|
|
|
}`,
|
2022-02-09 21:44:00 +00:00
|
|
|
}
|
2022-04-20 22:16:15 +00:00
|
|
|
q := &consulapi.WriteOptions{
|
|
|
|
Token: consulToken,
|
|
|
|
}
|
|
|
|
_, _, err = consul.ACL().PolicyCreate(policy, q)
|
2022-02-09 21:44:00 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-17 01:31:08 +00:00
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
// Create a Consul role that contains the test policy, for Consul 1.5 and newer
|
|
|
|
currVersion, _ := goversion.NewVersion(version)
|
|
|
|
roleVersion, _ := goversion.NewVersion("1.5")
|
|
|
|
if currVersion.GreaterThanOrEqual(roleVersion) {
|
2022-05-10 01:07:35 +00:00
|
|
|
ACLList := []*consulapi.ACLTokenRoleLink{{Name: "test"}}
|
2022-02-17 01:31:08 +00:00
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
role := &consulapi.ACLRole{
|
|
|
|
Name: "role-test",
|
|
|
|
Description: "consul roles test",
|
|
|
|
Policies: ACLList,
|
2022-02-17 01:31:08 +00:00
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
_, _, err = consul.ACL().RoleCreate(role, q)
|
2022-02-17 01:31:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
// Configure a namespace and parition if testing enterprise Consul
|
|
|
|
if isEnterprise {
|
|
|
|
// Namespaces require Consul 1.7 or newer
|
|
|
|
namespaceVersion, _ := goversion.NewVersion("1.7")
|
|
|
|
if currVersion.GreaterThanOrEqual(namespaceVersion) {
|
|
|
|
namespace := &consulapi.Namespace{
|
|
|
|
Name: "ns1",
|
|
|
|
Description: "ns1 test",
|
|
|
|
}
|
|
|
|
|
|
|
|
_, _, err = consul.Namespaces().Create(namespace, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPolicy := &consulapi.ACLPolicy{
|
|
|
|
Name: "ns-test",
|
|
|
|
Description: "namespace test",
|
|
|
|
Namespace: "ns1",
|
|
|
|
Rules: `service_prefix "" {
|
|
|
|
policy = "read"
|
|
|
|
}`,
|
|
|
|
}
|
|
|
|
_, _, err = consul.ACL().PolicyCreate(nsPolicy, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-17 01:31:08 +00:00
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
|
2022-04-20 22:16:15 +00:00
|
|
|
// Partitions require Consul 1.11 or newer
|
|
|
|
partitionVersion, _ := goversion.NewVersion("1.11")
|
|
|
|
if currVersion.GreaterThanOrEqual(partitionVersion) {
|
|
|
|
partition := &consulapi.Partition{
|
|
|
|
Name: "part1",
|
|
|
|
Description: "part1 test",
|
|
|
|
}
|
|
|
|
|
|
|
|
_, _, err = consul.Partitions().Create(ctx, partition, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
partPolicy := &consulapi.ACLPolicy{
|
|
|
|
Name: "part-test",
|
|
|
|
Description: "partition test",
|
|
|
|
Partition: "part1",
|
|
|
|
Rules: `service_prefix "" {
|
2022-02-09 21:44:00 +00:00
|
|
|
policy = "read"
|
|
|
|
}`,
|
2022-04-20 22:16:15 +00:00
|
|
|
}
|
|
|
|
_, _, err = consul.ACL().PolicyCreate(partPolicy, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-17 01:31:08 +00:00
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
return &Config{
|
|
|
|
ServiceHostPort: *shp,
|
|
|
|
Token: consulToken,
|
|
|
|
}, nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not start docker Consul: %s", err)
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|
2022-02-09 21:44:00 +00:00
|
|
|
|
2020-09-15 14:01:26 +00:00
|
|
|
return svc.Cleanup, svc.Config.(*Config)
|
2019-04-22 16:26:10 +00:00
|
|
|
}
|