From 036a71fc93816c0934beba31c11d71313e38ee40 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 31 Jan 2023 14:29:39 -0500 Subject: [PATCH] test(e2e): Add test for updated `boundary authenticate` command (#2848) --- go.mod | 1 + testing/internal/e2e/boundary/account.go | 4 +- testing/internal/e2e/boundary/authenticate.go | 8 +-- testing/internal/e2e/boundary/boundary.go | 5 +- testing/internal/e2e/boundary/env.go | 6 +-- testing/internal/e2e/helpers.go | 2 + .../tests/static/authenticate_primary_test.go | 54 +++++++++++++++++++ 7 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 testing/internal/e2e/tests/static/authenticate_primary_test.go diff --git a/go.mod b/go.mod index abb7788e93..6dd186b564 100644 --- a/go.mod +++ b/go.mod @@ -92,6 +92,7 @@ require github.com/hashicorp/go-dbw v0.0.0-20220910135738-ed4505749995 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/cenkalti/backoff/v4 v4.1.3 + github.com/creack/pty v1.1.11 github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20221122211539-47c893099f13 github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/nodeenrollment v0.1.18 diff --git a/testing/internal/e2e/boundary/account.go b/testing/internal/e2e/boundary/account.go index 2855955afe..0d374c0829 100644 --- a/testing/internal/e2e/boundary/account.go +++ b/testing/internal/e2e/boundary/account.go @@ -15,7 +15,7 @@ import ( // CreateNewAccountApi creates a new account using the Go api. // Returns the id of the new account as well as the password that was generated func CreateNewAccountApi(t testing.TB, ctx context.Context, client *api.Client, loginName string) (accountId string, password string) { - c, err := loadConfig() + c, err := LoadConfig() require.NoError(t, err) aClient := accounts.NewClient(client) @@ -35,7 +35,7 @@ func CreateNewAccountApi(t testing.TB, ctx context.Context, client *api.Client, // CreateNewAccountCli creates a new account using the cli. // Returns the id of the new account as well as the password that was generated func CreateNewAccountCli(t testing.TB, ctx context.Context, loginName string) (string, string) { - c, err := loadConfig() + c, err := LoadConfig() require.NoError(t, err) password, err := base62.Random(16) diff --git a/testing/internal/e2e/boundary/authenticate.go b/testing/internal/e2e/boundary/authenticate.go index 532aa474a5..22763418c3 100644 --- a/testing/internal/e2e/boundary/authenticate.go +++ b/testing/internal/e2e/boundary/authenticate.go @@ -15,7 +15,7 @@ import ( // NewApiClient creates a new Api client for the specified Boundary instance and // attempts to authenticate it. Returns the client. func NewApiClient() (*api.Client, error) { - c, err := loadConfig() + c, err := LoadConfig() if err != nil { return nil, err } @@ -43,7 +43,7 @@ func NewApiClient() (*api.Client, error) { // AuthenticateAdminCli uses the cli to authenticate the specified Boundary instance as an admin func AuthenticateAdminCli(t testing.TB, ctx context.Context) { - c, err := loadConfig() + c, err := LoadConfig() require.NoError(t, err) AuthenticateCli(t, ctx, c.AdminLoginName, c.AdminLoginPassword) @@ -51,7 +51,7 @@ func AuthenticateAdminCli(t testing.TB, ctx context.Context) { // AuthenticateCli uses the cli to authenticate the specified Boundary instance func AuthenticateCli(t testing.TB, ctx context.Context, loginName string, password string) { - c, err := loadConfig() + c, err := LoadConfig() require.NoError(t, err) output := e2e.RunCommand(ctx, "boundary", @@ -70,7 +70,7 @@ func AuthenticateCli(t testing.TB, ctx context.Context, loginName string, passwo // GetAuthenticationTokenCli uses the cli to get an auth token that can be used in subsequent // commands func GetAuthenticationTokenCli(t testing.TB, ctx context.Context, loginName string, password string) string { - c, err := loadConfig() + c, err := LoadConfig() require.NoError(t, err) output := e2e.RunCommand(ctx, "boundary", diff --git a/testing/internal/e2e/boundary/boundary.go b/testing/internal/e2e/boundary/boundary.go index fd6f47adb8..127c1fd220 100644 --- a/testing/internal/e2e/boundary/boundary.go +++ b/testing/internal/e2e/boundary/boundary.go @@ -2,14 +2,13 @@ package boundary import ( - "github.com/hashicorp/boundary/api" "github.com/hashicorp/boundary/api/authmethods" ) // AuthenticateCliOutput parses the json response from running `boundary authenticate` type AuthenticateCliOutput struct { - Item *authmethods.AuthenticateResult - response *api.Response + Item *authmethods.AuthenticateResult + StatusCode int `json:"status_code"` } // AuthMethodInfo parses auth method info in the json response from running `boundary database init` diff --git a/testing/internal/e2e/boundary/env.go b/testing/internal/e2e/boundary/env.go index bfac1734f6..3c3e7d2a8b 100644 --- a/testing/internal/e2e/boundary/env.go +++ b/testing/internal/e2e/boundary/env.go @@ -2,15 +2,15 @@ package boundary import "github.com/kelseyhightower/envconfig" -type config struct { +type Config struct { Address string `envconfig:"BOUNDARY_ADDR" required:"true"` // e.g. http://127.0.0.1:9200 AuthMethodId string `envconfig:"E2E_PASSWORD_AUTH_METHOD_ID" required:"true"` // e.g. ampw_1234567890 AdminLoginName string `envconfig:"E2E_PASSWORD_ADMIN_LOGIN_NAME" default:"admin"` AdminLoginPassword string `envconfig:"E2E_PASSWORD_ADMIN_PASSWORD" required:"true"` } -func loadConfig() (*config, error) { - var c config +func LoadConfig() (*Config, error) { + var c Config err := envconfig.Process("", &c) if err != nil { return nil, err diff --git a/testing/internal/e2e/helpers.go b/testing/internal/e2e/helpers.go index 34dc15a2c7..993624de27 100644 --- a/testing/internal/e2e/helpers.go +++ b/testing/internal/e2e/helpers.go @@ -92,6 +92,8 @@ func RunCommand(ctx context.Context, command string, opt ...Option) *CommandResu // WithArgs is an option to RunCommand that allows the user to specify arguments // for the provided command. This option can be used multiple times in one command. +// +// RunCommand(context.Background(), "ls", WithArgs("-al")) func WithArgs(args ...string) Option { return func(o *options) { if o.withArgs == nil { diff --git a/testing/internal/e2e/tests/static/authenticate_primary_test.go b/testing/internal/e2e/tests/static/authenticate_primary_test.go new file mode 100644 index 0000000000..cbf62d4fa7 --- /dev/null +++ b/testing/internal/e2e/tests/static/authenticate_primary_test.go @@ -0,0 +1,54 @@ +package static_test + +import ( + "bytes" + "context" + "encoding/json" + "io" + "net/http" + "os/exec" + "strings" + "testing" + + "github.com/creack/pty" + "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/hashicorp/boundary/testing/internal/e2e/boundary" + "github.com/stretchr/testify/require" +) + +// TestCliAuthenticatePrimary tests the `boundary authenticate` command to ensure that a user can +// more quickly log in using the short-hand form of the command (authenticates using the primary auth +// method). +func TestCliAuthenticatePrimary(t *testing.T) { + e2e.MaybeSkipTest(t) + + bc, err := boundary.LoadConfig() + require.NoError(t, err) + + var cmd *exec.Cmd + ctx := context.Background() + cmd = exec.CommandContext(ctx, "boundary", "authenticate", "-addr", bc.Address, "-format", "json") + + f, err := pty.Start(cmd) + require.NoError(t, err) + t.Cleanup(func() { + err := f.Close() + require.NoError(t, err) + }) + + f.Write([]byte(bc.AdminLoginName + "\n")) + f.Write([]byte(bc.AdminLoginPassword + "\n")) + f.Write([]byte{4}) // EOT (End of Transmission - marks end of file stream) + + // Get last line from output (authentication response) + var buf bytes.Buffer + io.Copy(&buf, f) + parts := strings.Split(strings.TrimSpace(buf.String()), "\r\n") + response := parts[len(parts)-1] + + var authenticationResult boundary.AuthenticateCliOutput + err = json.Unmarshal([]byte(response), &authenticationResult) + require.NoError(t, err) + require.Equal(t, http.StatusOK, authenticationResult.StatusCode, response) + require.NotEmpty(t, authenticationResult.Item.Attributes["token"]) +}