Merge pull request #4590 from Infisical/ENG-3723

feat(pam): PAM Platform V1
This commit is contained in:
x032205
2025-10-03 15:35:54 -04:00
committed by GitHub
164 changed files with 10032 additions and 209 deletions
@@ -12,6 +12,8 @@ import {
ProjectPermissionIdentityActions,
ProjectPermissionKmipActions,
ProjectPermissionMemberActions,
ProjectPermissionPamAccountActions,
ProjectPermissionPamSessionActions,
ProjectPermissionPkiSubscriberActions,
ProjectPermissionPkiSyncActions,
ProjectPermissionPkiTemplateActions,
@@ -49,7 +51,9 @@ const buildAdminPermissionRules = () => {
ProjectPermissionSub.SshCertificateAuthorities,
ProjectPermissionSub.SshCertificates,
ProjectPermissionSub.SshCertificateTemplates,
ProjectPermissionSub.SshHostGroups
ProjectPermissionSub.SshHostGroups,
ProjectPermissionSub.PamFolders,
ProjectPermissionSub.PamResources
].forEach((el) => {
can(
[
@@ -290,6 +294,19 @@ const buildAdminPermissionRules = () => {
ProjectPermissionSub.AppConnections
);
can(
[
ProjectPermissionPamAccountActions.Access,
ProjectPermissionPamAccountActions.Read,
ProjectPermissionPamAccountActions.Create,
ProjectPermissionPamAccountActions.Edit,
ProjectPermissionPamAccountActions.Delete
],
ProjectPermissionSub.PamAccounts
);
can([ProjectPermissionPamSessionActions.Read], ProjectPermissionSub.PamSessions);
return rules;
};
@@ -518,6 +535,15 @@ const buildMemberPermissionRules = () => {
can(ProjectPermissionAppConnectionActions.Connect, ProjectPermissionSub.AppConnections);
can([ProjectPermissionActions.Read], ProjectPermissionSub.PamFolders);
can([ProjectPermissionActions.Read], ProjectPermissionSub.PamResources);
can(
[ProjectPermissionPamAccountActions.Access, ProjectPermissionPamAccountActions.Read],
ProjectPermissionSub.PamAccounts
);
return rules;
};
@@ -579,6 +605,12 @@ const buildViewerPermissionRules = () => {
ProjectPermissionSub.SecretEvents
);
can([ProjectPermissionActions.Read], ProjectPermissionSub.PamFolders);
can([ProjectPermissionActions.Read], ProjectPermissionSub.PamResources);
can([ProjectPermissionPamAccountActions.Read], ProjectPermissionSub.PamAccounts);
return rules;
};
@@ -186,6 +186,19 @@ export enum ProjectPermissionAuditLogsActions {
Read = "read"
}
export enum ProjectPermissionPamAccountActions {
Access = "access",
Read = "read",
Create = "create",
Edit = "edit",
Delete = "delete"
}
export enum ProjectPermissionPamSessionActions {
Read = "read"
// Terminate = "terminate"
}
export enum ProjectPermissionSub {
Role = "role",
Member = "member",
@@ -228,7 +241,11 @@ export enum ProjectPermissionSub {
SecretScanningFindings = "secret-scanning-findings",
SecretScanningConfigs = "secret-scanning-configs",
SecretEvents = "secret-events",
AppConnections = "app-connections"
AppConnections = "app-connections",
PamFolders = "pam-folders",
PamResources = "pam-resources",
PamAccounts = "pam-accounts",
PamSessions = "pam-sessions"
}
export type SecretSubjectFields = {
@@ -300,6 +317,12 @@ export type AppConnectionSubjectFields = {
connectionId: string;
};
export type PamAccountSubjectFields = {
resourceName: string;
accountName: string;
accountPath: string;
};
export type ProjectPermissionSet =
| [
ProjectPermissionSecretActions,
@@ -404,7 +427,14 @@ export type ProjectPermissionSet =
| ProjectPermissionSub.AppConnections
| (ForcedSubject<ProjectPermissionSub.AppConnections> & AppConnectionSubjectFields)
)
];
]
| [ProjectPermissionActions, ProjectPermissionSub.PamFolders]
| [ProjectPermissionActions, ProjectPermissionSub.PamResources]
| [
ProjectPermissionPamAccountActions,
ProjectPermissionSub.PamAccounts | (ForcedSubject<ProjectPermissionSub.PamAccounts> & PamAccountSubjectFields)
]
| [ProjectPermissionPamSessionActions, ProjectPermissionSub.PamSessions];
const SECRET_PATH_MISSING_SLASH_ERR_MSG = "Invalid Secret Path; it must start with a '/'";
const SECRET_PATH_PERMISSION_OPERATOR_SCHEMA = z.union([
@@ -427,6 +457,27 @@ const SECRET_PATH_PERMISSION_OPERATOR_SCHEMA = z.union([
})
.partial()
]);
const PAM_ACCOUNT_PATH_MISSING_SLASH_ERR_MSG = "Invalid Secret Path; it must start with a '/'";
const PAM_ACCOUNT_PATH_PERMISSION_OPERATOR_SCHEMA = z.union([
z.string().refine((val) => val.startsWith("/"), SECRET_PATH_MISSING_SLASH_ERR_MSG),
z
.object({
[PermissionConditionOperators.$EQ]: PermissionConditionSchema[PermissionConditionOperators.$EQ].refine(
(val) => val.startsWith("/"),
PAM_ACCOUNT_PATH_MISSING_SLASH_ERR_MSG
),
[PermissionConditionOperators.$NEQ]: PermissionConditionSchema[PermissionConditionOperators.$NEQ].refine(
(val) => val.startsWith("/"),
PAM_ACCOUNT_PATH_MISSING_SLASH_ERR_MSG
),
[PermissionConditionOperators.$IN]: PermissionConditionSchema[PermissionConditionOperators.$IN].refine(
(val) => val.every((el) => el.startsWith("/")),
PAM_ACCOUNT_PATH_MISSING_SLASH_ERR_MSG
),
[PermissionConditionOperators.$GLOB]: PermissionConditionSchema[PermissionConditionOperators.$GLOB]
})
.partial()
]);
// akhilmhdh: don't modify this for v2
// if you want to update create a new schema
const SecretConditionV1Schema = z
@@ -650,6 +701,34 @@ const AppConnectionConditionSchema = z
})
.partial();
const PamAccountConditionSchema = z
.object({
resourceName: z.union([
z.string(),
z
.object({
[PermissionConditionOperators.$EQ]: PermissionConditionSchema[PermissionConditionOperators.$EQ],
[PermissionConditionOperators.$NEQ]: PermissionConditionSchema[PermissionConditionOperators.$NEQ],
[PermissionConditionOperators.$IN]: PermissionConditionSchema[PermissionConditionOperators.$IN],
[PermissionConditionOperators.$GLOB]: PermissionConditionSchema[PermissionConditionOperators.$GLOB]
})
.partial()
]),
accountName: z.union([
z.string(),
z
.object({
[PermissionConditionOperators.$EQ]: PermissionConditionSchema[PermissionConditionOperators.$EQ],
[PermissionConditionOperators.$NEQ]: PermissionConditionSchema[PermissionConditionOperators.$NEQ],
[PermissionConditionOperators.$IN]: PermissionConditionSchema[PermissionConditionOperators.$IN],
[PermissionConditionOperators.$GLOB]: PermissionConditionSchema[PermissionConditionOperators.$GLOB]
})
.partial()
]),
accountPath: PAM_ACCOUNT_PATH_PERMISSION_OPERATOR_SCHEMA
})
.partial();
const GeneralPermissionSchema = [
z.object({
subject: z.literal(ProjectPermissionSub.SecretApproval).describe("The entity this permission pertains to."),
@@ -840,6 +919,34 @@ const GeneralPermissionSchema = [
conditions: AppConnectionConditionSchema.describe(
"When specified, only matching conditions will be allowed to access given resource."
).optional()
}),
z.object({
subject: z.literal(ProjectPermissionSub.PamFolders).describe("The entity this permission pertains to."),
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
"Describe what action an entity can take."
)
}),
z.object({
subject: z.literal(ProjectPermissionSub.PamResources).describe("The entity this permission pertains to."),
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
"Describe what action an entity can take."
)
}),
z.object({
subject: z.literal(ProjectPermissionSub.PamAccounts).describe("The entity this permission pertains to."),
inverted: z.boolean().optional().describe("Whether rule allows or forbids."),
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionPamAccountActions).describe(
"Describe what action an entity can take."
),
conditions: PamAccountConditionSchema.describe(
"When specified, only matching conditions will be allowed to access given resource."
).optional()
}),
z.object({
subject: z.literal(ProjectPermissionSub.PamSessions).describe("The entity this permission pertains to."),
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionPamSessionActions).describe(
"Describe what action an entity can take."
)
})
];