diff --git a/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-fns.ts b/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-fns.ts index 32e2a5459..037df50ac 100644 --- a/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-fns.ts +++ b/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-fns.ts @@ -19,6 +19,8 @@ import { getAzureConnectionAccessToken } from "@app/services/app-connection/azur const GRAPH_API_BASE = "https://graph.microsoft.com/v1.0"; +type AzureErrorResponse = { error: { message: string } }; + const sleep = async () => new Promise((resolve) => { setTimeout(resolve, 1000); @@ -30,7 +32,7 @@ export const azureClientSecretRotationFactory: TRotationFactory< > = (secretRotation, appConnectionDAL, kmsService) => { const { connection, - parameters: { appId, clientId: clientIdParam }, + parameters: { objectId, clientId: clientIdParam }, secretsMapping } = secretRotation; @@ -39,7 +41,7 @@ export const azureClientSecretRotationFactory: TRotationFactory< */ const $rotateClientSecret = async () => { 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 formattedDate = `${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart( @@ -78,8 +80,19 @@ export const azureClientSecretRotationFactory: TRotationFactory< }; } catch (error: unknown) { 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({ - 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({ @@ -93,7 +106,7 @@ export const azureClientSecretRotationFactory: TRotationFactory< */ const revokeCredential = async (keyId: string) => { 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 { await request.post( @@ -108,9 +121,18 @@ export const azureClientSecretRotationFactory: TRotationFactory< ); } catch (error: unknown) { 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({ - message: `Failed to remove client secret with keyId ${keyId} from app ${appId}: ${ - error.message || "Unknown error" + message: `Failed to remove client secret with keyId ${keyId} from app ${objectId}: ${ + message || error.message || "Unknown error" }` }); } diff --git a/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-schemas.ts b/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-schemas.ts index 888dece54..9d98cac49 100644 --- a/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-schemas.ts +++ b/backend/src/ee/services/secret-rotation-v2/azure-client-secret/azure-client-secret-rotation-schemas.ts @@ -21,9 +21,17 @@ export const AzureClientSecretRotationGeneratedCredentialsSchema = z .max(2); 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(), - 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({ diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index f75e13df4..37a3d3679 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -2088,7 +2088,7 @@ export const SecretRotations = { clientId: "The client ID of the Auth0 Application to rotate the client secret for." }, 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.", clientId: "The client ID of the Azure Application to rotate the client secret for." }, diff --git a/docs/documentation/platform/secret-rotation/azure-client-secret.mdx b/docs/documentation/platform/secret-rotation/azure-client-secret.mdx index 6ae7e89e0..046b772f6 100644 --- a/docs/documentation/platform/secret-rotation/azure-client-secret.mdx +++ b/docs/documentation/platform/secret-rotation/azure-client-secret.mdx @@ -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 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) @@ -74,7 +74,7 @@ description: "Learn how to automatically rotate Azure Client Secrets." "minutes": 0 }, "parameters": { - "appId": "...", + "objectId": "...", "clientId": "...", "appName": "..." }, @@ -131,7 +131,7 @@ description: "Learn how to automatically rotate Azure Client Secrets." "lastRotationMessage": null, "type": "azure-client-secret", "parameters": { - "appId": "...", + "objectId": "...", "appName": "...", "clientId": "..." } diff --git a/docs/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png b/docs/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png index 916f0224f..7c040f758 100644 Binary files a/docs/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png and b/docs/images/secret-rotations-v2/azure-client-secret/azure-app-client-id.png differ diff --git a/docs/mint.json b/docs/mint.json index 80e725b6f..010a399bb 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -180,13 +180,11 @@ "pages": [ "documentation/platform/secret-rotation/overview", "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/azure-client-secret", "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" ] }, - { - "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", "pages": [ @@ -904,6 +889,19 @@ "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", "pages": [ diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx index ff77dc1f7..14d350bc2 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx @@ -25,7 +25,7 @@ export const AzureClientSecretRotationParametersFields = () => { return ( ( { <> {parameters.appName} - {parameters.appId} + {parameters.objectId} {clientId} diff --git a/frontend/src/components/secret-rotations-v2/forms/schemas/azure-client-secret-rotation-schema.ts b/frontend/src/components/secret-rotations-v2/forms/schemas/azure-client-secret-rotation-schema.ts index c68afb0ed..3db113003 100644 --- a/frontend/src/components/secret-rotations-v2/forms/schemas/azure-client-secret-rotation-schema.ts +++ b/frontend/src/components/secret-rotations-v2/forms/schemas/azure-client-secret-rotation-schema.ts @@ -7,7 +7,7 @@ export const AzureClientSecretRotationSchema = z .object({ type: z.literal(SecretRotation.AzureClientSecret), 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"), clientId: z.string().trim().min(1, "Client ID required") }), diff --git a/frontend/src/hooks/api/secretRotationsV2/types/azure-client-secret-rotation.ts b/frontend/src/hooks/api/secretRotationsV2/types/azure-client-secret-rotation.ts index 09af2b85d..d4e06d45b 100644 --- a/frontend/src/hooks/api/secretRotationsV2/types/azure-client-secret-rotation.ts +++ b/frontend/src/hooks/api/secretRotationsV2/types/azure-client-secret-rotation.ts @@ -8,7 +8,7 @@ import { export type TAzureClientSecretRotation = TSecretRotationV2Base & { type: SecretRotation.AzureClientSecret; parameters: { - appId: string; + objectId: string; appName: string; }; secretsMapping: {