Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
284024d
Add k8s stuff
fangpenlin Dec 3, 2025
e12f30c
Connect k8s
fangpenlin Dec 3, 2025
5ac4e0a
Fix adding res and add missing forms
fangpenlin Dec 3, 2025
2140956
Fix account creation, remove rotation stuff for now
fangpenlin Dec 3, 2025
e62705a
Add missing k8s stuff
fangpenlin Dec 3, 2025
02babcb
Fix ssl stuff
fangpenlin Dec 3, 2025
c1d537c
Adjust ui
fangpenlin Dec 3, 2025
8d2f308
Remove unused stuff
fangpenlin Dec 3, 2025
47da427
Fix form
fangpenlin Dec 3, 2025
30b4514
Fix sa validation without ns
fangpenlin Dec 4, 2025
73f2c2b
Add http events
fangpenlin Dec 4, 2025
5b97f5a
Fix log format
fangpenlin Dec 4, 2025
b98e9e7
Add HTTP event view
fangpenlin Dec 4, 2025
f5d2920
Provide metadata for k8s pam
fangpenlin Dec 4, 2025
43525b5
Update http view
fangpenlin Dec 4, 2025
7a9374c
Handle body
fangpenlin Dec 4, 2025
4475457
Display body
fangpenlin Dec 4, 2025
96c077b
Update UI
fangpenlin Dec 5, 2025
2c1aaf0
Update UI
fangpenlin Dec 5, 2025
59201ed
Fix access cmd
fangpenlin Dec 5, 2025
1818edc
Fix ts type linter
fangpenlin Dec 5, 2025
344d0ef
Fix type linter
fangpenlin Dec 5, 2025
51f7b97
Fix linter issues
fangpenlin Dec 5, 2025
2afd765
Fix linters
fangpenlin Dec 5, 2025
76c3245
Throw error for k8s rotation
fangpenlin Dec 5, 2025
43cfcca
Lint frontend
fangpenlin Dec 5, 2025
10faea4
Fix ts type check
fangpenlin Dec 5, 2025
45350a6
ts linter
fangpenlin Dec 5, 2025
ff9644a
misc: added sni
sheensantoscapadngan Dec 10, 2025
4e1cb7e
misc: used kube auth whoami
sheensantoscapadngan Dec 10, 2025
178989d
Merge remote-tracking branch 'origin/main' into PAM-12-add-k8s-for-pam
sheensantoscapadngan Dec 10, 2025
d1d435d
misc: address backend lint
sheensantoscapadngan Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions backend/src/ee/routes/v1/pam-account-routers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import {
SanitizedAwsIamAccountWithResourceSchema,
UpdateAwsIamAccountSchema
} from "@app/ee/services/pam-resource/aws-iam/aws-iam-resource-schemas";
import {
CreateKubernetesAccountSchema,
SanitizedKubernetesAccountWithResourceSchema,
UpdateKubernetesAccountSchema
} from "@app/ee/services/pam-resource/kubernetes/kubernetes-resource-schemas";
import {
CreateMySQLAccountSchema,
SanitizedMySQLAccountWithResourceSchema,
Expand Down Expand Up @@ -50,6 +55,15 @@ export const PAM_ACCOUNT_REGISTER_ROUTER_MAP: Record<PamResource, (server: Fasti
updateAccountSchema: UpdateSSHAccountSchema
});
},
[PamResource.Kubernetes]: async (server: FastifyZodProvider) => {
registerPamResourceEndpoints({
server,
resourceType: PamResource.Kubernetes,
accountResponseSchema: SanitizedKubernetesAccountWithResourceSchema,
createAccountSchema: CreateKubernetesAccountSchema,
updateAccountSchema: UpdateKubernetesAccountSchema
});
},
[PamResource.AwsIam]: async (server: FastifyZodProvider) => {
registerPamResourceEndpoints({
server,
Expand Down
21 changes: 12 additions & 9 deletions backend/src/ee/routes/v1/pam-account-routers/pam-account-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PamFoldersSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PamAccountOrderBy, PamAccountView } from "@app/ee/services/pam-account/pam-account-enums";
import { SanitizedAwsIamAccountWithResourceSchema } from "@app/ee/services/pam-resource/aws-iam/aws-iam-resource-schemas";
import { SanitizedKubernetesAccountWithResourceSchema } from "@app/ee/services/pam-resource/kubernetes/kubernetes-resource-schemas";
import { SanitizedMySQLAccountWithResourceSchema } from "@app/ee/services/pam-resource/mysql/mysql-resource-schemas";
import { PamResource } from "@app/ee/services/pam-resource/pam-resource-enums";
import { GatewayAccessResponseSchema } from "@app/ee/services/pam-resource/pam-resource-schemas";
Expand All @@ -21,10 +22,17 @@ const SanitizedAccountSchema = z.union([
SanitizedSSHAccountWithResourceSchema, // ORDER MATTERS
SanitizedPostgresAccountWithResourceSchema,
SanitizedMySQLAccountWithResourceSchema,
SanitizedKubernetesAccountWithResourceSchema,
SanitizedAwsIamAccountWithResourceSchema
]);

type TSanitizedAccount = z.infer<typeof SanitizedAccountSchema>;
const ListPamAccountsResponseSchema = z.object({
accounts: SanitizedAccountSchema.array(),
folders: PamFoldersSchema.array(),
totalCount: z.number().default(0),
folderId: z.string().optional(),
folderPaths: z.record(z.string(), z.string())
});

export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
server.route({
Expand Down Expand Up @@ -55,13 +63,7 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
.optional()
}),
response: {
200: z.object({
accounts: SanitizedAccountSchema.array(),
folders: PamFoldersSchema.array(),
totalCount: z.number().default(0),
folderId: z.string().optional(),
folderPaths: z.record(z.string(), z.string())
})
200: ListPamAccountsResponseSchema
}
},
onRequest: verifyAuth([AuthMode.JWT]),
Expand Down Expand Up @@ -98,7 +100,7 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
}
});

return { accounts: accounts as TSanitizedAccount[], folders, totalCount, folderId, folderPaths };
return { accounts, folders, totalCount, folderId, folderPaths } as z.infer<typeof ListPamAccountsResponseSchema>;
}
});

Expand Down Expand Up @@ -135,6 +137,7 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
GatewayAccessResponseSchema.extend({ resourceType: z.literal(PamResource.Postgres) }),
GatewayAccessResponseSchema.extend({ resourceType: z.literal(PamResource.MySQL) }),
GatewayAccessResponseSchema.extend({ resourceType: z.literal(PamResource.SSH) }),
GatewayAccessResponseSchema.extend({ resourceType: z.literal(PamResource.Kubernetes) }),
// AWS IAM (no gateway, returns console URL)
z.object({
sessionId: z.string(),
Expand Down
14 changes: 14 additions & 0 deletions backend/src/ee/routes/v1/pam-resource-routers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import {
SanitizedAwsIamResourceSchema,
UpdateAwsIamResourceSchema
} from "@app/ee/services/pam-resource/aws-iam/aws-iam-resource-schemas";
import {
CreateKubernetesResourceSchema,
SanitizedKubernetesResourceSchema,
UpdateKubernetesResourceSchema
} from "@app/ee/services/pam-resource/kubernetes/kubernetes-resource-schemas";
import {
CreateMySQLResourceSchema,
MySQLResourceSchema,
Expand Down Expand Up @@ -50,6 +55,15 @@ export const PAM_RESOURCE_REGISTER_ROUTER_MAP: Record<PamResource, (server: Fast
updateResourceSchema: UpdateSSHResourceSchema
});
},
[PamResource.Kubernetes]: async (server: FastifyZodProvider) => {
registerPamResourceEndpoints({
server,
resourceType: PamResource.Kubernetes,
resourceResponseSchema: SanitizedKubernetesResourceSchema,
createResourceSchema: CreateKubernetesResourceSchema,
updateResourceSchema: UpdateKubernetesResourceSchema
});
},
[PamResource.AwsIam]: async (server: FastifyZodProvider) => {
registerPamResourceEndpoints({
server,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {
AwsIamResourceListItemSchema,
SanitizedAwsIamResourceSchema
} from "@app/ee/services/pam-resource/aws-iam/aws-iam-resource-schemas";
import {
KubernetesResourceListItemSchema,
SanitizedKubernetesResourceSchema
} from "@app/ee/services/pam-resource/kubernetes/kubernetes-resource-schemas";
import {
MySQLResourceListItemSchema,
SanitizedMySQLResourceSchema
Expand All @@ -27,13 +31,15 @@ const SanitizedResourceSchema = z.union([
SanitizedPostgresResourceSchema,
SanitizedMySQLResourceSchema,
SanitizedSSHResourceSchema,
SanitizedKubernetesResourceSchema,
SanitizedAwsIamResourceSchema
]);

const ResourceOptionsSchema = z.discriminatedUnion("resource", [
PostgresResourceListItemSchema,
MySQLResourceListItemSchema,
SSHResourceListItemSchema,
KubernetesResourceListItemSchema,
AwsIamResourceListItemSchema
]);

Expand Down
7 changes: 5 additions & 2 deletions backend/src/ee/routes/v1/pam-session-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { z } from "zod";

import { PamSessionsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KubernetesSessionCredentialsSchema } from "@app/ee/services/pam-resource/kubernetes/kubernetes-resource-schemas";
import { MySQLSessionCredentialsSchema } from "@app/ee/services/pam-resource/mysql/mysql-resource-schemas";
import { PostgresSessionCredentialsSchema } from "@app/ee/services/pam-resource/postgres/postgres-resource-schemas";
import { SSHSessionCredentialsSchema } from "@app/ee/services/pam-resource/ssh/ssh-resource-schemas";
import {
HttpEventSchema,
PamSessionCommandLogSchema,
SanitizedSessionSchema,
TerminalEventSchema
Expand All @@ -17,7 +19,8 @@ import { AuthMode } from "@app/services/auth/auth-type";
const SessionCredentialsSchema = z.union([
SSHSessionCredentialsSchema,
PostgresSessionCredentialsSchema,
MySQLSessionCredentialsSchema
MySQLSessionCredentialsSchema,
KubernetesSessionCredentialsSchema
]);

export const registerPamSessionRouter = async (server: FastifyZodProvider) => {
Expand Down Expand Up @@ -89,7 +92,7 @@ export const registerPamSessionRouter = async (server: FastifyZodProvider) => {
sessionId: z.string().uuid()
}),
body: z.object({
logs: z.array(z.union([PamSessionCommandLogSchema, TerminalEventSchema]))
logs: z.array(z.union([PamSessionCommandLogSchema, TerminalEventSchema, HttpEventSchema]))
}),
response: {
200: z.object({
Expand Down
28 changes: 26 additions & 2 deletions backend/src/ee/services/pam-account/pam-account-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,30 @@ export const pamAccountServiceFactory = ({
throw new BadRequestError({ message: "Gateway ID is required for this resource type" });
}

const { host, port } =
resourceType !== PamResource.Kubernetes
? connectionDetails
: (() => {
const url = new URL(connectionDetails.url);
let portNumber: number | undefined;
if (url.port) {
portNumber = Number(url.port);
} else {
portNumber = url.protocol === "https:" ? 443 : 80;
}
return {
host: url.hostname,
port: portNumber
};
})();

const gatewayConnectionDetails = await gatewayV2Service.getPAMConnectionDetails({
gatewayId,
duration,
sessionId: session.id,
resourceType: resource.resourceType as PamResource,
host: (connectionDetails as TSqlResourceConnectionDetails).host,
port: (connectionDetails as TSqlResourceConnectionDetails).port,
host,
port,
actorMetadata: {
id: actor.id,
type: actor.type,
Expand Down Expand Up @@ -746,6 +763,13 @@ export const pamAccountServiceFactory = ({
};
}
break;
case PamResource.Kubernetes:
metadata = {
resourceName: resource.name,
accountName: account.name,
accountPath
};
break;
default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum KubernetesAuthMethod {
ServiceAccountToken = "service-account-token"
}
Loading
Loading