mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: added validation against confused deputy
This commit is contained in:
@@ -146,6 +146,18 @@ export const getGcpSecretManagerProjects = async (appConnection: TGcpConnection)
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const validateGcpConnectionCredentials = async (appConnection: TGcpConnectionConfig) => {
|
export const validateGcpConnectionCredentials = async (appConnection: TGcpConnectionConfig) => {
|
||||||
|
// Check if provided service account email prefix matches organization ID.
|
||||||
|
// We do this to mitigate confused deputy attacks in multi-tenant instances
|
||||||
|
const expectedEmailPrefix = appConnection.orgId.split("-").slice(0, 2).join("-");
|
||||||
|
if (
|
||||||
|
appConnection.credentials.serviceAccountEmail &&
|
||||||
|
!appConnection.credentials.serviceAccountEmail.startsWith(expectedEmailPrefix)
|
||||||
|
) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `GCP service account email must have a prefix of "${expectedEmailPrefix}"`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await getAuthToken(appConnection);
|
await getAuthToken(appConnection);
|
||||||
|
|
||||||
return appConnection.credentials;
|
return appConnection.credentials;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import { GcpConnectionMethod } from "./gcp-connection-enums";
|
import { GcpConnectionMethod } from "./gcp-connection-enums";
|
||||||
|
|
||||||
export const GcpConnectionServiceAccountImpersonationCredentialsSchema = z.object({
|
export const GcpConnectionServiceAccountImpersonationCredentialsSchema = z.object({
|
||||||
serviceAccountEmail: z.string().trim().min(1, "Service account email required")
|
serviceAccountEmail: z.string().email().trim().min(1, "Service account email required")
|
||||||
});
|
});
|
||||||
|
|
||||||
const BaseGcpConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.GCP) });
|
const BaseGcpConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.GCP) });
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
SelectItem
|
SelectItem
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
|
import { useOrganization } from "@app/context";
|
||||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||||
import { GcpConnectionMethod, TGcpConnection } from "@app/hooks/api/appConnections";
|
import { GcpConnectionMethod, TGcpConnection } from "@app/hooks/api/appConnections";
|
||||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||||
@@ -32,7 +33,7 @@ const formSchema = z.discriminatedUnion("method", [
|
|||||||
rootSchema.extend({
|
rootSchema.extend({
|
||||||
method: z.literal(GcpConnectionMethod.ServiceAccountImpersonation),
|
method: z.literal(GcpConnectionMethod.ServiceAccountImpersonation),
|
||||||
credentials: z.object({
|
credentials: z.object({
|
||||||
serviceAccountEmail: z.string().trim().min(1, "Service account email required")
|
serviceAccountEmail: z.string().email().trim().min(1, "Service account email required")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
@@ -49,6 +50,7 @@ export const GcpConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
|||||||
method: GcpConnectionMethod.ServiceAccountImpersonation
|
method: GcpConnectionMethod.ServiceAccountImpersonation
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -101,6 +103,7 @@ export const GcpConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
|||||||
isError={Boolean(error?.message)}
|
isError={Boolean(error?.message)}
|
||||||
label="Service Account Email"
|
label="Service Account Email"
|
||||||
className="group"
|
className="group"
|
||||||
|
helperText={`Service account email must be prefixed with "${currentOrg.id.split("-").slice(0, 2).join("-")}".`}
|
||||||
>
|
>
|
||||||
<SecretInput
|
<SecretInput
|
||||||
containerClassName="text-gray-400 group-focus-within:!border-primary-400/50 border border-mineshaft-500 bg-mineshaft-900 px-2.5 py-1.5"
|
containerClassName="text-gray-400 group-focus-within:!border-primary-400/50 border border-mineshaft-500 bg-mineshaft-900 px-2.5 py-1.5"
|
||||||
|
|||||||
Reference in New Issue
Block a user