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 5d0b7b109..7363e18b2 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
@@ -1,3 +1,5 @@
+import { AxiosError } from "axios";
+
import {
AzureAddPasswordResponse,
TAzureClientSecretRotationGeneratedCredentials,
@@ -11,7 +13,7 @@ import {
TRotationFactoryRotateCredentials
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
import { request } from "@app/lib/config/request";
-import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
+import { BadRequestError } from "@app/lib/errors";
import { getAzureConnectionAccessToken } from "@app/services/app-connection/azure-client-secrets";
const GRAPH_API_BASE = "https://graph.microsoft.com/v1.0";
@@ -23,8 +25,7 @@ export const azureClientSecretRotationFactory: TRotationFactory<
const {
connection,
parameters: { appId },
- secretsMapping,
- rotationInterval
+ secretsMapping
} = secretRotation;
/**
@@ -34,11 +35,6 @@ export const azureClientSecretRotationFactory: TRotationFactory<
const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService);
const endpoint = `${GRAPH_API_BASE}/applications/${appId}/addPassword`;
- await blockLocalAndPrivateIpAddresses(endpoint);
-
- const endDateTime = new Date();
- endDateTime.setDate(endDateTime.getDate() + rotationInterval);
-
const now = new Date();
const formattedDate = `${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(
2,
@@ -50,8 +46,7 @@ export const azureClientSecretRotationFactory: TRotationFactory<
endpoint,
{
passwordCredential: {
- displayName: `Infisical Rotated Secret (${formattedDate})`,
- endDateTime: endDateTime.toISOString()
+ displayName: `Infisical Rotated Secret (${formattedDate})`
}
},
{
@@ -70,9 +65,15 @@ export const azureClientSecretRotationFactory: TRotationFactory<
clientSecret: data.secretText,
clientId: data.keyId
};
- } catch (err: unknown) {
- const message = err instanceof Error ? err.message : String(err);
- throw new Error(`Failed to add client secret to Azure app ${appId}: ${message}`);
+ } catch (error: unknown) {
+ if (error instanceof AxiosError) {
+ throw new BadRequestError({
+ message: `Failed to add client secret to Azure app ${appId}: ${error.message || "Unknown error"}`
+ });
+ }
+ throw new BadRequestError({
+ message: "Unable to validate connection: verify credentials"
+ });
}
};
@@ -83,8 +84,6 @@ export const azureClientSecretRotationFactory: TRotationFactory<
const accessToken = await getAzureConnectionAccessToken(connection.id, appConnectionDAL, kmsService);
const endpoint = `${GRAPH_API_BASE}/applications/${appId}/removePassword`;
- await blockLocalAndPrivateIpAddresses(endpoint);
-
try {
await request.post(
endpoint,
@@ -96,9 +95,17 @@ export const azureClientSecretRotationFactory: TRotationFactory<
}
}
);
- } catch (err: unknown) {
- const message = err instanceof Error ? err.message : String(err);
- throw new Error(`Failed to remove client secret with keyId ${clientId} from app ${appId}: ${message}`);
+ } catch (error: unknown) {
+ if (error instanceof AxiosError) {
+ throw new BadRequestError({
+ message: `Failed to remove client secret with keyId ${clientId} from app ${appId}: ${
+ error.message || "Unknown error"
+ }`
+ });
+ }
+ throw new BadRequestError({
+ message: "Unable to validate connection: verify credentials"
+ });
}
};
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 af5448467..b8a313a86 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,11 +21,7 @@ export const AzureClientSecretRotationGeneratedCredentialsSchema = z
const AzureClientSecretRotationParametersSchema = z.object({
appId: z.string().trim().min(1, "App ID Required").describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appId),
- appName: z
- .string()
- .trim()
- .min(1, "App Name Required")
- .describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appName)
+ appName: z.string().trim().describe(SecretRotations.PARAMETERS.AZURE_CLIENT_SECRET.appName).optional()
});
const AzureClientSecretRotationSecretsMappingSchema = z.object({
diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts
index b8ea6bf7e..9a5f1a48f 100644
--- a/backend/src/lib/api-docs/constants.ts
+++ b/backend/src/lib/api-docs/constants.ts
@@ -1875,6 +1875,10 @@ export const AppConnections = {
TEAMCITY: {
instanceUrl: "The TeamCity instance URL to connect with.",
accessToken: "The access token to use to connect with TeamCity."
+ },
+ AZURE_CLIENT_SECRETS: {
+ code: "The OAuth code to use to connect with Azure Client Secrets.",
+ tenantId: "The Tenant ID to use to connect with Azure Client Secrets."
}
}
};
diff --git a/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-connection-schemas.ts b/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-connection-schemas.ts
index 962125b5a..2b4e65a13 100644
--- a/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-connection-schemas.ts
+++ b/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-connection-schemas.ts
@@ -11,12 +11,16 @@ import {
import { AzureClientSecretsConnectionMethod } from "./azure-client-secrets-connection-enums";
export const AzureClientSecretsConnectionOAuthInputCredentialsSchema = z.object({
- code: z.string().trim().min(1, "OAuth code required"),
- tenantId: z.string().trim().optional()
+ code: z.string().trim().min(1, "OAuth code required").describe(AppConnections.CREDENTIALS.AZURE_CLIENT_SECRETS.code),
+ tenantId: z
+ .string()
+ .trim()
+ .min(1, "Tenant ID required")
+ .describe(AppConnections.CREDENTIALS.AZURE_CLIENT_SECRETS.tenantId)
});
export const AzureClientSecretsConnectionOAuthOutputCredentialsSchema = z.object({
- tenantId: z.string().optional(),
+ tenantId: z.string(),
accessToken: z.string(),
refreshToken: z.string(),
expiresAt: z.number()
diff --git a/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-service.ts b/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-service.ts
index e95178973..336c48d58 100644
--- a/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-service.ts
+++ b/backend/src/services/app-connection/azure-client-secrets/azure-client-secrets-service.ts
@@ -1,6 +1,5 @@
import { request } from "@app/lib/config/request";
import { OrgServiceActor } from "@app/lib/types";
-import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
import { TAppConnectionDALFactory } from "@app/services/app-connection/app-connection-dal";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { getAzureConnectionAccessToken } from "@app/services/app-connection/azure-client-secrets/azure-client-secrets-connection-fns";
@@ -26,7 +25,6 @@ const listAzureRegisteredApps = async (
const accessToken = await getAzureConnectionAccessToken(appConnection.id, appConnectionDAL, kmsService);
const graphEndpoint = `https://graph.microsoft.com/v1.0/applications`;
- await blockLocalAndPrivateIpAddresses(graphEndpoint);
const apps: TAzureRegisteredApp[] = [];
let nextLink = graphEndpoint;
diff --git a/docs/api-reference/endpoints/app-connections/azure-client-secret/create.mdx b/docs/api-reference/endpoints/app-connections/azure-client-secret/create.mdx
index 16a384949..c1c6bd6a8 100644
--- a/docs/api-reference/endpoints/app-connections/azure-client-secret/create.mdx
+++ b/docs/api-reference/endpoints/app-connections/azure-client-secret/create.mdx
@@ -4,6 +4,7 @@ openapi: "POST /api/v1/app-connections/azure-client-secrets"
---
- Check out the configuration docs for [Azure Client Secret Connections](/integrations/app-connections/azure-client-secrets) to learn how to obtain the
- required credentials.
+ Azure Client Secret Connections must be created through the Infisical UI.
+ Check out the configuration docs for [Azure Client Secret Connections](/integrations/app-connections/azure-client-secrets) for a step-by-step
+ guide.
\ No newline at end of file
diff --git a/docs/api-reference/endpoints/app-connections/azure-client-secret/update.mdx b/docs/api-reference/endpoints/app-connections/azure-client-secret/update.mdx
index 05248e5f1..f60993285 100644
--- a/docs/api-reference/endpoints/app-connections/azure-client-secret/update.mdx
+++ b/docs/api-reference/endpoints/app-connections/azure-client-secret/update.mdx
@@ -4,6 +4,7 @@ openapi: "PATCH /api/v1/app-connections/azure-client-secrets/{connectionId}"
---
- Check out the configuration docs for [Azure Client Secret Connections](/integrations/app-connections/azure-client-secrets) to learn how to obtain the
- required credentials.
-
\ No newline at end of file
+ Azure Client Secret Connections must be updated through the Infisical UI.
+ Check out the configuration docs for [Azure Client Secret Connections](/integrations/app-connections/azure-client-secrets) for a step-by-step
+ guide.
+
diff --git a/docs/documentation/platform/secret-rotation/azure-client-secret.mdx b/docs/documentation/platform/secret-rotation/azure-client-secret.mdx
index 4997e80d0..d377e0667 100644
--- a/docs/documentation/platform/secret-rotation/azure-client-secret.mdx
+++ b/docs/documentation/platform/secret-rotation/azure-client-secret.mdx
@@ -5,7 +5,7 @@ description: "Learn how to automatically rotate Azure Client Secrets."
## Prerequisites
-- Create an [Azure Client Secret Connection](/integrations/app-connections/azure-client-secrets) with the required **Secret Rotation** audience and permissions
+- Create an [Azure Client Secret Connection](/integrations/app-connections/azure-client-secrets).
## Create an Azure Client Secret Rotation in Infisical
diff --git a/docs/images/app-connections/azure/client-secrets/config-credentials-1.png b/docs/images/app-connections/azure/client-secrets/config-credentials-1.png
new file mode 100644
index 000000000..954f8aeb9
Binary files /dev/null and b/docs/images/app-connections/azure/client-secrets/config-credentials-1.png differ
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 488263071..916f0224f 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/integrations/app-connections/azure-client-secrets.mdx b/docs/integrations/app-connections/azure-client-secrets.mdx
index 61749d64d..7e50348d2 100644
--- a/docs/integrations/app-connections/azure-client-secrets.mdx
+++ b/docs/integrations/app-connections/azure-client-secrets.mdx
@@ -42,9 +42,9 @@ Infisical currently only supports one method for connecting to Azure, which is O
- Obtain the **Application (Client) ID** in Overview and generate a **Client Secret** in Certificate & secrets for your Azure application.
+ Obtain the **Application (Client) ID** and **Directory (Tenant) ID** in Overview and generate a **Client Secret** in Certificate & secrets for your Azure application.
- 
+ 


diff --git a/docs/mint.json b/docs/mint.json
index 9753d6a68..80e725b6f 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -433,8 +433,8 @@
"integrations/app-connections/auth0",
"integrations/app-connections/aws",
"integrations/app-connections/azure-app-configuration",
- "integrations/app-connections/azure-key-vault",
"integrations/app-connections/azure-client-secrets",
+ "integrations/app-connections/azure-key-vault",
"integrations/app-connections/camunda",
"integrations/app-connections/databricks",
"integrations/app-connections/gcp",
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 ceee60dec..982e2a392 100644
--- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx
+++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AzureClientSecretRotationParametersFields.tsx
@@ -38,8 +38,8 @@ export const AzureClientSecretRotationParametersFields = () => {
content={
<>
Ensure that your connection has the{" "}
- read_clients permission and the application
- exists in the connection's audience.
+ Application.ReadWrite.All permission and
+ the application exists in Azure.
>
}
>
diff --git a/frontend/src/helpers/secretRotationsV2.ts b/frontend/src/helpers/secretRotationsV2.ts
index fd96e5a83..451658135 100644
--- a/frontend/src/helpers/secretRotationsV2.ts
+++ b/frontend/src/helpers/secretRotationsV2.ts
@@ -23,7 +23,7 @@ export const SECRET_ROTATION_MAP: Record<
[SecretRotation.AzureClientSecret]: {
name: "Azure Client Secret",
image: "Microsoft Azure.png",
- size: 35
+ size: 65
},
[SecretRotation.LdapPassword]: {
name: "LDAP Password",
diff --git a/frontend/src/hooks/api/appConnections/types/azure-client-secrets-connection.ts b/frontend/src/hooks/api/appConnections/types/azure-client-secrets-connection.ts
index a7587d3ff..04ad167d2 100644
--- a/frontend/src/hooks/api/appConnections/types/azure-client-secrets-connection.ts
+++ b/frontend/src/hooks/api/appConnections/types/azure-client-secrets-connection.ts
@@ -11,6 +11,6 @@ export type TAzureClientSecretsConnection = TRootAppConnection & {
method: AzureClientSecretsConnectionMethod.OAuth;
credentials: {
code: string;
- tenantId?: string;
+ tenantId: string;
};
};
diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AzureClientSecretsConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AzureClientSecretsConnectionForm.tsx
index 8af319fc7..4b7071f61 100644
--- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AzureClientSecretsConnectionForm.tsx
+++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AzureClientSecretsConnectionForm.tsx
@@ -27,7 +27,7 @@ type Props = {
const formSchema = genericAppConnectionFieldsSchema.extend({
app: z.literal(AppConnection.AzureClientSecrets),
method: z.nativeEnum(AzureClientSecretsConnectionMethod),
- tenantId: z.string().trim().optional()
+ tenantId: z.string().trim()
});
type FormData = z.infer;
@@ -97,10 +97,9 @@ export const AzureClientSecretsConnectionForm = ({ appConnection }: Props) => {
control={control}
render={({ field, fieldState: { error } }) => (