* test(e2e): Address deprecation * test(e2e): Add additional connection assertions on tests * CR: Fix flake when waiting for sessions If no sessions are available and the page needs to reload, we should wait to ensure that the page has loaded before checking what the state of the sessions are * CR: Address flake in connect methods Noticed an issue where a session recording was not playable. The theory is that the session didn't last long enough before it was cancelled. This adds a 2 second wait after establishing a connection before continuing. * CR: Use authenticated state by default * CR: Update dynamic host catalog assertion * CR: Simplify host set checks - Use .all() when looping - Add check to see if we need to reload the page or not * CR: Be more specific with locator Ran into a conflict with the Static/Dynamic host catalog type and the Static/Dynamic credential type. * CR: Update connection methods to be more resilient Rather than using a hardcoded sleep, we will now run a command on the target and wait for a specific string to return before continuing. * CR
152 lines
4.2 KiB
JavaScript
152 lines
4.2 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { test } from '../../global-setup.js';
|
|
import { execSync } from 'child_process';
|
|
|
|
import * as boundaryCli from '../../helpers/boundary-cli';
|
|
import * as vaultCli from '../../helpers/vault-cli';
|
|
import { CredentialStoresPage } from '../pages/credential-stores.js';
|
|
import { OrgsPage } from '../pages/orgs.js';
|
|
import { ProjectsPage } from '../pages/projects.js';
|
|
import { SessionsPage } from '../pages/sessions.js';
|
|
import { TargetsPage } from '../pages/targets.js';
|
|
|
|
const sshPolicyName = 'ssh-policy';
|
|
const boundaryPolicyName = 'boundary-controller';
|
|
// This must match the secret path in ssh-policy.hcl
|
|
const secretsPath = 'e2e_secrets';
|
|
// This must match the secret name in ssh-policy.hcl
|
|
const secretName = 'boundary-client';
|
|
|
|
test.beforeAll(async () => {
|
|
await boundaryCli.checkBoundaryCli();
|
|
await vaultCli.checkVaultCli();
|
|
});
|
|
|
|
test.beforeEach(async () => {
|
|
execSync(`vault secrets disable ${secretsPath}`);
|
|
});
|
|
|
|
test('SSH Certificate Injection @ent @docker', async ({
|
|
page,
|
|
baseURL,
|
|
adminAuthMethodId,
|
|
adminLoginName,
|
|
adminPassword,
|
|
sshUser,
|
|
sshCaKey,
|
|
sshCaKeyPublic,
|
|
targetAddress,
|
|
targetPort,
|
|
vaultAddr,
|
|
}) => {
|
|
await page.goto('/');
|
|
let orgId;
|
|
let connect;
|
|
try {
|
|
// Set up vault
|
|
execSync(
|
|
`vault policy write ${boundaryPolicyName} ./admin/tests/fixtures/boundary-controller-policy.hcl`,
|
|
);
|
|
execSync(`vault secrets enable -path=${secretsPath} ssh`);
|
|
execSync(
|
|
`vault policy write ${sshPolicyName} ./admin/tests/fixtures/ssh-policy.hcl`,
|
|
);
|
|
execSync(
|
|
`vault write ${secretsPath}/roles/${secretName} @./admin/tests/fixtures/ssh-certificate-injection-role.json`,
|
|
);
|
|
|
|
const private_key = Buffer.from(sshCaKey, 'base64');
|
|
const public_key = Buffer.from(sshCaKeyPublic, 'base64');
|
|
|
|
execSync(
|
|
`vault write ${secretsPath}/config/ca` +
|
|
` private_key="${private_key}"` +
|
|
` public_key="${public_key}"` +
|
|
` generate_signing_key=false`,
|
|
` format=json`,
|
|
);
|
|
|
|
const vaultToken = JSON.parse(
|
|
execSync(
|
|
`vault token create` +
|
|
` -no-default-policy=true` +
|
|
` -policy=${boundaryPolicyName}` +
|
|
` -policy=${sshPolicyName}` +
|
|
` -orphan=true` +
|
|
` -period=20m` +
|
|
` -renewable=true` +
|
|
` -format=json`,
|
|
),
|
|
);
|
|
const clientToken = vaultToken.auth.client_token;
|
|
|
|
// Create org
|
|
const orgsPage = new OrgsPage(page);
|
|
const orgName = await orgsPage.createOrg();
|
|
|
|
// Create project
|
|
const projectsPage = new ProjectsPage(page);
|
|
const projectName = await projectsPage.createProject();
|
|
|
|
// Create target
|
|
const targetsPage = new TargetsPage(page);
|
|
const targetName = await targetsPage.createSshTargetWithAddressEnt(
|
|
targetAddress,
|
|
targetPort,
|
|
);
|
|
|
|
// Create credentials
|
|
const credentialStoresPage = new CredentialStoresPage(page);
|
|
await credentialStoresPage.createVaultCredentialStore(
|
|
vaultAddr,
|
|
clientToken,
|
|
);
|
|
const credentialLibraryName =
|
|
await credentialStoresPage.createVaultSshCertificateCredentialLibraryEnt(
|
|
`${secretsPath}/issue/${secretName}`,
|
|
sshUser,
|
|
);
|
|
await targetsPage.addInjectedCredentialsToTarget(
|
|
targetName,
|
|
credentialLibraryName,
|
|
);
|
|
|
|
// Connect to target
|
|
await boundaryCli.authenticateBoundary(
|
|
baseURL,
|
|
adminAuthMethodId,
|
|
adminLoginName,
|
|
adminPassword,
|
|
);
|
|
orgId = await boundaryCli.getOrgIdFromName(orgName);
|
|
const projectId = await boundaryCli.getProjectIdFromName(
|
|
orgId,
|
|
projectName,
|
|
);
|
|
const targetId = await boundaryCli.getTargetIdFromName(
|
|
projectId,
|
|
targetName,
|
|
);
|
|
connect = await boundaryCli.connectSshToTarget(targetId);
|
|
const sessionsPage = new SessionsPage(page);
|
|
await sessionsPage.waitForSessionToBeVisible(targetName);
|
|
} finally {
|
|
// End `boundary connect` process
|
|
if (connect) {
|
|
connect.kill('SIGTERM');
|
|
}
|
|
|
|
if (orgId) {
|
|
await boundaryCli.deleteScope(orgId);
|
|
}
|
|
|
|
execSync(`vault secrets disable ${secretsPath}`);
|
|
execSync(`vault policy delete ${sshPolicyName}`);
|
|
execSync(`vault policy delete ${boundaryPolicyName}`);
|
|
}
|
|
});
|