190 lines
4.8 KiB
JavaScript
Executable File
190 lines
4.8 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
import { exec, execSync, spawnSync } from "child_process";
|
|
import { writeFileSync } from "fs";
|
|
import { parseArgs } from "util";
|
|
|
|
const args = parseArgs({
|
|
options: {
|
|
"app-name": { type: "string", short: "a" },
|
|
help: { type: "boolean", short: "h" },
|
|
"generate-client-secret": { type: "boolean", short: "s" },
|
|
"config": { type: "string", short: "c", default: "config.js" },
|
|
"write-config": { type: "string", short: "w" },
|
|
},
|
|
});
|
|
|
|
if (args.values["write-config"] && !["js", "env", "both"].includes(args.values["write-config"])) {
|
|
console.error(
|
|
"Invalid value for --write-config. Allowed values are: js, env, both.",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const config = {};
|
|
|
|
if (args.values["app-name"]) {
|
|
config.appName = args.values["app-name"];
|
|
} else {
|
|
config.appName = "Azure Node Playground";
|
|
}
|
|
|
|
// Get the tenant ID
|
|
try {
|
|
config.tenantId = execSync(`az account show --query "tenantId" -o tsv`)
|
|
.toString()
|
|
.trim();
|
|
} catch (error) {
|
|
console.error("Failed to get Azure tenant ID.");
|
|
process.exit(1);
|
|
}
|
|
|
|
if (config.tenantId) {
|
|
console.log(`Using Tenant ID: ${config.tenantId}`);
|
|
} else {
|
|
console.error("Failed to get Azure tenant ID.");
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
const appIdList = JSON.parse(
|
|
execSync(
|
|
`az ad app list --filter "displayName eq '${config.appName}'" -o json`,
|
|
)
|
|
.toString()
|
|
.trim(),
|
|
);
|
|
if (appIdList.length !== 1) {
|
|
throw new Error("App not found or multiple apps with the same name.");
|
|
}
|
|
config.clientId = appIdList[0].appId;
|
|
} catch (error) {
|
|
console.error("Failed to query Azure AD applications.");
|
|
process.exit(1);
|
|
}
|
|
|
|
if (config.clientId) {
|
|
console.log(`App already exists with Client ID: ${config.clientId}`);
|
|
} else {
|
|
// Create the Azure AD application, capturing the JSON output, and extracting the .appId
|
|
try {
|
|
config.clientId = execSync(
|
|
`az ad app create --display-name "${config.appName}" --query "appId" -o tsv`,
|
|
)
|
|
.toString()
|
|
.trim();
|
|
} catch (error) {
|
|
console.error("Failed to create Azure AD application.");
|
|
process.exit(1);
|
|
}
|
|
console.log(`Created App with Client ID: ${config.clientId}`);
|
|
}
|
|
|
|
// Check if service principal exists
|
|
let spObjId;
|
|
|
|
try {
|
|
const spIdList = JSON.parse(
|
|
execSync(`az ad sp list --filter "appId eq '${config.clientId}'" -o json`)
|
|
.toString()
|
|
.trim(),
|
|
);
|
|
if (spIdList.length === 1) {
|
|
spObjId = spIdList[0].id;
|
|
} else {
|
|
spObjId = null;
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to query service principals.");
|
|
process.exit(1);
|
|
}
|
|
|
|
if (spObjId) {
|
|
console.log("Using existing service principal.");
|
|
} else {
|
|
// Now create the service principal for the app
|
|
try {
|
|
spObjId = execSync(
|
|
`az ad sp create --id ${config.clientId} --query "id" -o tsv`,
|
|
);
|
|
console.log("Service principal created.");
|
|
} catch (error) {
|
|
console.log("Failed to create service principal.");
|
|
}
|
|
}
|
|
|
|
if (args.values["generate-client-secret"]) {
|
|
// Generate a new client secret for the application
|
|
try {
|
|
const result = spawnSync(
|
|
"az",
|
|
[
|
|
"ad",
|
|
"app",
|
|
"credential",
|
|
"reset",
|
|
"--id",
|
|
config.clientId,
|
|
"--query",
|
|
"password",
|
|
"-o",
|
|
"tsv",
|
|
],
|
|
{ encoding: "utf-8" },
|
|
);
|
|
config.clientSecret = result.stdout.toString().trim();
|
|
console.log("Client secret generated.");
|
|
} catch (error) {
|
|
console.error("Failed to generate client secret.");
|
|
console.error(error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
let envContent = `AZ_APP_NAME="${config.appName}"
|
|
ARM_TENANT_ID=${config.tenantId}
|
|
ARM_CLIENT_ID=${config.clientId}
|
|
`;
|
|
|
|
if (config.clientSecret) {
|
|
envContent += `ARM_CLIENT_SECRET=${config.clientSecret}\n`;
|
|
}
|
|
|
|
if (["env", "both"].includes(args.values["write-config"])) {
|
|
// Write the APP_ID to the .env file
|
|
writeFileSync(".env", envContent);
|
|
try {
|
|
execSync("chmod 600 .env");
|
|
} catch (error) {
|
|
console.warn(
|
|
"Could not set file permissions for .env. Please ensure it is secured appropriately.",
|
|
);
|
|
}
|
|
console.log(".env file created with application configuration.");
|
|
} else {
|
|
console.log("\nThe .env file for the application:");
|
|
console.log(envContent);
|
|
}
|
|
|
|
if (["js", "both"].includes(args.values["write-config"])) {
|
|
// Save the config to the 'config.js' file.
|
|
writeFileSync(
|
|
args.values["config"],
|
|
`export const config = ${JSON.stringify(config, null, 4)};\n`,
|
|
);
|
|
|
|
try {
|
|
execSync(`chmod 600 ${args.values["config"]}`);
|
|
} catch (error) {
|
|
console.warn(
|
|
`Could not set file permissions for ${args.values["config"]}. Please ensure it is secured appropriately.`,
|
|
);
|
|
}
|
|
console.log(`${args.values["config"]} file created.`);
|
|
} else {
|
|
console.log(`The ${args.values["config"]} file content:`);
|
|
console.log(
|
|
`export const config = ${JSON.stringify(config, null, 4)};\n`,
|
|
);
|
|
}
|