Public dry run dryrun-750f29790fe2
Source commit: 750f29790fe2046599fbe5b5d06fdb63d92fabff Public tree identity: sha256:02326e08850bb287585789733ea5f3f153e1f7f3fd88afcc24e249107df91506
This commit is contained in:
commit
de66658961
102 changed files with 31669 additions and 0 deletions
206
scripts/cli-browser-login-flow-smoke.js
Normal file
206
scripts/cli-browser-login-flow-smoke.js
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const assert = require("assert");
|
||||
const cp = require("child_process");
|
||||
const fs = require("fs");
|
||||
const http = require("http");
|
||||
const net = require("net");
|
||||
const path = require("path");
|
||||
|
||||
const repo = path.resolve(__dirname, "..");
|
||||
const tmp = path.join(repo, "target", "acceptance", "tmp", "cli-browser-login-flow");
|
||||
fs.mkdirSync(tmp, { recursive: true });
|
||||
|
||||
function writeOpener() {
|
||||
const opener = path.join(tmp, "browser-opener.js");
|
||||
const trace = path.join(tmp, "browser-opener.log");
|
||||
fs.writeFileSync(
|
||||
opener,
|
||||
`#!/usr/bin/env node
|
||||
const fs = require("fs");
|
||||
const http = require("http");
|
||||
|
||||
const trace = ${JSON.stringify(trace)};
|
||||
fs.appendFileSync(trace, "started " + process.argv.slice(2).join(" ") + "\\n");
|
||||
const loginUrl = new URL(process.argv[2]);
|
||||
const state = loginUrl.searchParams.get("state");
|
||||
const redirect = new URL(loginUrl.searchParams.get("redirect_uri"));
|
||||
if (!state || !redirect) {
|
||||
fs.appendFileSync(trace, "missing state or redirect\\n");
|
||||
console.error("browser opener did not receive state and redirect_uri");
|
||||
process.exit(1);
|
||||
}
|
||||
redirect.searchParams.set("code", "browser-smoke-code");
|
||||
redirect.searchParams.set("state", state);
|
||||
fs.appendFileSync(trace, "callback " + redirect.toString() + "\\n");
|
||||
|
||||
http.get(redirect, (response) => {
|
||||
response.resume();
|
||||
response.on("end", () => {
|
||||
fs.appendFileSync(trace, "status " + response.statusCode + "\\n");
|
||||
process.exit(response.statusCode === 200 ? 0 : 1);
|
||||
});
|
||||
}).on("error", (error) => {
|
||||
fs.appendFileSync(trace, "error " + (error.stack || error.message) + "\\n");
|
||||
console.error(error.stack || error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
`
|
||||
);
|
||||
fs.chmodSync(opener, 0o755);
|
||||
return opener;
|
||||
}
|
||||
|
||||
function listen(server, host = "127.0.0.1") {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.once("error", reject);
|
||||
server.listen(0, host, () => {
|
||||
server.off("error", reject);
|
||||
resolve(server.address());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function startCoordinator() {
|
||||
const requests = [];
|
||||
const server = net.createServer((socket) => {
|
||||
let buffered = "";
|
||||
socket.on("data", (chunk) => {
|
||||
buffered += chunk.toString("utf8");
|
||||
if (!buffered.includes("\n")) return;
|
||||
const [line] = buffered.split(/\r?\n/);
|
||||
const request = JSON.parse(line);
|
||||
requests.push(request);
|
||||
assert.strictEqual(request.type, "oidc_browser_login");
|
||||
assert.strictEqual(request.authorization_code, "browser-smoke-code");
|
||||
assert.strictEqual(request.issuer_url, "http://127.0.0.1:1");
|
||||
assert.strictEqual(request.client_id, "disasmer-smoke");
|
||||
assert.match(request.redirect_path, /^http:\/\/127\.0\.0\.1:45173\/callback$/);
|
||||
assert.match(request.state, /^sha256:[a-f0-9]{64}$/);
|
||||
socket.end(
|
||||
JSON.stringify({
|
||||
type: "oidc_browser_session",
|
||||
session: {
|
||||
tenant: request.tenant,
|
||||
project: request.project,
|
||||
user: request.user,
|
||||
browser_credential_kind: "BrowserSession",
|
||||
cli_session_credential_kind: "CliDeviceSession",
|
||||
provider_tokens_sent_to_nodes: false,
|
||||
flow: {
|
||||
authorization_url: "http://127.0.0.1:1/application/o/authorize/",
|
||||
callback_path: request.redirect_path,
|
||||
state: request.state,
|
||||
},
|
||||
oidc_token_exchange: {
|
||||
token_endpoint: "http://127.0.0.1:1/application/o/token/",
|
||||
token_type: "Bearer",
|
||||
received_access_token: true,
|
||||
received_id_token: true,
|
||||
retained_provider_tokens: false,
|
||||
},
|
||||
},
|
||||
}) + "\n"
|
||||
);
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
const address = await listen(server);
|
||||
return {
|
||||
url: `${address.address}:${address.port}`,
|
||||
requests,
|
||||
close: () => new Promise((resolve) => server.close(() => resolve())),
|
||||
};
|
||||
}
|
||||
|
||||
function runDisasmer(args, env) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = cp.spawn("cargo", args, {
|
||||
cwd: repo,
|
||||
env,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
const timeout = setTimeout(() => {
|
||||
child.kill();
|
||||
reject(new Error(`disasmer command timed out\n${stderr}`));
|
||||
}, 30000);
|
||||
child.stdout.on("data", (chunk) => {
|
||||
stdout += chunk.toString("utf8");
|
||||
});
|
||||
child.stderr.on("data", (chunk) => {
|
||||
stderr += chunk.toString("utf8");
|
||||
});
|
||||
child.on("error", (error) => {
|
||||
clearTimeout(timeout);
|
||||
reject(error);
|
||||
});
|
||||
child.on("close", (code, signal) => {
|
||||
clearTimeout(timeout);
|
||||
if (code !== 0) {
|
||||
reject(
|
||||
new Error(
|
||||
`disasmer command failed with ${signal || code}\nSTDERR:\n${stderr}\nSTDOUT:\n${stdout}`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const opener = writeOpener();
|
||||
const coordinator = await startCoordinator();
|
||||
try {
|
||||
const stdout = await runDisasmer(
|
||||
[
|
||||
"run",
|
||||
"-q",
|
||||
"-p",
|
||||
"disasmer-cli",
|
||||
"--bin",
|
||||
"disasmer",
|
||||
"--",
|
||||
"login",
|
||||
"--browser",
|
||||
"--json",
|
||||
"--coordinator",
|
||||
coordinator.url,
|
||||
"--oidc-issuer-url",
|
||||
"http://127.0.0.1:1",
|
||||
"--oidc-client-id",
|
||||
"disasmer-smoke",
|
||||
"--tenant",
|
||||
"tenant-smoke",
|
||||
"--project-id",
|
||||
"project-smoke",
|
||||
"--user",
|
||||
"user-smoke",
|
||||
],
|
||||
{
|
||||
...process.env,
|
||||
DISASMER_BROWSER_OPEN_COMMAND: opener,
|
||||
DISASMER_BROWSER_LOGIN_TIMEOUT_SECONDS: "5",
|
||||
}
|
||||
);
|
||||
const report = JSON.parse(stdout);
|
||||
assert.strictEqual(report.plan.coordinator, coordinator.url);
|
||||
assert.strictEqual(report.boundary.cli_contacted_coordinator, true);
|
||||
assert.strictEqual(report.boundary.scoped_cli_session_received, true);
|
||||
assert.strictEqual(report.boundary.provider_tokens_exposed_to_cli, false);
|
||||
assert.strictEqual(report.boundary.provider_tokens_sent_to_nodes, false);
|
||||
assert.strictEqual(report.boundary.coordinator_session_requests, 1);
|
||||
assert.strictEqual(coordinator.requests.length, 1);
|
||||
} finally {
|
||||
if (coordinator.requests.length === 0) {
|
||||
await coordinator.close().catch(() => {});
|
||||
}
|
||||
}
|
||||
console.log("CLI browser login flow smoke passed");
|
||||
})().catch((error) => {
|
||||
console.error(error.stack || error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue