Create IPv6 and dual stack enos tests (#5212)

Co-authored-by: Danielle Miu <29378233+DanielleMiu@users.noreply.github.com>
Co-authored-by: Damian Debkowski <damian.debkowski@hashicorp.com>
This commit is contained in:
authored and GitHub committed 2025-01-21 07:37:04 -08:00
1 parent 34d13a0aae
commit dd9c7b9d60
59 files changed
+1773 -301

No files matched your search

+44 -13
View File
@@ -203,19 +203,30 @@ func AddHostToHostSetCli(t testing.TB, ctx context.Context, hostSetId string, ho
// CreateAwsHostCatalogCli uses the cli to create a new AWS dynamic host catalog.
// Returns the id of the new host catalog.
func CreateAwsHostCatalogCli(t testing.TB, ctx context.Context, projectId, accessKeyId, secretAccessKey, region string) (string, error) {
func CreateAwsHostCatalogCli(t testing.TB, ctx context.Context, projectId, accessKeyId, secretAccessKey, region string, dualStack bool) (string, error) {
name, err := base62.Random(16)
if err != nil {
return "", err
}
output := e2e.RunCommand(ctx, "boundary",
opts := []e2e.Option{
e2e.WithArgs(
"host-catalogs", "create", "plugin",
"-scope-id", projectId,
"-plugin-name", "aws",
"-attr", "disable_credential_rotation=true",
"-attr", fmt.Sprintf("region=%s", region),
),
}
if dualStack {
opts = append(opts,
e2e.WithArgs(
"-attr", fmt.Sprintf("dual_stack=%t", dualStack),
),
)
}
opts = append(opts,
e2e.WithArgs(
"-secret", "access_key_id=env://E2E_AWS_ACCESS_KEY_ID",
"-secret", "secret_access_key=env://E2E_AWS_SECRET_ACCESS_KEY",
"-name", fmt.Sprintf("e2e Host Catalog %s", name),
@@ -225,6 +236,7 @@ func CreateAwsHostCatalogCli(t testing.TB, ctx context.Context, projectId, acces
e2e.WithEnv("E2E_AWS_ACCESS_KEY_ID", accessKeyId),
e2e.WithEnv("E2E_AWS_SECRET_ACCESS_KEY", secretAccessKey),
)
output := e2e.RunCommand(ctx, "boundary", opts...)
if output.Err != nil {
return "", fmt.Errorf("%w: %s", output.Err, string(output.Stderr))
}
@@ -242,22 +254,41 @@ func CreateAwsHostCatalogCli(t testing.TB, ctx context.Context, projectId, acces
// CreatePluginHostSetCli uses the cli to create a new host set from a dynamic host catalog.
// Returns the id of the new host set.
func CreatePluginHostSetCli(t testing.TB, ctx context.Context, hostCatalogId string, filter string) (string, error) {
func CreatePluginHostSetCli(t testing.TB, ctx context.Context, hostCatalogId string, filter string, ipVersion string) (string, error) {
name, err := base62.Random(16)
if err != nil {
return "", err
}
output := e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"host-sets", "create", "plugin",
"-host-catalog-id", hostCatalogId,
"-attr", "filters="+filter,
"-name", fmt.Sprintf("e2e Host Set %s", name),
"-description", "e2e",
"-format", "json",
),
)
var output *e2e.CommandResult
switch ipVersion {
case "4":
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"host-sets", "create", "plugin",
"-host-catalog-id", hostCatalogId,
"-attr", "filters="+filter,
"-name", fmt.Sprintf("e2e Host Set %s", name),
"-description", "e2e",
"-format", "json",
),
)
case "6", "dual":
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"host-sets", "create", "plugin",
"-host-catalog-id", hostCatalogId,
"-preferred-endpoint", "cidr:::/0",
"-attr", "filters="+filter,
"-name", fmt.Sprintf("e2e Host Set %s", name),
"-description", "e2e",
"-format", "json",
),
)
default:
return "", fmt.Errorf("unknown ip version: %q", ipVersion)
}
if output.Err != nil {
return "", fmt.Errorf("%w: %s", output.Err, string(output.Stderr))
}
@@ -38,11 +38,11 @@ func TestCliCreateAwsDynamicHostCatalogWithEmptyHostSet(t *testing.T) {
})
projectId, err := boundary.CreateProjectCli(t, ctx, orgId)
require.NoError(t, err)
hostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion)
hostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion, c.IpVersion != "4")
require.NoError(t, err)
// Set up a host set
hostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, "tag:empty_test=true")
hostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, "tag:empty_test=true", c.IpVersion)
require.NoError(t, err)
// Check that there are no hosts in the host set
@@ -8,7 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"regexp"
"testing"
"time"
@@ -17,12 +17,17 @@ import (
"github.com/hashicorp/boundary/api/hosts"
"github.com/hashicorp/boundary/api/hostsets"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/api/sessions"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/testing/internal/e2e"
"github.com/hashicorp/boundary/testing/internal/e2e/boundary"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var sessionRegex = regexp.MustCompile("Session ID:\\s+(.+)(?:$|\n)")
// TestCliCreateAwsDynamicHostCatalogWithHostSet uses the boundary cli to create a host catalog with the AWS
// plugin. The test sets up an AWS dynamic host catalog, creates some host sets, sets up a target to
// one of the host sets, and attempts to connect to the target.
@@ -43,11 +48,11 @@ func TestCliCreateAwsDynamicHostCatalogWithHostSet(t *testing.T) {
})
projectId, err := boundary.CreateProjectCli(t, ctx, orgId)
require.NoError(t, err)
hostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion)
hostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion, c.IpVersion != "4")
require.NoError(t, err)
// Set up a host set
hostSetId1, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.AwsHostSetFilter1)
hostSetId1, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.AwsHostSetFilter1, c.IpVersion)
require.NoError(t, err)
var targetIps1 []string
err = json.Unmarshal([]byte(c.AwsHostSetIps1), &targetIps1)
@@ -56,7 +61,7 @@ func TestCliCreateAwsDynamicHostCatalogWithHostSet(t *testing.T) {
boundary.WaitForNumberOfHostsInHostSetCli(t, ctx, hostSetId1, expectedHostSetCount1)
// Set up another host set
hostSetId2, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.AwsHostSetFilter2)
hostSetId2, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.AwsHostSetFilter2, c.IpVersion)
require.NoError(t, err)
var targetIps2 []string
err = json.Unmarshal([]byte(c.AwsHostSetIps2), &targetIps2)
@@ -112,41 +117,63 @@ func TestCliCreateAwsDynamicHostCatalogWithHostSet(t *testing.T) {
assert.Equal(t, expectedHostCatalogCount, actualHostCatalogCount, "Numbers of hosts in host catalog did not match expected amount")
// Create target
targetId, err := boundary.CreateTargetCli(t, ctx, projectId, c.TargetPort)
var targetId string
if c.IpVersion == "4" {
targetId, err = boundary.CreateTargetCli(t, ctx, projectId, c.TargetPort)
} else {
targetId, err = boundary.CreateTargetCli(t, ctx, projectId, c.TargetPort,
target.WithIngressWorkerFilter(fmt.Sprintf(`"%s" in "/tags/type"`, c.WorkerTagCollocated)),
)
}
require.NoError(t, err)
err = boundary.AddHostSourceToTargetCli(t, ctx, targetId, hostSetId1)
require.NoError(t, err)
// Connect to target
ctxCancel, cancel := context.WithCancel(context.Background())
go func() {
e2e.RunCommand(ctxCancel, "boundary",
e2e.WithArgs(
"connect",
"-target-id", targetId,
"-exec", "/usr/bin/ssh", "--",
"-l", c.TargetSshUser,
"-i", c.TargetSshKeyPath,
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
"-o", "IdentitiesOnly=yes", // forces the use of the provided key
"-p", "{{boundary.port}}", // this is provided by boundary
"{{boundary.ip}}",
"hostname -i; sleep 60",
),
)
}()
t.Cleanup(cancel)
s := boundary.WaitForSessionCli(t, ctx, projectId)
boundary.WaitForSessionStatusCli(t, ctx, s.Id, session.StatusActive.String())
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"connect",
"-target-id", targetId,
"-exec", "/usr/bin/ssh", "--",
"-l", c.TargetSshUser,
"-i", c.TargetSshKeyPath,
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
"-o", "IdentitiesOnly=yes", // forces the use of the provided key
"-p", "{{boundary.port}}", // this is provided by boundary
"{{boundary.ip}}",
"hostname", "-i",
),
e2e.WithArgs("sessions", "read", "-id", s.Id, "-format", "json"),
)
require.NoError(t, output.Err, string(output.Stderr))
var sessionReadResult sessions.SessionReadResult
err = json.Unmarshal(output.Stdout, &sessionReadResult)
require.NoError(t, err)
s = sessionReadResult.Item
parts := strings.Fields(string(output.Stdout))
hostIp := parts[len(parts)-1]
t.Log("Successfully connected to the target")
// Check if connected host exists in the host set
hostIpInList := false
for _, v := range targetIps1 {
if v == hostIp {
hostIpInList = true
}
require.Greater(t, len(s.Connections), 0)
var hostIp string
switch c.IpVersion {
case "4":
hostIp = s.Connections[0].EndpointTcpAddress
case "6", "dual":
hostIp = fmt.Sprintf("[%s]", s.Connections[0].EndpointTcpAddress)
default:
require.Fail(t, "unknown ip version", c.IpVersion)
}
require.True(t, hostIpInList, fmt.Sprintf("Connected host (%s) is not in expected list (%s)", hostIp, targetIps1))
require.Contains(t, targetIps1, hostIp, fmt.Sprintf("Connected host (%s) is not in expected list (%s)", hostIp, targetIps1))
}
// TestApiCreateAwsDynamicHostCatalog uses the Go api to create a host catalog with the AWS plugin.
+17 -15
View File
@@ -6,21 +6,23 @@ package aws_test
import "github.com/kelseyhightower/envconfig"
type config struct {
AwsAccessKeyId string `envconfig:"E2E_AWS_ACCESS_KEY_ID" required:"true"`
AwsBucketName string `envconfig:"E2E_AWS_BUCKET_NAME" required:"true"`
AwsSecretAccessKey string `envconfig:"E2E_AWS_SECRET_ACCESS_KEY" required:"true"`
AwsHostSetFilter1 string `envconfig:"E2E_AWS_HOST_SET_FILTER" required:"true"` // e.g. "tag:testtag=true"
AwsHostSetIps1 string `envconfig:"E2E_AWS_HOST_SET_IPS" required:"true"` // e.g. "[\"1.2.3.4\", \"2.3.4.5\"]"
AwsHostSetFilter2 string `envconfig:"E2E_AWS_HOST_SET_FILTER2" required:"true"` // e.g. "tag:testtagtwo=test"
AwsHostSetIps2 string `envconfig:"E2E_AWS_HOST_SET_IPS2" required:"true"` // e.g. "[\"1.2.3.4\"]"
AwsRegion string `envconfig:"E2E_AWS_REGION" required:"true"` // e.g. "us-east-1"
TargetSshKeyPath string `envconfig:"E2E_SSH_KEY_PATH" required:"true"` // e.g. "/Users/username/key.pem"
TargetSshUser string `envconfig:"E2E_SSH_USER" required:"true"` // e.g. "ubuntu"
TargetPort string `envconfig:"E2E_TARGET_PORT" required:"true"` // e.g. "22"
TargetAddress string `envconfig:"E2E_TARGET_ADDRESS" required:"true"` // e.g. "192.168.0.1"
WorkerTagEgress string `envconfig:"E2E_WORKER_TAG_EGRESS" required:"true"` // e.g. "egress"
WorkerAddress string `envconfig:"E2E_WORKER_ADDRESS" required:"true"` // e.g. ""192.168.0.2"
MaxPageSize int `envconfig:"E2E_MAX_PAGE_SIZE" default:"1000"`
AwsAccessKeyId string `envconfig:"E2E_AWS_ACCESS_KEY_ID" required:"true"`
AwsBucketName string `envconfig:"E2E_AWS_BUCKET_NAME" required:"true"`
AwsSecretAccessKey string `envconfig:"E2E_AWS_SECRET_ACCESS_KEY" required:"true"`
AwsHostSetFilter1 string `envconfig:"E2E_AWS_HOST_SET_FILTER" required:"true"` // e.g. "tag:testtag=true"
AwsHostSetIps1 string `envconfig:"E2E_AWS_HOST_SET_IPS" required:"true"` // e.g. "[\"1.2.3.4\", \"2.3.4.5\"]"
AwsHostSetFilter2 string `envconfig:"E2E_AWS_HOST_SET_FILTER2" required:"true"` // e.g. "tag:testtagtwo=test"
AwsHostSetIps2 string `envconfig:"E2E_AWS_HOST_SET_IPS2" required:"true"` // e.g. "[\"1.2.3.4\"]"
AwsRegion string `envconfig:"E2E_AWS_REGION" required:"true"` // e.g. "us-east-1"
TargetSshKeyPath string `envconfig:"E2E_SSH_KEY_PATH" required:"true"` // e.g. "/Users/username/key.pem"
TargetSshUser string `envconfig:"E2E_SSH_USER" required:"true"` // e.g. "ubuntu"
TargetPort string `envconfig:"E2E_TARGET_PORT" required:"true"` // e.g. "22"
TargetAddress string `envconfig:"E2E_TARGET_ADDRESS" required:"true"` // e.g. "192.168.0.1"
WorkerTagIsolated string `envconfig:"E2E_WORKER_TAG_ISOLATED" required:"true"` // e.g. "isolated"
WorkerTagCollocated string `envconfig:"E2E_WORKER_TAG_COLLOCATED" required:"true"` // e.g. "collocated"
WorkerAddress string `envconfig:"E2E_WORKER_ADDRESS" required:"true"` // e.g. "192.168.0.2"
MaxPageSize int `envconfig:"E2E_MAX_PAGE_SIZE" default:"1000"`
IpVersion string `envconfig:"E2E_IP_VERSION" default:"4"` // should always be 4, 6, or dual
}
func loadTestConfig() (*config, error) {
@@ -74,7 +74,7 @@ func TestCliWorker(t *testing.T) {
e2e.WithArgs(
"targets", "update", "tcp",
"-id", targetId,
"-egress-worker-filter", fmt.Sprintf(`"%s" in "/tags/type"`, c.WorkerTagEgress),
"-egress-worker-filter", fmt.Sprintf(`"%s" in "/tags/type"`, c.WorkerTagIsolated),
"-format", "json",
),
)
@@ -241,9 +241,9 @@ func populateBoundaryDatabase(t testing.TB, ctx context.Context, c *config, te T
require.NoError(t, err)
// Create AWS dynamic host catalog
awsHostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion)
awsHostCatalogId, err := boundary.CreateAwsHostCatalogCli(t, ctx, projectId, c.AwsAccessKeyId, c.AwsSecretAccessKey, c.AwsRegion, false)
require.NoError(t, err)
awsHostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, awsHostCatalogId, c.AwsHostSetFilter)
awsHostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, awsHostCatalogId, c.AwsHostSetFilter, "4")
require.NoError(t, err)
boundary.WaitForHostsInHostSetCli(t, ctx, awsHostSetId)
@@ -43,7 +43,7 @@ func TestCliCreateGcpDynamicHostCatalogWithEmptyHostSet(t *testing.T) {
require.NoError(t, err)
// Set up a host set
hostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, "labels.empty_test=true")
hostSetId, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, "labels.empty_test=true", "4")
require.NoError(t, err)
// Check that there are no hosts in the host set
@@ -48,12 +48,12 @@ func TestCliCreateGcpDynamicHostCatalogWithHostSet(t *testing.T) {
require.NoError(t, err)
// Set up a host set
hostSetId1, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.GcpHostSetFilter1)
hostSetId1, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.GcpHostSetFilter1, "4")
require.NoError(t, err)
boundary.WaitForNumberOfHostsInHostSetCli(t, ctx, hostSetId1, 1)
// Set up another host set
hostSetId2, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.GcpHostSetFilter2)
hostSetId2, err := boundary.CreatePluginHostSetCli(t, ctx, hostCatalogId, c.GcpHostSetFilter2, "4")
require.NoError(t, err)
boundary.WaitForNumberOfHostsInHostSetCli(t, ctx, hostSetId2, 1)