Improve error propagation and change appId to objectId to match azure

This commit is contained in:
carlosmonastyrski
2025-04-30 20:06:13 -03:00
parent a01a9f3f77
commit d161be1170
10 changed files with 62 additions and 34 deletions
@@ -19,6 +19,8 @@ import { getAzureConnectionAccessToken } from "@app/services/app-connection/azur
const GRAPH_API_BASE = "https://graph.microsoft.com/v1.0"; const GRAPH_API_BASE = "https://graph.microsoft.com/v1.0";
type AzureErrorResponse = { error: { message: string } };
const sleep = async () => const sleep = async () =>
new Promise((resolve) => { new Promise((resolve) => {
setTimeout(resolve, 1000); setTimeout(resolve, 1000);
@@ -30,7 +32,7 @@ export const azureClientSecretRotationFactory: TRotationFactory<
> = (secretRotation, appConnectionDAL, kmsService) => { > = (secretRotation, appConnectionDAL, kmsService) => {
const { const {
connection, connection,
parameters: { appId, clientId: clientIdParam }, parameters: { objectId, clientId: clientIdParam },
secretsMapping secretsMapping
} = secretRotation; } = secretRotation;
@@ -39,7 +41,7 @@ export const azureClientSecretRotationFactory: TRotationFactory<
*/ */
const $rotateClientSecret = async () => { const $rotateClientSecret = async () => {
const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService); const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService);
const endpoint = `${GRAPH_API_BASE}/applications/${appId}/addPassword`; const endpoint = `${GRAPH_API_BASE}/applications/${objectId}/addPassword`;
const now = new Date(); const now = new Date();
const formattedDate = `${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart( const formattedDate = `${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(
@@ -78,8 +80,19 @@ export const azureClientSecretRotationFactory: TRotationFactory<
}; };
} catch (error: unknown) { } catch (error: unknown) {
if (error instanceof AxiosError) { if (error instanceof AxiosError) {
let message;
if (
error.response?.data &&
typeof error.response.data === "object" &&
"error" in error.response.data &&
typeof (error.response.data as AzureErrorResponse).error.message === "string"
) {
message = (error.response.data as AzureErrorResponse).error.message;
}
throw new BadRequestError({ throw new BadRequestError({
message: `Failed to add client secret to Azure app ${appId}: ${error.message || "Unknown error"}` message: `Failed to add client secret to Azure app ${objectId}: ${
message || error.message || "Unknown error"
}`
}); });
} }
throw new BadRequestError({ throw new BadRequestError({
@@ -93,7 +106,7 @@ export const azureClientSecretRotationFactory: TRotationFactory<
*/ */
const revokeCredential = async (keyId: string) => { const revokeCredential = async (keyId: string) => {
const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService); const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService);
const endpoint = `${GRAPH_API_BASE}/applications/${appId}/removePassword`; const endpoint = `${GRAPH_API_BASE}/applications/${objectId}/removePassword`;
try { try {
await request.post( await request.post(
@@ -108,9 +121,18 @@ export const azureClientSecretRotationFactory: TRotationFactory<
); );
} catch (error: unknown) { } catch (error: unknown) {
if (error instanceof AxiosError) { if (error instanceof AxiosError) {
let message;
if (
error.response?.data &&
typeof error.response.data === "object" &&
"error" in error.response.data &&
typeof (error.response.data as AzureErrorResponse).error.message === "string"
) {
message = (error.response.data as AzureErrorResponse).error.message;
}
throw new BadRequestError({ throw new BadRequestError({
message: `Failed to remove client secret with keyId ${keyId} from app ${appId}: ${ message: `Failed to remove client secret with keyId ${keyId} from app ${objectId}: ${
error.message || "Unknown error" message || error.message || "Unknown error"
}` }`
}); });
} }
@@ -21,9 +21,17 @@ export const AzureClientSecretRotationGeneratedCredentialsSchema = z
.max(2); .max(2);
const AzureClientSecretRotationParametersSchema = z.object({ const AzureClientSecretRotationParametersSchema = z.object({
appId: z.string().trim().min(1, "App ID Required").describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appId), objectId: z
.string()
.trim()
.min(1, "Object ID Required")
.describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.objectId),
appName: z.string().trim().describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appName).optional(), appName: z.string().trim().describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appName).optional(),
clientId: z.string().trim().describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.clientId) clientId: z
.string()
.trim()
.min(1, "Client ID Required")
.describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.clientId)
}); });
const AzureClientSecretRotationSecretsMappingSchema = z.object({ const AzureClientSecretRotationSecretsMappingSchema = z.object({
+1 -1
View File
@@ -2088,7 +2088,7 @@ export const SecretRotations = {
clientId: "The client ID of the Auth0 Application to rotate the client secret for." clientId: "The client ID of the Auth0 Application to rotate the client secret for."
}, },
AZURE_CLIENT_SECRET: { AZURE_CLIENT_SECRET: {
appId: "The ID of the Azure Application to rotate the client secret for.", objectId: "The ID of the Azure Application to rotate the client secret for.",
appName: "The name of the Azure Application to rotate the client secret for.", appName: "The name of the Azure Application to rotate the client secret for.",
clientId: "The client ID of the Azure Application to rotate the client secret for." clientId: "The client ID of the Azure Application to rotate the client secret for."
}, },
@@ -50,7 +50,7 @@ description: "Learn how to automatically rotate Azure Client Secrets."
To create an Azure Client Secret Rotation, make an API request to the [Create Azure To create an Azure Client Secret Rotation, make an API request to the [Create Azure
Client Secret Rotation](/api-reference/endpoints/secret-rotations/azure-client-secret/create) API endpoint. Client Secret Rotation](/api-reference/endpoints/secret-rotations/azure-client-secret/create) API endpoint.
You will first need the **Client ID** of the Azure application you want to rotate the secret for. This can be obtained from the Applications dashboard. You will first need the **Client ID** and **Object ID** of the Azure application you want to rotate the secret for. This can be obtained from the Applications dashboard.
![Azure Client ID](/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png) ![Azure Client ID](/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png)
@@ -74,7 +74,7 @@ description: "Learn how to automatically rotate Azure Client Secrets."
"minutes": 0 "minutes": 0
}, },
"parameters": { "parameters": {
"appId": "...", "objectId": "...",
"clientId": "...", "clientId": "...",
"appName": "..." "appName": "..."
}, },
@@ -131,7 +131,7 @@ description: "Learn how to automatically rotate Azure Client Secrets."
"lastRotationMessage": null, "lastRotationMessage": null,
"type": "azure-client-secret", "type": "azure-client-secret",
"parameters": { "parameters": {
"appId": "...", "objectId": "...",
"appName": "...", "appName": "...",
"clientId": "..." "clientId": "..."
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 576 KiB

After

Width:  |  Height:  |  Size: 259 KiB

+16 -18
View File
@@ -180,13 +180,11 @@
"pages": [ "pages": [
"documentation/platform/secret-rotation/overview", "documentation/platform/secret-rotation/overview",
"documentation/platform/secret-rotation/auth0-client-secret", "documentation/platform/secret-rotation/auth0-client-secret",
"documentation/platform/secret-rotation/azure-client-secret",
"documentation/platform/secret-rotation/postgres-credentials",
"documentation/platform/secret-rotation/mssql-credentials",
"documentation/platform/secret-rotation/aws-iam-user-secret", "documentation/platform/secret-rotation/aws-iam-user-secret",
"documentation/platform/secret-rotation/azure-client-secret",
"documentation/platform/secret-rotation/ldap-password", "documentation/platform/secret-rotation/ldap-password",
"documentation/platform/secret-rotation/mssql-credentials", "documentation/platform/secret-rotation/postgres-credentials",
"documentation/platform/secret-rotation/postgres-credentials" "documentation/platform/secret-rotation/mssql-credentials"
] ]
}, },
{ {
@@ -878,19 +876,6 @@
"api-reference/endpoints/secret-rotations/auth0-client-secret/update" "api-reference/endpoints/secret-rotations/auth0-client-secret/update"
] ]
}, },
{
"group": "Azure Client Secret",
"pages": [
"api-reference/endpoints/secret-rotations/azure-client-secret/create",
"api-reference/endpoints/secret-rotations/azure-client-secret/delete",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-by-id",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-by-name",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-generated-credentials-by-id",
"api-reference/endpoints/secret-rotations/azure-client-secret/list",
"api-reference/endpoints/secret-rotations/azure-client-secret/rotate-secrets",
"api-reference/endpoints/secret-rotations/azure-client-secret/update"
]
},
{ {
"group": "AWS IAM User Secret", "group": "AWS IAM User Secret",
"pages": [ "pages": [
@@ -904,6 +889,19 @@
"api-reference/endpoints/secret-rotations/aws-iam-user-secret/update" "api-reference/endpoints/secret-rotations/aws-iam-user-secret/update"
] ]
}, },
{
"group": "Azure Client Secret",
"pages": [
"api-reference/endpoints/secret-rotations/azure-client-secret/create",
"api-reference/endpoints/secret-rotations/azure-client-secret/delete",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-by-id",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-by-name",
"api-reference/endpoints/secret-rotations/azure-client-secret/get-generated-credentials-by-id",
"api-reference/endpoints/secret-rotations/azure-client-secret/list",
"api-reference/endpoints/secret-rotations/azure-client-secret/rotate-secrets",
"api-reference/endpoints/secret-rotations/azure-client-secret/update"
]
},
{ {
"group": "LDAP Password", "group": "LDAP Password",
"pages": [ "pages": [
@@ -25,7 +25,7 @@ export const AzureClientSecretRotationParametersFields = () => {
return ( return (
<Controller <Controller
name="parameters.appId" name="parameters.objectId"
control={control} control={control}
render={({ field: { value, onChange }, fieldState: { error } }) => ( render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl <FormControl
@@ -19,7 +19,7 @@ export const AzureClientSecretRotationReviewFields = () => {
<> <>
<SecretRotationReviewSection label="Parameters"> <SecretRotationReviewSection label="Parameters">
<GenericFieldLabel label="App Name">{parameters.appName}</GenericFieldLabel> <GenericFieldLabel label="App Name">{parameters.appName}</GenericFieldLabel>
<GenericFieldLabel label="App ID">{parameters.appId}</GenericFieldLabel> <GenericFieldLabel label="App ID">{parameters.objectId}</GenericFieldLabel>
</SecretRotationReviewSection> </SecretRotationReviewSection>
<SecretRotationReviewSection label="Secrets Mapping"> <SecretRotationReviewSection label="Secrets Mapping">
<GenericFieldLabel label="Client ID">{clientId}</GenericFieldLabel> <GenericFieldLabel label="Client ID">{clientId}</GenericFieldLabel>
@@ -7,7 +7,7 @@ export const AzureClientSecretRotationSchema = z
.object({ .object({
type: z.literal(SecretRotation.AzureClientSecret), type: z.literal(SecretRotation.AzureClientSecret),
parameters: z.object({ parameters: z.object({
appId: z.string().trim().min(1, "App ID required"), objectId: z.string().trim().min(1, "Object ID required"),
appName: z.string().trim().min(1, "App Name required"), appName: z.string().trim().min(1, "App Name required"),
clientId: z.string().trim().min(1, "Client ID required") clientId: z.string().trim().min(1, "Client ID required")
}), }),
@@ -8,7 +8,7 @@ import {
export type TAzureClientSecretRotation = TSecretRotationV2Base & { export type TAzureClientSecretRotation = TSecretRotationV2Base & {
type: SecretRotation.AzureClientSecret; type: SecretRotation.AzureClientSecret;
parameters: { parameters: {
appId: string; objectId: string;
appName: string; appName: string;
}; };
secretsMapping: { secretsMapping: {