test(e2e): Add test for LDAP (#4061)

* test(e2e): Add test for LDAP

This adds the infrastructure and a test for an LDAP workflow

* test(e2e): Refactor test packages

This reduces the number of scenarios needed

* CR

* fixup! test(e2e): Add test for LDAP
This commit is contained in:
Michael Li authored and GitHub committed 2023-11-28 16:25:26 -05:00
1 parent a89573b35f
commit 093f889333
13 files changed
+451 -41

No files matched your search

@@ -0,0 +1,33 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package base_plus_test
import "github.com/kelseyhightower/envconfig"
type config struct {
TargetAddress string `envconfig:"E2E_TARGET_ADDRESS" required:"true"` // e.g. 192.168.0.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
PostgresDbName string `envconfig:"E2E_POSTGRES_DB_NAME" required:"true"`
PostgresUser string `envconfig:"E2E_POSTGRES_USER" required:"true"`
PostgresPassword string `envconfig:"E2E_POSTGRES_PASSWORD" required:"true"`
LdapAddress string `envconfig:"E2E_LDAP_ADDR" required:"true"` // e.g. ldap://ldap
LdapDomainDn string `envconfig:"E2E_LDAP_DOMAIN_DN" required:"true"` // e.g. dc=example,dc=org
LdapAdminDn string `envconfig:"E2E_LDAP_ADMIN_DN" required:"true"` // e.g. cn=admin,dc=example,dc=org
LdapAdminPassword string `envconfig:"E2E_LDAP_ADMIN_PASSWORD" required:"true"`
LdapUserName string `envconfig:"E2E_LDAP_USER_NAME" required:"true"`
LdapUserPassword string `envconfig:"E2E_LDAP_USER_PASSWORD" required:"true"`
LdapGroupName string `envconfig:"E2E_LDAP_GROUP_NAME" required:"true"`
}
func loadTestConfig() (*config, error) {
var c config
err := envconfig.Process("", &c)
if err != nil {
return nil, err
}
return &c, nil
}
@@ -1,7 +1,7 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package base_test
package base_plus_test
import (
"context"
@@ -0,0 +1,183 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package base_plus_test
import (
"context"
"encoding/json"
"net/http"
"testing"
"github.com/hashicorp/boundary/api/accounts"
"github.com/hashicorp/boundary/api/authmethods"
"github.com/hashicorp/boundary/api/managedgroups"
"github.com/hashicorp/boundary/testing/internal/e2e"
"github.com/hashicorp/boundary/testing/internal/e2e/boundary"
"github.com/stretchr/testify/require"
)
// TestCliLdap uses the boundary cli to set up an LDAP auth method and confirm
// that an LDAP user can authenticate to boundary. It also confirms that an LDAP
// managed group can be added as a principal to a role.
func TestCliLdap(t *testing.T) {
e2e.MaybeSkipTest(t)
c, err := loadTestConfig()
require.NoError(t, err)
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
newOrgId := boundary.CreateNewOrgCli(t, ctx)
t.Cleanup(func() {
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs("scopes", "delete", "-id", newOrgId))
require.NoError(t, output.Err, string(output.Stderr))
})
// Create an LDAP auth method
output := e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"auth-methods", "create", "ldap",
"-scope-id", newOrgId,
"-name", "e2e LDAP",
"-urls", c.LdapAddress,
"-user-dn", c.LdapDomainDn,
"-user-attr", "uid",
"-group-dn", c.LdapDomainDn,
"-bind-dn", c.LdapAdminDn,
"-bind-password", "env://LDAP_PW",
"-state", "active-public",
"-enable-groups", "true",
"-discover-dn", "true",
"-format", "json",
),
e2e.WithEnv("LDAP_PW", c.LdapAdminPassword),
)
require.NoError(t, output.Err, string(output.Stderr))
var newAuthMethodResult authmethods.AuthMethodCreateResult
err = json.Unmarshal(output.Stdout, &newAuthMethodResult)
require.NoError(t, err)
ldapAuthMethodId := newAuthMethodResult.Item.Id
t.Logf("Create Auth Method: %s", ldapAuthMethodId)
// Create an LDAP account
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"accounts", "create", "ldap",
"-auth-method-id", ldapAuthMethodId,
"-name", "einstein",
"-login-name", c.LdapUserName,
"-format", "json",
),
)
require.NoError(t, output.Err, string(output.Stderr))
var newAccountResult accounts.AccountCreateResult
err = json.Unmarshal(output.Stdout, &newAccountResult)
require.NoError(t, err)
newAccountId := newAccountResult.Item.Id
t.Logf("Created Account: %s", newAccountId)
// Create a user and attach the LDAP account
newUserId := boundary.CreateNewUserCli(t, ctx, newOrgId)
boundary.SetAccountToUserCli(t, ctx, newUserId, newAccountId)
// Try to log in with the wrong password
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"authenticate", "ldap",
"-auth-method-id", ldapAuthMethodId,
"-login-name", c.LdapUserName,
"-password", "env://LDAP_PW",
),
e2e.WithEnv("LDAP_PW", c.LdapAdminPassword),
)
require.Error(t, output.Err, string(output.Stderr))
// Log in as the LDAP user
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"authenticate", "ldap",
"-auth-method-id", ldapAuthMethodId,
"-login-name", c.LdapUserName,
"-password", "env://LDAP_PW",
),
e2e.WithEnv("LDAP_PW", c.LdapUserPassword),
)
require.NoError(t, output.Err, string(output.Stderr))
// Confirm there is a permissions error when trying to read an auth method
// as an LDAP user
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"auth-methods", "read",
"-id", ldapAuthMethodId,
"-format", "json",
),
)
require.Error(t, output.Err, string(output.Stderr))
var response boundary.CliError
err = json.Unmarshal(output.Stderr, &response)
require.NoError(t, err)
require.Equal(t, http.StatusForbidden, response.Status)
// Create an LDAP managed group
boundary.AuthenticateAdminCli(t, ctx)
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"managed-groups", "create", "ldap",
"-auth-method-id", ldapAuthMethodId,
"-name", c.LdapGroupName,
"-group-names", c.LdapGroupName,
"-format", "json",
),
)
require.NoError(t, output.Err, string(output.Stderr))
var newManagedGroupResult managedgroups.ManagedGroupCreateResult
err = json.Unmarshal(output.Stdout, &newManagedGroupResult)
require.NoError(t, err)
managedGroupId := newManagedGroupResult.Item.Id
t.Logf("Created Managed Group: %s", managedGroupId)
// Confirm that LDAP user is in the managed group
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"managed-groups", "read",
"-id", managedGroupId,
"-format", "json",
),
)
require.NoError(t, output.Err, string(output.Stderr))
var managedGroupReadResult managedgroups.ManagedGroupReadResult
err = json.Unmarshal(output.Stdout, &managedGroupReadResult)
require.NoError(t, err)
require.Contains(t, managedGroupReadResult.Item.MemberIds, newAccountId)
// Add managed group as a principal to a role with permissions to read auth methods
newRoleId := boundary.CreateNewRoleCli(t, ctx, newOrgId)
boundary.AddPrincipalToRoleCli(t, ctx, newRoleId, managedGroupId)
boundary.AddGrantToRoleCli(t, ctx, newRoleId, "ids=*;type=auth-method;actions=read")
// Log in as the LDAP user again
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"authenticate", "ldap",
"-auth-method-id", ldapAuthMethodId,
"-login-name", c.LdapUserName,
"-password", "env://LDAP_PW",
),
e2e.WithEnv("LDAP_PW", c.LdapUserPassword),
)
require.NoError(t, output.Err, string(output.Stderr))
// Read the auth method. Expect no error
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"auth-methods", "read",
"-id", ldapAuthMethodId,
"-format", "json",
),
)
require.NoError(t, output.Err, string(output.Stderr))
}
@@ -1,7 +1,7 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package base_with_postgres_test
package base_plus_test
import (
"bytes"
@@ -1,24 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package base_with_postgres_test
import "github.com/kelseyhightower/envconfig"
type config struct {
TargetAddress string `envconfig:"E2E_TARGET_ADDRESS" required:"true"` // e.g. 192.168.0.1
TargetPort string `envconfig:"E2E_TARGET_PORT" required:"true"`
PostgresDbName string `envconfig:"E2E_POSTGRES_DB_NAME" required:"true"`
PostgresUser string `envconfig:"E2E_POSTGRES_USER" required:"true"`
PostgresPassword string `envconfig:"E2E_POSTGRES_PASSWORD" required:"true"`
}
func loadTestConfig() (*config, error) {
var c config
err := envconfig.Process("", &c)
if err != nil {
return nil, err
}
return &c, nil
}