mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 07:35:09 +00:00
feat: integrated with github app connection to gateway and some adjustments
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
@@ -21,7 +21,18 @@ export const registerProxyRouter = async (server: FastifyZodProvider) => {
|
||||
name: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.any()
|
||||
200: z.object({
|
||||
pki: z.object({
|
||||
serverCertificate: z.string(),
|
||||
serverPrivateKey: z.string(),
|
||||
clientCertificateChain: z.string()
|
||||
}),
|
||||
ssh: z.object({
|
||||
serverCertificate: z.string(),
|
||||
serverPrivateKey: z.string(),
|
||||
clientCAPublicKey: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: (req, _, next) => {
|
||||
@@ -59,6 +70,10 @@ export const registerProxyRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
throw new BadRequestError({
|
||||
message: "Org proxy registration is not yet supported"
|
||||
});
|
||||
|
||||
return server.services.proxy.registerProxy({
|
||||
...req.body,
|
||||
identityId: req.permission.id,
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
import z from "zod";
|
||||
|
||||
import { GatewaysV2Schema } from "@app/db/schemas";
|
||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
const SanitizedGatewayV2Schema = GatewaysV2Schema.pick({
|
||||
id: true,
|
||||
identityId: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
heartbeat: true
|
||||
});
|
||||
|
||||
export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
@@ -14,7 +24,20 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
name: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.any()
|
||||
200: z.object({
|
||||
gatewayId: z.string(),
|
||||
proxyIp: z.string(),
|
||||
pki: z.object({
|
||||
serverCertificate: z.string(),
|
||||
serverPrivateKey: z.string(),
|
||||
clientCertificateChain: z.string()
|
||||
}),
|
||||
ssh: z.object({
|
||||
clientCertificate: z.string(),
|
||||
clientPrivateKey: z.string(),
|
||||
serverCAPublicKey: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -23,6 +46,7 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
orgId: req.permission.orgId,
|
||||
proxyName: req.body.proxyName,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
name: req.body.name
|
||||
});
|
||||
|
||||
@@ -58,7 +82,12 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
url: "/",
|
||||
schema: {
|
||||
response: {
|
||||
200: z.any()
|
||||
200: SanitizedGatewayV2Schema.extend({
|
||||
identity: z.object({
|
||||
name: z.string(),
|
||||
id: z.string()
|
||||
})
|
||||
}).array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -82,7 +111,7 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
id: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.any()
|
||||
200: SanitizedGatewayV2Schema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN, AuthMode.JWT]),
|
||||
@@ -91,7 +120,7 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
orgPermission: req.permission,
|
||||
id: req.params.id
|
||||
});
|
||||
return { gateway };
|
||||
return gateway;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import net from "node:net";
|
||||
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
|
||||
import { TProxies } from "@app/db/schemas";
|
||||
@@ -9,7 +10,7 @@ import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { GatewayProxyProtocol } from "@app/lib/gateway/types";
|
||||
import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
||||
import { constructPemChainFromCerts } from "@app/services/certificate/certificate-fns";
|
||||
import { CertExtendedKeyUsage, CertKeyAlgorithm, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
||||
import {
|
||||
@@ -20,6 +21,8 @@ import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
|
||||
import { TLicenseServiceFactory } from "../license/license-service";
|
||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service-types";
|
||||
import { TProxyDALFactory } from "../proxy/proxy-dal";
|
||||
import { isInstanceProxy } from "../proxy/proxy-fns";
|
||||
import { TProxyServiceFactory } from "../proxy/proxy-service";
|
||||
@@ -34,6 +37,7 @@ type TGatewayV2ServiceFactoryDep = {
|
||||
proxyService: TProxyServiceFactory;
|
||||
gatewayV2DAL: TGatewayV2DALFactory;
|
||||
proxyDAL: TProxyDALFactory;
|
||||
permissionService: TPermissionServiceFactory;
|
||||
};
|
||||
|
||||
export type TGatewayV2ServiceFactory = ReturnType<typeof gatewayV2ServiceFactory>;
|
||||
@@ -44,8 +48,32 @@ export const gatewayV2ServiceFactory = ({
|
||||
kmsService,
|
||||
proxyService,
|
||||
gatewayV2DAL,
|
||||
proxyDAL
|
||||
proxyDAL,
|
||||
permissionService
|
||||
}: TGatewayV2ServiceFactoryDep) => {
|
||||
const $validateIdentityAccessToGateway = async (orgId: string, actorId: string, actorAuthMethod: ActorAuthMethod) => {
|
||||
const orgLicensePlan = await licenseService.getPlan(orgId);
|
||||
if (!orgLicensePlan.gateway) {
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
"Gateway operation failed due to organization plan restrictions. Please upgrade your instance to Infisical's Enterprise plan."
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
ActorType.IDENTITY,
|
||||
actorId,
|
||||
orgId,
|
||||
actorAuthMethod,
|
||||
orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
OrgPermissionGatewayActions.CreateGateways,
|
||||
OrgPermissionSubjects.Gateway
|
||||
);
|
||||
};
|
||||
|
||||
const $getOrgCAs = async (orgId: string) => {
|
||||
const { encryptor: orgKmsEncryptor, decryptor: orgKmsDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
@@ -217,20 +245,18 @@ export const gatewayV2ServiceFactory = ({
|
||||
};
|
||||
|
||||
const listGateways = async ({ orgPermission }: { orgPermission: OrgServiceActor }) => {
|
||||
// const { permission } = await permissionService.getOrgPermission(
|
||||
// orgPermission.type,
|
||||
// orgPermission.id,
|
||||
// orgPermission.orgId,
|
||||
// orgPermission.authMethod,
|
||||
// orgPermission.orgId
|
||||
// );
|
||||
// ForbiddenError.from(permission).throwUnlessCan(
|
||||
// OrgPermissionGatewayActions.ListGateways,
|
||||
// OrgPermissionSubjects.Gateway
|
||||
// );
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
orgPermission.type,
|
||||
orgPermission.id,
|
||||
orgPermission.orgId,
|
||||
orgPermission.authMethod,
|
||||
orgPermission.orgId
|
||||
);
|
||||
|
||||
const orgGatewayConfig = await orgGatewayConfigV2DAL.findOne({ orgId: orgPermission.orgId });
|
||||
if (!orgGatewayConfig) return [];
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
OrgPermissionGatewayActions.ListGateways,
|
||||
OrgPermissionSubjects.Gateway
|
||||
);
|
||||
|
||||
const gateways = await gatewayV2DAL.find({
|
||||
orgId: orgPermission.orgId
|
||||
@@ -389,14 +415,17 @@ export const gatewayV2ServiceFactory = ({
|
||||
const registerGateway = async ({
|
||||
orgId,
|
||||
actorId,
|
||||
actorAuthMethod,
|
||||
proxyName,
|
||||
name
|
||||
}: {
|
||||
orgId: string;
|
||||
actorId: string;
|
||||
actorAuthMethod: ActorAuthMethod;
|
||||
proxyName: string;
|
||||
name: string;
|
||||
}) => {
|
||||
await $validateIdentityAccessToGateway(orgId, actorId, actorAuthMethod);
|
||||
const orgCAs = await $getOrgCAs(orgId);
|
||||
|
||||
let proxy: TProxies;
|
||||
@@ -407,7 +436,7 @@ export const gatewayV2ServiceFactory = ({
|
||||
}
|
||||
|
||||
if (!proxy) {
|
||||
throw new Error("Proxy not found");
|
||||
throw new NotFoundError({ message: `Proxy ${proxyName} not found` });
|
||||
}
|
||||
|
||||
const [gateway] = await gatewayV2DAL.upsert(
|
||||
@@ -499,6 +528,8 @@ export const gatewayV2ServiceFactory = ({
|
||||
};
|
||||
|
||||
const heartbeat = async ({ orgPermission }: { orgPermission: OrgServiceActor }) => {
|
||||
await $validateIdentityAccessToGateway(orgPermission.orgId, orgPermission.id, orgPermission.authMethod);
|
||||
|
||||
const gateway = await gatewayV2DAL.findOne({
|
||||
orgId: orgPermission.orgId,
|
||||
identityId: orgPermission.id
|
||||
@@ -587,19 +618,25 @@ export const gatewayV2ServiceFactory = ({
|
||||
};
|
||||
|
||||
const deleteGatewayById = async ({ orgPermission, id }: { orgPermission: OrgServiceActor; id: string }) => {
|
||||
// const { permission } = await permissionService.getOrgPermission(
|
||||
// orgPermission.type,
|
||||
// orgPermission.id,
|
||||
// orgPermission.orgId,
|
||||
// orgPermission.authMethod,
|
||||
// orgPermission.orgId
|
||||
// );
|
||||
// ForbiddenError.from(permission).throwUnlessCan(
|
||||
// OrgPermissionGatewayActions.DeleteGateways,
|
||||
// OrgPermissionSubjects.Gateway
|
||||
// );
|
||||
const gateway = await gatewayV2DAL.findOne({ id, orgId: orgPermission.orgId });
|
||||
if (!gateway) {
|
||||
throw new NotFoundError({ message: `Gateway ${id} not found` });
|
||||
}
|
||||
|
||||
return gatewayV2DAL.deleteById(id);
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
orgPermission.type,
|
||||
orgPermission.id,
|
||||
gateway.orgId,
|
||||
orgPermission.authMethod,
|
||||
orgPermission.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
OrgPermissionGatewayActions.DeleteGateways,
|
||||
OrgPermissionSubjects.Gateway
|
||||
);
|
||||
|
||||
return gatewayV2DAL.deleteById(gateway.id);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -799,7 +799,7 @@ export const proxyServiceFactory = ({
|
||||
const proxyClientSshCert = await createSshCert({
|
||||
caPrivateKey: instanceCAs.instanceProxySshServerCaPrivateKey.toString("utf8"),
|
||||
clientPublicKey: proxyClientSshPublicKey,
|
||||
keyId: `proxy-client-${proxy.id}`,
|
||||
keyId: `client-${proxyName}`,
|
||||
principals: [gatewayId],
|
||||
certType: SshCertType.USER,
|
||||
requestedTtl: "30d"
|
||||
@@ -898,7 +898,6 @@ export const proxyServiceFactory = ({
|
||||
const isOrgProxy = identityId && orgId;
|
||||
|
||||
if (isOrgProxy) {
|
||||
// organization proxy
|
||||
if (isInstanceProxy(name)) {
|
||||
throw new BadRequestError({
|
||||
message: "Org proxy name cannot start with 'infisical-'. This is reserved for internal use."
|
||||
@@ -935,8 +934,7 @@ export const proxyServiceFactory = ({
|
||||
return existingProxy;
|
||||
});
|
||||
} else {
|
||||
// instance proxy
|
||||
if (!name.startsWith("infisical-")) {
|
||||
if (!isInstanceProxy(name)) {
|
||||
throw new BadRequestError({
|
||||
message: "Instance proxy name must start with 'infisical-'."
|
||||
});
|
||||
@@ -952,7 +950,7 @@ export const proxyServiceFactory = ({
|
||||
|
||||
if (existingProxy && existingProxy.ip !== ip) {
|
||||
throw new BadRequestError({
|
||||
message: "Instance proxy with this name already exists"
|
||||
message: "Instance proxy with this name already exists with a different IP address"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user