Refactor of authentication code. Added configuration file selectable authentication method. Selectable from built-in Azure Identity, and custom PCA using MSAL.
Some checks failed
build / build (push) Failing after 14s

This commit is contained in:
2026-03-08 19:07:10 +01:00
parent 0829b35113
commit a98c77cd2e
17 changed files with 297 additions and 131 deletions

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
import { acquireResourceToken } from "../../azure/index.ts";
import { getAccessToken } from "../../azure/index.ts";
import { getDevOpsApiToken } from "../../devops/index.ts";
import { loadConfig } from "../../index.ts";
import { loadAuthConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -13,22 +13,21 @@ Options:
--type, -t <value> Token type: azurerm|devops`;
}
export async function runGetTokenCommand(values: CommandValues): Promise<unknown> {
export async function runGetTokenCommand(
values: CommandValues,
): Promise<unknown> {
const tokenType = (values.type ?? "").toString().trim().toLowerCase();
if (!tokenType) {
throw new Error("--type is required for get-token (allowed: azurerm, devops)");
throw new Error(
"--type is required for get-token (allowed: azurerm, devops)",
);
}
const config = await loadConfig("public-config");
const config = await loadAuthConfig("public-config");
if (tokenType === "azurerm") {
const result = await acquireResourceToken(
config.tenantId,
config.clientId,
"arm",
);
const accessToken = await getAccessToken(config.tenantId, config.clientId, ["arm"]);
const accessToken = result?.accessToken;
if (!accessToken) {
throw new Error("Failed to obtain AzureRM token");
}
@@ -40,7 +39,10 @@ export async function runGetTokenCommand(values: CommandValues): Promise<unknown
}
if (tokenType === "devops") {
const accessToken = await getDevOpsApiToken(config.tenantId, config.clientId);
const accessToken = await getDevOpsApiToken(
config.tenantId,
config.clientId,
);
return {
tokenType,
accessToken,

View File

@@ -1,8 +1,7 @@
// SPDX-License-Identifier: MIT
import { listAppGrants } from "../../graph/app.ts";
import { getGraphClientFromPublicConfig } from "./shared.ts";
import { getGraphClient } from "../../graph/index.ts";
import type { CommandValues } from "./types.ts";
export function usageListAppGrants(): string {
@@ -17,6 +16,6 @@ export async function runListAppGrantsCommand(values: CommandValues): Promise<un
throw new Error("--app-id is required for list-app-grants");
}
const { client } = await getGraphClientFromPublicConfig();
const client = await getGraphClient();
return listAppGrants(client, values["app-id"]);
}

View File

@@ -2,7 +2,8 @@
import { listAppPermissions, listAppPermissionsResolved } from "../../graph/app.ts";
import { filterByPermissionName, getGraphClientFromPublicConfig } from "./shared.ts";
import { filterByPermissionName } from "./shared.ts";
import { getGraphClient } from "../../graph/index.ts";
import type { CommandValues } from "./types.ts";
function isRecord(value: unknown): value is Record<string, unknown> {
@@ -37,7 +38,7 @@ export async function runListAppPermissionsCommand(values: CommandValues): Promi
throw new Error("--app-id is required for list-app-permissions");
}
const { client } = await getGraphClientFromPublicConfig();
const client = await getGraphClient();
let result: unknown = values.resolve || values.filter
? await listAppPermissionsResolved(client, values["app-id"])
: await listAppPermissions(client, values["app-id"]);

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
import { listApps } from "../../graph/app.ts";
import { filterByDisplayName, getGraphClientFromPublicConfig } from "./shared.ts";
import { filterByDisplayName } from "./shared.ts";
import { getGraphClient } from "../../graph/index.ts";
import type { CommandValues } from "./types.ts";
export function usageListApps(): string {
@@ -15,7 +15,8 @@ Options:
}
export async function runListAppsCommand(values: CommandValues): Promise<unknown> {
const { client } = await getGraphClientFromPublicConfig();
const client = await getGraphClient();
let result = await listApps(client, values["display-name"], values["app-id"]);
if (values["app-id"] && result.length > 1) {
throw new Error(`Expected a single app for --app-id ${values["app-id"]}, but got ${result.length}`);

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
import { listResourcePermissions } from "../../graph/app.ts";
import { filterByPermissionName, getGraphClientFromPublicConfig } from "./shared.ts";
import { getGraphClient } from "../../graph/index.ts";
import { filterByPermissionName } from "./shared.ts";
import type { CommandValues } from "./types.ts";
export function usageListResourcePermissions(): string {
@@ -22,7 +22,7 @@ export async function runListResourcePermissionsCommand(values: CommandValues):
throw new Error("Use either --app-id or --display-name for list-resource-permissions, not both");
}
const { client } = await getGraphClientFromPublicConfig();
const client = await getGraphClient();
let result = await listResourcePermissions(
client,
values["app-id"],

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
import { login } from "../../azure/index.ts";
import { loadConfig } from "../../index.ts";
import { loadAuthConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -17,7 +17,7 @@ Options:
}
export async function runLoginCommand(values: CommandValues): Promise<unknown> {
const config = await loadConfig("public-config");
const config = await loadAuthConfig("public-config");
return login(
config.tenantId,
config.clientId,

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
import { logout } from "../../azure/index.ts";
import { loadConfig } from "../../index.ts";
import { loadAuthConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -13,6 +13,6 @@ Options:
}
export async function runLogoutCommand(values: CommandValues): Promise<unknown> {
const config = await loadConfig("public-config");
const config = await loadAuthConfig("public-config");
return logout(config.tenantId, config.clientId, Boolean(values.all));
}

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
import { acquireResourceToken } from "../../azure/index.ts";
import { getAccessToken } from "../../azure/index.ts";
import { getDevOpsApiToken } from "../../devops/index.ts";
import { loadConfig } from "../../index.ts";
import { loadAuthConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -19,7 +19,9 @@ Authorization is added automatically for:
dev.azure.com Uses devops token`;
}
function parseHeaderLine(header?: string): { name: string; value: string } | null {
function parseHeaderLine(
header?: string,
): { name: string; value: string } | null {
if (!header || header.trim() === "") {
return null;
}
@@ -54,15 +56,10 @@ async function getAutoAuthorizationHeader(url: URL): Promise<string | null> {
return null;
}
const config = await loadConfig("public-config");
const config = await loadAuthConfig("public-config");
if (host === "management.azure.com") {
const result = await acquireResourceToken(
config.tenantId,
config.clientId,
"arm",
);
const accessToken = result?.accessToken;
const accessToken = await getAccessToken(config.tenantId, config.clientId, ["arm"]);
if (!accessToken) {
throw new Error("Failed to obtain AzureRM token");
}
@@ -74,7 +71,8 @@ async function getAutoAuthorizationHeader(url: URL): Promise<string | null> {
}
export async function runRestCommand(values: CommandValues): Promise<unknown> {
const method = (values.method ?? "GET").toString().trim().toUpperCase() || "GET";
const method =
(values.method ?? "GET").toString().trim().toUpperCase() || "GET";
const urlValue = (values.url ?? "").toString().trim();
if (!urlValue) {