129 lines
4.9 KiB
TypeScript
129 lines
4.9 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import { expect, test } from "../../fixtures/docker-test-base";
|
|
import { waitForLatestSessionDone } from "../../helpers/session";
|
|
import {
|
|
assertExactFixtureTransport,
|
|
credentialBrokerPublicURL,
|
|
fixtureGitHost,
|
|
fixtureGitURL,
|
|
fixtureGitSecret,
|
|
fixtureGitUser,
|
|
fixtureGitProvider,
|
|
installFixturePlugin,
|
|
revokeFixtureConnection,
|
|
runDockerGit,
|
|
startPluginGitFixture,
|
|
uninstallFixturePlugin,
|
|
} from "../../helpers/plugin-git-credentials";
|
|
import { E2E_IMAGE_TAG } from "../../fixtures/docker-probe";
|
|
|
|
test.skip(
|
|
!process.env.KANDEV_E2E_CREDENTIAL_BROKER_PUBLIC_BASE_URL?.trim(),
|
|
"requires KANDEV_E2E_CREDENTIAL_BROKER_PUBLIC_BASE_URL reachable over HTTPS from Docker",
|
|
);
|
|
|
|
test.describe("Bitbucket plugin contract — Docker executor credential leases", () => {
|
|
test("clones and pushes through an exact provider lease, then rejects its revoked generation", async ({
|
|
apiClient,
|
|
backend,
|
|
seedData,
|
|
}) => {
|
|
test.setTimeout(240_000);
|
|
const publicBrokerURL = credentialBrokerPublicURL(backend.port);
|
|
if (!publicBrokerURL) throw new Error("credential broker public URL is required");
|
|
|
|
const releaseBrokerEnv = await backend.useEnv({
|
|
KANDEV_GITHUB_CREDENTIAL_BROKER_PUBLIC_BASE_URL: publicBrokerURL,
|
|
});
|
|
const fixture = await startPluginGitFixture(backend.tmpDir);
|
|
try {
|
|
await installFixturePlugin(backend.baseUrl);
|
|
const { executors } = await apiClient.listExecutors();
|
|
const dockerExecutor = executors.find((executor) => executor.type === "local_docker");
|
|
expect(dockerExecutor).toBeTruthy();
|
|
const profile = await apiClient.createExecutorProfile(dockerExecutor!.id, {
|
|
name: "E2E provider-neutral Git credentials",
|
|
config: { image_tag: E2E_IMAGE_TAG },
|
|
prepare_script: "",
|
|
cleanup_script: "",
|
|
env_vars: [
|
|
...fixture.profileGitEnv,
|
|
{ key: "NO_PROXY", value: new URL(publicBrokerURL).hostname },
|
|
],
|
|
});
|
|
const repository = await apiClient.createRepository(
|
|
seedData.workspaceId,
|
|
fixture.checkoutPath,
|
|
"main",
|
|
{
|
|
name: "TEAM/fixture",
|
|
provider: fixtureGitProvider,
|
|
provider_host: `https://${fixtureGitHost}`,
|
|
provider_owner: "TEAM",
|
|
provider_name: "fixture",
|
|
},
|
|
);
|
|
const task = await apiClient.createTaskWithAgent(
|
|
seedData.workspaceId,
|
|
"Docker fixture credential lease",
|
|
seedData.agentProfileId,
|
|
{
|
|
description: "/e2e:simple-message",
|
|
workflow_id: seedData.workflowId,
|
|
workflow_step_id: seedData.startStepId,
|
|
repository_ids: [repository.id],
|
|
executor_profile_id: profile.id,
|
|
},
|
|
);
|
|
await waitForLatestSessionDone(
|
|
apiClient,
|
|
task.id,
|
|
1,
|
|
"waiting for credentialed Docker clone",
|
|
);
|
|
const environment = await apiClient.getTaskEnvironment(task.id);
|
|
expect(environment?.container_id).toBeTruthy();
|
|
const remoteURL = await runDockerGit(
|
|
environment!.container_id!,
|
|
"cd /workspace && git remote get-url origin",
|
|
);
|
|
expect(remoteURL.status, remoteURL.output).toBe(0);
|
|
expect(remoteURL.output.trim()).toBe(fixtureGitURL);
|
|
|
|
const push = await runDockerGit(
|
|
environment!.container_id!,
|
|
"cd /workspace && printf 'pushed\\n' >> README.md && git add README.md && git -c user.name=E2E -c user.email=e2e@test.local commit -m 'credential fixture push' && git push origin HEAD:main",
|
|
);
|
|
expect(push.status, push.output).toBe(0);
|
|
expect(fixture.pushed()).toBe(true);
|
|
assertExactFixtureTransport(fixture);
|
|
|
|
const inspect = spawnSync("docker", ["inspect", environment!.container_id!], {
|
|
encoding: "utf8",
|
|
});
|
|
const taskResponse = await apiClient.rawRequest("GET", `/api/v1/tasks/${task.id}`);
|
|
const taskBody = await taskResponse.text();
|
|
expect(`${inspect.stdout}${taskBody}`).not.toContain(fixtureGitSecret);
|
|
expect(`${inspect.stdout}${taskBody}`).not.toContain(`${fixtureGitUser}:${fixtureGitSecret}`);
|
|
|
|
const revoke = await revokeFixtureConnection(backend.baseUrl, seedData.workspaceId);
|
|
expect(revoke.status).toBe(200);
|
|
expect(await revoke.text()).not.toContain(fixtureGitSecret);
|
|
|
|
const afterRevocation = await runDockerGit(
|
|
environment!.container_id!,
|
|
"cd /workspace && git fetch origin",
|
|
);
|
|
expect(afterRevocation.status).not.toBe(0);
|
|
expect(afterRevocation.output).not.toContain(fixtureGitSecret);
|
|
expect(afterRevocation.output).not.toContain(`${fixtureGitUser}:${fixtureGitSecret}`);
|
|
const logs = spawnSync("docker", ["logs", environment!.container_id!], { encoding: "utf8" });
|
|
expect(`${logs.stdout}${logs.stderr}`).not.toContain(fixtureGitSecret);
|
|
} finally {
|
|
await uninstallFixturePlugin(backend.baseUrl);
|
|
await fixture.close();
|
|
await releaseBrokerEnv();
|
|
}
|
|
});
|
|
});
|