mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: gateway registration + start of gateway v2 integration
This commit is contained in:
4
backend/src/@types/knex.d.ts
vendored
4
backend/src/@types/knex.d.ts
vendored
@@ -101,6 +101,9 @@ import {
|
||||
TGateways,
|
||||
TGatewaysInsert,
|
||||
TGatewaysUpdate,
|
||||
TGatewaysV2,
|
||||
TGatewaysV2Insert,
|
||||
TGatewaysV2Update,
|
||||
TGitAppInstallSessions,
|
||||
TGitAppInstallSessionsInsert,
|
||||
TGitAppInstallSessionsUpdate,
|
||||
@@ -1282,5 +1285,6 @@ declare module "knex/types/tables" {
|
||||
TOrgGatewayConfigV2Update
|
||||
>;
|
||||
[TableName.Proxy]: KnexOriginal.CompositeTableType<TProxies, TProxiesInsert, TProxiesUpdate>;
|
||||
[TableName.GatewayV2]: KnexOriginal.CompositeTableType<TGatewaysV2, TGatewaysV2Insert, TGatewaysV2Update>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,14 +110,14 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.timestamps(true, true, true);
|
||||
|
||||
t.uuid("orgId");
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
|
||||
t.uuid("identityId").unique();
|
||||
t.uuid("identityId").notNullable().unique();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
|
||||
t.uuid("proxyId");
|
||||
t.foreign("proxyId").references("id").inTable(TableName.Proxy).onDelete("CASCADE");
|
||||
t.foreign("proxyId").references("id").inTable(TableName.Proxy).onDelete("SET NULL");
|
||||
|
||||
t.string("name").notNullable().unique();
|
||||
});
|
||||
@@ -136,9 +136,9 @@ export async function down(knex: Knex): Promise<void> {
|
||||
await dropOnUpdateTrigger(knex, TableName.OrgGatewayConfigV2);
|
||||
await knex.schema.dropTableIfExists(TableName.OrgGatewayConfigV2);
|
||||
|
||||
await dropOnUpdateTrigger(knex, TableName.Proxy);
|
||||
await knex.schema.dropTableIfExists(TableName.Proxy);
|
||||
|
||||
await dropOnUpdateTrigger(knex, TableName.GatewayV2);
|
||||
await knex.schema.dropTableIfExists(TableName.GatewayV2);
|
||||
|
||||
await dropOnUpdateTrigger(knex, TableName.Proxy);
|
||||
await knex.schema.dropTableIfExists(TableName.Proxy);
|
||||
}
|
||||
|
||||
22
backend/src/db/schemas/gateways-v2.ts
Normal file
22
backend/src/db/schemas/gateways-v2.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const GatewaysV2Schema = z.object({
|
||||
id: z.string().uuid(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
orgId: z.string().uuid(),
|
||||
identityId: z.string().uuid(),
|
||||
proxyId: z.string().uuid().nullable().optional(),
|
||||
name: z.string()
|
||||
});
|
||||
|
||||
export type TGatewaysV2 = z.infer<typeof GatewaysV2Schema>;
|
||||
export type TGatewaysV2Insert = Omit<z.input<typeof GatewaysV2Schema>, TImmutableDBKeys>;
|
||||
export type TGatewaysV2Update = Partial<Omit<z.input<typeof GatewaysV2Schema>, TImmutableDBKeys>>;
|
||||
@@ -31,6 +31,7 @@ export * from "./folder-commits";
|
||||
export * from "./folder-tree-checkpoint-resources";
|
||||
export * from "./folder-tree-checkpoints";
|
||||
export * from "./gateways";
|
||||
export * from "./gateways-v2";
|
||||
export * from "./git-app-install-sessions";
|
||||
export * from "./git-app-org";
|
||||
export * from "./github-org-sync-configs";
|
||||
@@ -98,6 +99,7 @@ export * from "./project-templates";
|
||||
export * from "./project-user-additional-privilege";
|
||||
export * from "./project-user-membership-roles";
|
||||
export * from "./projects";
|
||||
export * from "./proxies";
|
||||
export * from "./rate-limit";
|
||||
export * from "./resource-metadata";
|
||||
export * from "./saml-configs";
|
||||
@@ -165,4 +167,3 @@ export * from "./user-group-membership";
|
||||
export * from "./users";
|
||||
export * from "./webhooks";
|
||||
export * from "./workflow-integrations";
|
||||
export * from "./proxies";
|
||||
|
||||
@@ -7,23 +7,43 @@ export const registerGatewayV2Router = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
proxyName: z.string()
|
||||
proxyName: z.string(),
|
||||
name: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.any()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const gateway = await server.services.gatewayV2.registerGateway({
|
||||
orgId: req.permission.orgId,
|
||||
proxyName: req.body.proxyName,
|
||||
actorId: req.permission.id
|
||||
actorId: req.permission.id,
|
||||
name: req.body.name
|
||||
});
|
||||
|
||||
return gateway;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
schema: {
|
||||
response: {
|
||||
200: z.any()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const gateways = await server.services.gatewayV2.listGateways({
|
||||
orgPermission: req.permission
|
||||
});
|
||||
|
||||
return gateways;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-fold
|
||||
import { TDynamicSecretLeaseDALFactory } from "../dynamic-secret-lease/dynamic-secret-lease-dal";
|
||||
import { TDynamicSecretLeaseQueueServiceFactory } from "../dynamic-secret-lease/dynamic-secret-lease-queue";
|
||||
import { TGatewayDALFactory } from "../gateway/gateway-dal";
|
||||
import { TGatewayV2DALFactory } from "../gateway-v2/gateway-v2-dal";
|
||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||
import { TDynamicSecretDALFactory } from "./dynamic-secret-dal";
|
||||
import { DynamicSecretStatus, TDynamicSecretServiceFactory } from "./dynamic-secret-types";
|
||||
@@ -39,6 +40,7 @@ type TDynamicSecretServiceFactoryDep = {
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
gatewayDAL: Pick<TGatewayDALFactory, "findOne" | "find">;
|
||||
gatewayV2DAL: Pick<TGatewayV2DALFactory, "findOne" | "find">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
};
|
||||
|
||||
@@ -53,6 +55,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
projectDAL,
|
||||
kmsService,
|
||||
gatewayDAL,
|
||||
gatewayV2DAL,
|
||||
resourceMetadataDAL
|
||||
}: TDynamicSecretServiceFactoryDep): TDynamicSecretServiceFactory => {
|
||||
const create: TDynamicSecretServiceFactory["create"] = async ({
|
||||
@@ -118,8 +121,9 @@ export const dynamicSecretServiceFactory = ({
|
||||
const gatewayId = inputs.gatewayId as string;
|
||||
|
||||
const [gateway] = await gatewayDAL.find({ id: gatewayId, orgId: actorOrgId });
|
||||
const [gatewayv2] = await gatewayV2DAL.find({ id: gatewayId, orgId: actorOrgId });
|
||||
|
||||
if (!gateway) {
|
||||
if (!gateway && !gatewayv2) {
|
||||
throw new NotFoundError({
|
||||
message: `Gateway with ID ${gatewayId} not found`
|
||||
});
|
||||
@@ -128,7 +132,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
const { permission: orgPermission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
gateway.orgId,
|
||||
gateway?.orgId ?? gatewayv2?.orgId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
@@ -138,7 +142,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
OrgPermissionSubjects.Gateway
|
||||
);
|
||||
|
||||
selectedGatewayId = gateway.id;
|
||||
selectedGatewayId = gateway?.id ?? gatewayv2?.id;
|
||||
}
|
||||
|
||||
const isConnected = await selectedProvider.validateConnection(provider.inputs, { projectId });
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SnowflakeProvider } from "@app/ee/services/dynamic-secret/providers/snowflake";
|
||||
|
||||
import { TGatewayServiceFactory } from "../../gateway/gateway-service";
|
||||
import { TGatewayV2ServiceFactory } from "../../gateway-v2/gateway-v2-service";
|
||||
import { AwsElastiCacheDatabaseProvider } from "./aws-elasticache";
|
||||
import { AwsIamProvider } from "./aws-iam";
|
||||
import { AzureEntraIDProvider } from "./azure-entra-id";
|
||||
@@ -24,10 +25,12 @@ import { VerticaProvider } from "./vertica";
|
||||
|
||||
type TBuildDynamicSecretProviderDTO = {
|
||||
gatewayService: Pick<TGatewayServiceFactory, "fnGetGatewayClientTlsByGatewayId">;
|
||||
gatewayV2Service: Pick<TGatewayV2ServiceFactory, "getPlatformConnectionDetailsByGatewayId">;
|
||||
};
|
||||
|
||||
export const buildDynamicSecretProviders = ({
|
||||
gatewayService
|
||||
gatewayService,
|
||||
gatewayV2Service
|
||||
}: TBuildDynamicSecretProviderDTO): Record<DynamicSecretProviders, TDynamicProviderFns> => ({
|
||||
[DynamicSecretProviders.SqlDatabase]: SqlDatabaseProvider({ gatewayService }),
|
||||
[DynamicSecretProviders.Cassandra]: CassandraProvider(),
|
||||
@@ -44,7 +47,7 @@ export const buildDynamicSecretProviders = ({
|
||||
[DynamicSecretProviders.Snowflake]: SnowflakeProvider(),
|
||||
[DynamicSecretProviders.Totp]: TotpProvider(),
|
||||
[DynamicSecretProviders.SapAse]: SapAseProvider(),
|
||||
[DynamicSecretProviders.Kubernetes]: KubernetesProvider({ gatewayService }),
|
||||
[DynamicSecretProviders.Kubernetes]: KubernetesProvider({ gatewayService, gatewayV2Service }),
|
||||
[DynamicSecretProviders.Vertica]: VerticaProvider({ gatewayService }),
|
||||
[DynamicSecretProviders.GcpIam]: GcpIamProvider(),
|
||||
[DynamicSecretProviders.Github]: GithubProvider(),
|
||||
|
||||
@@ -5,12 +5,14 @@ import https from "https";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { sanitizeString } from "@app/lib/fn";
|
||||
import { GatewayHttpProxyActions, GatewayProxyProtocol, withGatewayProxy } from "@app/lib/gateway";
|
||||
import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
|
||||
import { TKubernetesTokenRequest } from "@app/services/identity-kubernetes-auth/identity-kubernetes-auth-types";
|
||||
|
||||
import { TDynamicSecretKubernetesLeaseConfig } from "../../dynamic-secret-lease/dynamic-secret-lease-types";
|
||||
import { TGatewayServiceFactory } from "../../gateway/gateway-service";
|
||||
import { TGatewayV2ServiceFactory } from "../../gateway-v2/gateway-v2-service";
|
||||
import {
|
||||
DynamicSecretKubernetesSchema,
|
||||
KubernetesAuthMethod,
|
||||
@@ -26,6 +28,7 @@ const GATEWAY_AUTH_DEFAULT_URL = "https://kubernetes.default.svc.cluster.local";
|
||||
|
||||
type TKubernetesProviderDTO = {
|
||||
gatewayService: Pick<TGatewayServiceFactory, "fnGetGatewayClientTlsByGatewayId">;
|
||||
gatewayV2Service: Pick<TGatewayV2ServiceFactory, "getPlatformConnectionDetailsByGatewayId">;
|
||||
};
|
||||
|
||||
const generateUsername = (usernameTemplate?: string | null) => {
|
||||
@@ -38,7 +41,10 @@ const generateUsername = (usernameTemplate?: string | null) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const KubernetesProvider = ({ gatewayService }: TKubernetesProviderDTO): TDynamicProviderFns => {
|
||||
export const KubernetesProvider = ({
|
||||
gatewayService,
|
||||
gatewayV2Service
|
||||
}: TKubernetesProviderDTO): TDynamicProviderFns => {
|
||||
const validateProviderInputs = async (inputs: unknown) => {
|
||||
const providerInputs = await DynamicSecretKubernetesSchema.parseAsync(inputs);
|
||||
if (!providerInputs.gatewayId && providerInputs.url) {
|
||||
@@ -58,6 +64,26 @@ export const KubernetesProvider = ({ gatewayService }: TKubernetesProviderDTO):
|
||||
},
|
||||
gatewayCallback: (host: string, port: number, httpsAgent?: https.Agent) => Promise<T>
|
||||
): Promise<T> => {
|
||||
const gatewayV2ConnectionDetails = await gatewayV2Service.getPlatformConnectionDetailsByGatewayId(inputs.gatewayId);
|
||||
if (gatewayV2ConnectionDetails) {
|
||||
const callbackResult = await withGatewayV2Proxy(
|
||||
async (port) => {
|
||||
return gatewayCallback(
|
||||
inputs.reviewTokenThroughGateway ? "http://localhost" : "https://localhost",
|
||||
port,
|
||||
inputs.httpsAgent
|
||||
);
|
||||
},
|
||||
{
|
||||
proxyIp: gatewayV2ConnectionDetails.proxyIp,
|
||||
gateway: gatewayV2ConnectionDetails.gateway,
|
||||
proxy: gatewayV2ConnectionDetails.proxy
|
||||
}
|
||||
);
|
||||
|
||||
return callbackResult;
|
||||
}
|
||||
|
||||
const relayDetails = await gatewayService.fnGetGatewayClientTlsByGatewayId(inputs.gatewayId);
|
||||
const [relayHost, relayPort] = relayDetails.relayAddress.split(":");
|
||||
|
||||
|
||||
11
backend/src/ee/services/gateway-v2/gateway-v2-dal.ts
Normal file
11
backend/src/ee/services/gateway-v2/gateway-v2-dal.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { ormify } from "@app/lib/knex";
|
||||
|
||||
export type TGatewayV2DALFactory = ReturnType<typeof gatewayV2DalFactory>;
|
||||
|
||||
export const gatewayV2DalFactory = (db: TDbClient) => {
|
||||
const orm = ormify(db, TableName.GatewayV2);
|
||||
|
||||
return orm;
|
||||
};
|
||||
@@ -1,7 +1,11 @@
|
||||
import * as x509 from "@peculiar/x509";
|
||||
|
||||
import { TProxies } from "@app/db/schemas";
|
||||
import { PgSqlLock } from "@app/keystore/keystore";
|
||||
import { crypto } from "@app/lib/crypto";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
import { 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 {
|
||||
@@ -11,13 +15,18 @@ import {
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
|
||||
import { TProxyDALFactory } from "../proxy/proxy-dal";
|
||||
import { isInstanceProxy } from "../proxy/proxy-fns";
|
||||
import { TProxyServiceFactory } from "../proxy/proxy-service";
|
||||
import { TGatewayV2DALFactory } from "./gateway-v2-dal";
|
||||
import { TOrgGatewayConfigV2DALFactory } from "./org-gateway-config-v2-dal";
|
||||
|
||||
type TGatewayV2ServiceFactoryDep = {
|
||||
orgGatewayConfigV2DAL: Pick<TOrgGatewayConfigV2DALFactory, "findOne" | "create" | "transaction" | "findById">;
|
||||
kmsService: TKmsServiceFactory;
|
||||
proxyService: TProxyServiceFactory;
|
||||
gatewayV2DAL: TGatewayV2DALFactory;
|
||||
proxyDAL: TProxyDALFactory;
|
||||
};
|
||||
|
||||
export type TGatewayV2ServiceFactory = ReturnType<typeof gatewayV2ServiceFactory>;
|
||||
@@ -25,7 +34,9 @@ export type TGatewayV2ServiceFactory = ReturnType<typeof gatewayV2ServiceFactory
|
||||
export const gatewayV2ServiceFactory = ({
|
||||
orgGatewayConfigV2DAL,
|
||||
kmsService,
|
||||
proxyService
|
||||
proxyService,
|
||||
gatewayV2DAL,
|
||||
proxyDAL
|
||||
}: TGatewayV2ServiceFactoryDep) => {
|
||||
const $getOrgCAs = async (orgId: string) => {
|
||||
const { encryptor: orgKmsEncryptor, decryptor: orgKmsDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
@@ -197,11 +208,179 @@ export const gatewayV2ServiceFactory = ({
|
||||
};
|
||||
};
|
||||
|
||||
const registerGateway = async ({ orgId, proxyName }: { orgId: string; actorId: string; proxyName: string }) => {
|
||||
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 orgGatewayConfig = await orgGatewayConfigV2DAL.findOne({ orgId: orgPermission.orgId });
|
||||
if (!orgGatewayConfig) return [];
|
||||
|
||||
const gateways = await gatewayV2DAL.find({
|
||||
orgId: orgPermission.orgId
|
||||
});
|
||||
|
||||
return gateways;
|
||||
};
|
||||
|
||||
const getPlatformConnectionDetailsByGatewayId = async (gatewayId: string) => {
|
||||
const gateway = await gatewayV2DAL.findById(gatewayId);
|
||||
if (!gateway) {
|
||||
return;
|
||||
}
|
||||
|
||||
const orgGatewayConfig = await orgGatewayConfigV2DAL.findOne({ orgId: gateway.orgId });
|
||||
if (!orgGatewayConfig) {
|
||||
throw new NotFoundError({ message: `Gateway Config for org ${gateway.orgId} not found.` });
|
||||
}
|
||||
|
||||
if (!gateway.proxyId) {
|
||||
throw new BadRequestError({
|
||||
message: "Gateway is not associated with a proxy"
|
||||
});
|
||||
}
|
||||
|
||||
// const orgLicensePlan = await licenseService.getPlan(orgGatewayConfig.orgId);
|
||||
// if (!orgLicensePlan.gateway) {
|
||||
// throw new BadRequestError({
|
||||
// message: "Please upgrade your instance to Infisical's Enterprise plan to use gateways."
|
||||
// });
|
||||
// }
|
||||
|
||||
const { decryptor: orgKmsDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
orgId: orgGatewayConfig.orgId
|
||||
});
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
||||
|
||||
const rootGatewayCaCert = new x509.X509Certificate(
|
||||
orgKmsDecryptor({
|
||||
cipherTextBlob: orgGatewayConfig.encryptedRootGatewayCaCertificate
|
||||
})
|
||||
);
|
||||
|
||||
const gatewayClientCaCert = new x509.X509Certificate(
|
||||
orgKmsDecryptor({
|
||||
cipherTextBlob: orgGatewayConfig.encryptedGatewayClientCaCertificate
|
||||
})
|
||||
);
|
||||
|
||||
const gatewayClientCaPrivateKey = orgKmsDecryptor({
|
||||
cipherTextBlob: orgGatewayConfig.encryptedGatewayClientCaPrivateKey
|
||||
});
|
||||
|
||||
const gatewayClientCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
||||
key: gatewayClientCaPrivateKey,
|
||||
format: "der",
|
||||
type: "pkcs8"
|
||||
});
|
||||
|
||||
const importedGatewayClientCaPrivateKey = await crypto.nativeCrypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
gatewayClientCaSkObj.export({ format: "der", type: "pkcs8" }),
|
||||
alg,
|
||||
true,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const clientCertIssuedAt = new Date();
|
||||
const clientCertExpiration = new Date(new Date().getTime() + 5 * 60 * 1000);
|
||||
const clientKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const clientCertSerialNumber = createSerialNumber();
|
||||
|
||||
const clientCert = await x509.X509CertificateGenerator.create({
|
||||
serialNumber: clientCertSerialNumber,
|
||||
subject: `O=${orgGatewayConfig.orgId},OU=gateway-client,CN=${ActorType.PLATFORM}:${gatewayId}`,
|
||||
issuer: gatewayClientCaCert.subject,
|
||||
notAfter: clientCertExpiration,
|
||||
notBefore: clientCertIssuedAt,
|
||||
signingKey: importedGatewayClientCaPrivateKey,
|
||||
publicKey: clientKeys.publicKey,
|
||||
signingAlgorithm: alg,
|
||||
extensions: [
|
||||
new x509.BasicConstraintsExtension(false),
|
||||
await x509.AuthorityKeyIdentifierExtension.create(gatewayClientCaCert, false),
|
||||
await x509.SubjectKeyIdentifierExtension.create(clientKeys.publicKey),
|
||||
new x509.CertificatePolicyExtension(["2.5.29.32.0"]), // anyPolicy
|
||||
new x509.KeyUsagesExtension(
|
||||
// eslint-disable-next-line no-bitwise
|
||||
x509.KeyUsageFlags[CertKeyUsage.DIGITAL_SIGNATURE] |
|
||||
x509.KeyUsageFlags[CertKeyUsage.KEY_ENCIPHERMENT] |
|
||||
x509.KeyUsageFlags[CertKeyUsage.KEY_AGREEMENT],
|
||||
true
|
||||
),
|
||||
new x509.ExtendedKeyUsageExtension([x509.ExtendedKeyUsage[CertExtendedKeyUsage.CLIENT_AUTH]], true)
|
||||
]
|
||||
});
|
||||
const gatewayClientCertPrivateKey = crypto.nativeCrypto.KeyObject.from(clientKeys.privateKey);
|
||||
|
||||
const proxyCredentials = await proxyService.getCredentialsForClient({
|
||||
proxyId: gateway.proxyId,
|
||||
orgId: gateway.orgId,
|
||||
gatewayId,
|
||||
actor: ActorType.PLATFORM
|
||||
});
|
||||
|
||||
return {
|
||||
proxyIp: proxyCredentials.proxyIp,
|
||||
gateway: {
|
||||
clientCertificate: clientCert.toString("pem"),
|
||||
clientPrivateKey: gatewayClientCertPrivateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
||||
clientCertificateChain: constructPemChainFromCerts([gatewayClientCaCert, rootGatewayCaCert]),
|
||||
serverCA: rootGatewayCaCert.toString("pem")
|
||||
},
|
||||
proxy: {
|
||||
clientCertificate: proxyCredentials.clientCertificate,
|
||||
clientPrivateKey: proxyCredentials.clientPrivateKey,
|
||||
serverCertificateChain: proxyCredentials.serverCertificateChain
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const registerGateway = async ({
|
||||
orgId,
|
||||
actorId,
|
||||
proxyName,
|
||||
name
|
||||
}: {
|
||||
orgId: string;
|
||||
actorId: string;
|
||||
proxyName: string;
|
||||
name: string;
|
||||
}) => {
|
||||
const orgCAs = await $getOrgCAs(orgId);
|
||||
|
||||
// TODO: Save gateway to DB and set Gateway ID as principal in SSH certificate
|
||||
// only throw error if proxy is different from existing DB record
|
||||
let proxy: TProxies;
|
||||
if (isInstanceProxy(proxyName)) {
|
||||
proxy = await proxyDAL.findOne({ name: proxyName });
|
||||
} else {
|
||||
proxy = await proxyDAL.findOne({ orgId, name: proxyName });
|
||||
}
|
||||
|
||||
if (!proxy) {
|
||||
throw new Error("Proxy not found");
|
||||
}
|
||||
|
||||
const [gateway] = await gatewayV2DAL.upsert(
|
||||
[
|
||||
{
|
||||
orgId,
|
||||
name,
|
||||
identityId: actorId,
|
||||
proxyId: proxy.id
|
||||
}
|
||||
],
|
||||
["identityId"]
|
||||
);
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
||||
const gatewayServerCaCert = new x509.X509Certificate(orgCAs.gatewayServerCaCertificate);
|
||||
@@ -253,11 +432,12 @@ export const gatewayV2ServiceFactory = ({
|
||||
|
||||
const proxyCredentials = await proxyService.getCredentialsForGateway({
|
||||
proxyName,
|
||||
orgId
|
||||
orgId,
|
||||
gatewayId: gateway.id
|
||||
});
|
||||
|
||||
return {
|
||||
// TODO: return gateway ID
|
||||
gatewayId: gateway.id,
|
||||
proxyIp: proxyCredentials.proxyIp,
|
||||
pki: {
|
||||
serverCertificate: gatewayServerCertificate.toString("pem"),
|
||||
@@ -274,6 +454,8 @@ export const gatewayV2ServiceFactory = ({
|
||||
};
|
||||
|
||||
return {
|
||||
registerGateway
|
||||
listGateways,
|
||||
registerGateway,
|
||||
getPlatformConnectionDetailsByGatewayId
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { TProxies } from "@app/db/schemas";
|
||||
import { PgSqlLock } from "@app/keystore/keystore";
|
||||
import { crypto } from "@app/lib/crypto";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { constructPemChainFromCerts, prependCertToPemChain } from "@app/services/certificate/certificate-fns";
|
||||
import { CertExtendedKeyUsage, CertKeyAlgorithm, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
||||
import {
|
||||
@@ -89,7 +90,7 @@ export const proxyServiceFactory = ({
|
||||
x509.KeyUsageFlags.keyEncipherment,
|
||||
true
|
||||
),
|
||||
new x509.BasicConstraintsExtension(true, 0, true),
|
||||
new x509.BasicConstraintsExtension(true, 2, true),
|
||||
await x509.AuthorityKeyIdentifierExtension.create(rootCaCert, false),
|
||||
await x509.SubjectKeyIdentifierExtension.create(orgProxyCaKeys.publicKey)
|
||||
]
|
||||
@@ -120,7 +121,7 @@ export const proxyServiceFactory = ({
|
||||
x509.KeyUsageFlags.keyEncipherment,
|
||||
true
|
||||
),
|
||||
new x509.BasicConstraintsExtension(true, 0, true),
|
||||
new x509.BasicConstraintsExtension(true, 1, true),
|
||||
await x509.AuthorityKeyIdentifierExtension.create(rootCaCert, false),
|
||||
await x509.SubjectKeyIdentifierExtension.create(instanceProxyCaKeys.publicKey)
|
||||
]
|
||||
@@ -587,88 +588,28 @@ export const proxyServiceFactory = ({
|
||||
};
|
||||
};
|
||||
|
||||
const getCredentialsForGateway = async ({ proxyName, orgId }: { proxyName: string; orgId: string }) => {
|
||||
let proxy: TProxies | null;
|
||||
if (isInstanceProxy(proxyName)) {
|
||||
proxy = await proxyDAL.findOne({
|
||||
name: proxyName
|
||||
});
|
||||
} else {
|
||||
proxy = await proxyDAL.findOne({
|
||||
orgId,
|
||||
name: proxyName
|
||||
});
|
||||
}
|
||||
|
||||
if (!proxy) {
|
||||
throw new NotFoundError({
|
||||
message: "Proxy not found"
|
||||
});
|
||||
}
|
||||
|
||||
const keyAlgorithm = SshCertKeyAlgorithm.RSA_2048;
|
||||
const { publicKey: proxyClientSshPublicKey, privateKey: proxyClientSshPrivateKey } =
|
||||
await createSshKeyPair(keyAlgorithm);
|
||||
|
||||
if (isInstanceProxy(proxyName)) {
|
||||
const instanceCAs = await $getInstanceCAs();
|
||||
const proxyClientSshCert = await createSshCert({
|
||||
caPrivateKey: instanceCAs.instanceProxySshServerCaPrivateKey.toString("utf8"),
|
||||
clientPublicKey: proxyClientSshPublicKey,
|
||||
keyId: `proxy-client-${proxy.id}`,
|
||||
principals: ["gateway ID"], // TODO: set gateway ID as principal in SSH certificate
|
||||
certType: SshCertType.USER,
|
||||
requestedTtl: "30d"
|
||||
});
|
||||
|
||||
return {
|
||||
proxyIp: proxy.ip,
|
||||
clientSshCert: proxyClientSshCert.signedPublicKey,
|
||||
clientSshPrivateKey: proxyClientSshPrivateKey,
|
||||
serverCAPublicKey: instanceCAs.instanceProxySshServerCaPublicKey.toString("utf8")
|
||||
};
|
||||
}
|
||||
|
||||
const orgCAs = await $getOrgCAs(orgId);
|
||||
const proxyClientSshCert = await createSshCert({
|
||||
caPrivateKey: orgCAs.proxySshServerCaPrivateKey.toString("utf8"),
|
||||
clientPublicKey: proxyClientSshPublicKey,
|
||||
keyId: `proxy-client-${proxy.id}`,
|
||||
principals: [orgId],
|
||||
certType: SshCertType.USER,
|
||||
requestedTtl: "30d"
|
||||
});
|
||||
|
||||
return {
|
||||
proxyIp: proxy.ip,
|
||||
clientSshCert: proxyClientSshCert.signedPublicKey,
|
||||
clientSshPrivateKey: proxyClientSshPrivateKey,
|
||||
serverCAPublicKey: orgCAs.proxySshServerCaPublicKey.toString("utf8")
|
||||
};
|
||||
};
|
||||
|
||||
const $generateProxyCredentials = async ({
|
||||
const $generateProxyServerCredentials = async ({
|
||||
ip,
|
||||
orgId,
|
||||
rootProxyPkiCaCertificate,
|
||||
proxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaPrivateKey,
|
||||
proxySshServerCaPrivateKey,
|
||||
proxyPkiServerCaCertificateChain,
|
||||
proxySshClientCaPublicKey
|
||||
proxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaCertificateChain,
|
||||
proxySshClientCaPublicKey,
|
||||
proxySshServerCaPrivateKey
|
||||
}: {
|
||||
ip: string;
|
||||
rootProxyPkiCaCertificate: Buffer;
|
||||
proxyPkiServerCaCertificate: Buffer;
|
||||
proxyPkiServerCaPrivateKey: Buffer;
|
||||
proxyPkiClientCaCertificateChain: Buffer;
|
||||
proxyPkiClientCaCertificate: Buffer;
|
||||
proxySshServerCaPrivateKey: Buffer;
|
||||
proxyPkiServerCaCertificateChain: Buffer;
|
||||
proxySshClientCaPublicKey: Buffer;
|
||||
orgId?: string;
|
||||
}) => {
|
||||
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
||||
const proxyServerCaCert = new x509.X509Certificate(proxyPkiServerCaCertificate);
|
||||
const rootProxyCaCert = new x509.X509Certificate(rootProxyPkiCaCertificate);
|
||||
const proxyClientCaCert = new x509.X509Certificate(proxyPkiClientCaCertificate);
|
||||
const proxyServerCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
||||
key: proxyPkiServerCaPrivateKey,
|
||||
format: "der",
|
||||
@@ -733,12 +674,11 @@ export const proxyServiceFactory = ({
|
||||
return {
|
||||
pki: {
|
||||
serverCertificate: proxyServerCertificate.toString("pem"),
|
||||
serverCertificateChain: prependCertToPemChain(
|
||||
proxyServerCaCert,
|
||||
proxyPkiServerCaCertificateChain.toString("utf8")
|
||||
),
|
||||
serverPrivateKey: proxyServerCertPrivateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
||||
clientCA: rootProxyCaCert.toString("pem")
|
||||
clientCertificateChain: prependCertToPemChain(
|
||||
proxyClientCaCert,
|
||||
proxyPkiClientCaCertificateChain.toString("utf8")
|
||||
)
|
||||
},
|
||||
ssh: {
|
||||
serverCertificate: proxyServerSshCert.signedPublicKey,
|
||||
@@ -748,6 +688,205 @@ export const proxyServiceFactory = ({
|
||||
};
|
||||
};
|
||||
|
||||
const $generateProxyClientCredentials = async ({
|
||||
actor,
|
||||
gatewayId,
|
||||
orgId,
|
||||
proxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaPrivateKey,
|
||||
proxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaCertificateChain
|
||||
}: {
|
||||
actor: ActorType;
|
||||
gatewayId: string;
|
||||
orgId: string;
|
||||
proxyPkiClientCaCertificate: Buffer;
|
||||
proxyPkiClientCaPrivateKey: Buffer;
|
||||
proxyPkiServerCaCertificate: Buffer;
|
||||
proxyPkiServerCaCertificateChain: Buffer;
|
||||
}) => {
|
||||
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
||||
const proxyClientCaCert = new x509.X509Certificate(proxyPkiClientCaCertificate);
|
||||
const proxyServerCaCert = new x509.X509Certificate(proxyPkiServerCaCertificate);
|
||||
const proxyClientCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
||||
key: proxyPkiClientCaPrivateKey,
|
||||
format: "der",
|
||||
type: "pkcs8"
|
||||
});
|
||||
|
||||
const importedProxyClientCaPrivateKey = await crypto.nativeCrypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
proxyClientCaSkObj.export({ format: "der", type: "pkcs8" }),
|
||||
alg,
|
||||
true,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const clientCertIssuedAt = new Date();
|
||||
const clientCertExpiration = new Date(new Date().getTime() + 5 * 60 * 1000);
|
||||
const clientKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const clientCertPrivateKey = crypto.nativeCrypto.KeyObject.from(clientKeys.privateKey);
|
||||
const clientCertSerialNumber = createSerialNumber();
|
||||
|
||||
const clientCert = await x509.X509CertificateGenerator.create({
|
||||
serialNumber: clientCertSerialNumber,
|
||||
subject: `O=${orgId},OU=proxy-client,CN=${actor}:${gatewayId}`,
|
||||
issuer: proxyClientCaCert.subject,
|
||||
notAfter: clientCertExpiration,
|
||||
notBefore: clientCertIssuedAt,
|
||||
signingKey: importedProxyClientCaPrivateKey,
|
||||
publicKey: clientKeys.publicKey,
|
||||
signingAlgorithm: alg,
|
||||
extensions: [
|
||||
new x509.BasicConstraintsExtension(false),
|
||||
await x509.AuthorityKeyIdentifierExtension.create(proxyClientCaCert, false),
|
||||
await x509.SubjectKeyIdentifierExtension.create(clientKeys.publicKey),
|
||||
new x509.CertificatePolicyExtension(["2.5.29.32.0"]), // anyPolicy
|
||||
new x509.KeyUsagesExtension(
|
||||
// eslint-disable-next-line no-bitwise
|
||||
x509.KeyUsageFlags[CertKeyUsage.DIGITAL_SIGNATURE] |
|
||||
x509.KeyUsageFlags[CertKeyUsage.KEY_ENCIPHERMENT] |
|
||||
x509.KeyUsageFlags[CertKeyUsage.KEY_AGREEMENT],
|
||||
true
|
||||
),
|
||||
new x509.ExtendedKeyUsageExtension([x509.ExtendedKeyUsage[CertExtendedKeyUsage.CLIENT_AUTH]], true)
|
||||
]
|
||||
});
|
||||
|
||||
return {
|
||||
clientCertificate: clientCert.toString("pem"),
|
||||
clientPrivateKey: clientCertPrivateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
||||
serverCertificateChain: prependCertToPemChain(
|
||||
proxyServerCaCert,
|
||||
proxyPkiServerCaCertificateChain.toString("utf8")
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
const getCredentialsForGateway = async ({
|
||||
proxyName,
|
||||
orgId,
|
||||
gatewayId
|
||||
}: {
|
||||
proxyName: string;
|
||||
orgId: string;
|
||||
gatewayId: string;
|
||||
}) => {
|
||||
let proxy: TProxies | null;
|
||||
if (isInstanceProxy(proxyName)) {
|
||||
proxy = await proxyDAL.findOne({
|
||||
name: proxyName
|
||||
});
|
||||
} else {
|
||||
proxy = await proxyDAL.findOne({
|
||||
orgId,
|
||||
name: proxyName
|
||||
});
|
||||
}
|
||||
|
||||
if (!proxy) {
|
||||
throw new NotFoundError({
|
||||
message: "Proxy not found"
|
||||
});
|
||||
}
|
||||
|
||||
const keyAlgorithm = SshCertKeyAlgorithm.RSA_2048;
|
||||
const { publicKey: proxyClientSshPublicKey, privateKey: proxyClientSshPrivateKey } =
|
||||
await createSshKeyPair(keyAlgorithm);
|
||||
|
||||
if (isInstanceProxy(proxyName)) {
|
||||
const instanceCAs = await $getInstanceCAs();
|
||||
const proxyClientSshCert = await createSshCert({
|
||||
caPrivateKey: instanceCAs.instanceProxySshServerCaPrivateKey.toString("utf8"),
|
||||
clientPublicKey: proxyClientSshPublicKey,
|
||||
keyId: `proxy-client-${proxy.id}`,
|
||||
principals: [gatewayId],
|
||||
certType: SshCertType.USER,
|
||||
requestedTtl: "30d"
|
||||
});
|
||||
|
||||
return {
|
||||
proxyIp: proxy.ip,
|
||||
clientSshCert: proxyClientSshCert.signedPublicKey,
|
||||
clientSshPrivateKey: proxyClientSshPrivateKey,
|
||||
serverCAPublicKey: instanceCAs.instanceProxySshServerCaPublicKey.toString("utf8")
|
||||
};
|
||||
}
|
||||
|
||||
const orgCAs = await $getOrgCAs(orgId);
|
||||
const proxyClientSshCert = await createSshCert({
|
||||
caPrivateKey: orgCAs.proxySshServerCaPrivateKey.toString("utf8"),
|
||||
clientPublicKey: proxyClientSshPublicKey,
|
||||
keyId: `proxy-client-${proxy.id}`,
|
||||
principals: [gatewayId],
|
||||
certType: SshCertType.USER,
|
||||
requestedTtl: "30d"
|
||||
});
|
||||
|
||||
return {
|
||||
proxyIp: proxy.ip,
|
||||
clientSshCert: proxyClientSshCert.signedPublicKey,
|
||||
clientSshPrivateKey: proxyClientSshPrivateKey,
|
||||
serverCAPublicKey: orgCAs.proxySshServerCaPublicKey.toString("utf8")
|
||||
};
|
||||
};
|
||||
|
||||
const getCredentialsForClient = async ({
|
||||
proxyId,
|
||||
orgId,
|
||||
gatewayId,
|
||||
actor
|
||||
}: {
|
||||
proxyId: string;
|
||||
orgId: string;
|
||||
gatewayId: string;
|
||||
actor: ActorType;
|
||||
}) => {
|
||||
const proxy = await proxyDAL.findOne({
|
||||
id: proxyId
|
||||
});
|
||||
|
||||
if (!proxy) {
|
||||
throw new NotFoundError({
|
||||
message: "Proxy not found"
|
||||
});
|
||||
}
|
||||
|
||||
if (isInstanceProxy(proxy.name)) {
|
||||
const instanceCAs = await $getInstanceCAs();
|
||||
const proxyCertificateCredentials = await $generateProxyClientCredentials({
|
||||
actor,
|
||||
gatewayId,
|
||||
orgId,
|
||||
proxyPkiClientCaCertificate: instanceCAs.instanceProxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaPrivateKey: instanceCAs.instanceProxyPkiClientCaPrivateKey,
|
||||
proxyPkiServerCaCertificate: instanceCAs.instanceProxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaCertificateChain: instanceCAs.instanceProxyPkiServerCaCertificateChain
|
||||
});
|
||||
|
||||
return {
|
||||
...proxyCertificateCredentials,
|
||||
proxyIp: proxy.ip
|
||||
};
|
||||
}
|
||||
|
||||
const orgCAs = await $getOrgCAs(orgId);
|
||||
const proxyCertificateCredentials = await $generateProxyClientCredentials({
|
||||
actor,
|
||||
gatewayId,
|
||||
orgId,
|
||||
proxyPkiClientCaCertificate: orgCAs.proxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaPrivateKey: orgCAs.proxyPkiClientCaPrivateKey,
|
||||
proxyPkiServerCaCertificate: orgCAs.proxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaCertificateChain: orgCAs.proxyPkiServerCaCertificateChain
|
||||
});
|
||||
|
||||
return {
|
||||
...proxyCertificateCredentials,
|
||||
proxyIp: proxy.ip
|
||||
};
|
||||
};
|
||||
|
||||
const registerProxy = async ({
|
||||
ip,
|
||||
name,
|
||||
@@ -837,14 +976,12 @@ export const proxyServiceFactory = ({
|
||||
|
||||
if (isInstanceProxy(name)) {
|
||||
const instanceCAs = await $getInstanceCAs();
|
||||
return $generateProxyCredentials({
|
||||
return $generateProxyServerCredentials({
|
||||
ip,
|
||||
rootProxyPkiCaCertificate: instanceCAs.rootProxyPkiCaCertificate,
|
||||
|
||||
proxyPkiServerCaCertificate: instanceCAs.instanceProxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaPrivateKey: instanceCAs.instanceProxyPkiServerCaPrivateKey,
|
||||
proxyPkiServerCaCertificateChain: instanceCAs.instanceProxyPkiServerCaCertificateChain,
|
||||
|
||||
proxyPkiClientCaCertificate: instanceCAs.instanceProxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaCertificateChain: instanceCAs.instanceProxyPkiClientCaCertificateChain,
|
||||
proxySshServerCaPrivateKey: instanceCAs.instanceProxySshServerCaPrivateKey,
|
||||
proxySshClientCaPublicKey: instanceCAs.instanceProxySshClientCaPublicKey
|
||||
});
|
||||
@@ -852,17 +989,13 @@ export const proxyServiceFactory = ({
|
||||
|
||||
if (proxy.orgId) {
|
||||
const orgCAs = await $getOrgCAs(proxy.orgId);
|
||||
const instanceCAs = await $getInstanceCAs();
|
||||
|
||||
return $generateProxyCredentials({
|
||||
return $generateProxyServerCredentials({
|
||||
ip,
|
||||
orgId: proxy.orgId,
|
||||
rootProxyPkiCaCertificate: instanceCAs.rootProxyPkiCaCertificate,
|
||||
|
||||
proxyPkiServerCaCertificate: orgCAs.proxyPkiServerCaCertificate,
|
||||
proxyPkiServerCaPrivateKey: orgCAs.proxyPkiServerCaPrivateKey,
|
||||
proxyPkiServerCaCertificateChain: orgCAs.proxyPkiServerCaCertificateChain,
|
||||
|
||||
proxyPkiClientCaCertificate: orgCAs.proxyPkiClientCaCertificate,
|
||||
proxyPkiClientCaCertificateChain: orgCAs.proxyPkiClientCaCertificateChain,
|
||||
proxySshServerCaPrivateKey: orgCAs.proxySshServerCaPrivateKey,
|
||||
proxySshClientCaPublicKey: orgCAs.proxySshClientCaPublicKey
|
||||
});
|
||||
@@ -875,6 +1008,7 @@ export const proxyServiceFactory = ({
|
||||
|
||||
return {
|
||||
registerProxy,
|
||||
getCredentialsForGateway
|
||||
getCredentialsForGateway,
|
||||
getCredentialsForClient
|
||||
};
|
||||
};
|
||||
|
||||
@@ -38,6 +38,9 @@ import { externalKmsServiceFactory } from "@app/ee/services/external-kms/externa
|
||||
import { gatewayDALFactory } from "@app/ee/services/gateway/gateway-dal";
|
||||
import { gatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
||||
import { orgGatewayConfigDALFactory } from "@app/ee/services/gateway/org-gateway-config-dal";
|
||||
import { gatewayV2DalFactory } from "@app/ee/services/gateway-v2/gateway-v2-dal";
|
||||
import { gatewayV2ServiceFactory } from "@app/ee/services/gateway-v2/gateway-v2-service";
|
||||
import { orgGatewayConfigV2DalFactory } from "@app/ee/services/gateway-v2/org-gateway-config-v2-dal";
|
||||
import { githubOrgSyncDALFactory } from "@app/ee/services/github-org-sync/github-org-sync-dal";
|
||||
import { githubOrgSyncServiceFactory } from "@app/ee/services/github-org-sync/github-org-sync-service";
|
||||
import { groupDALFactory } from "@app/ee/services/group/group-dal";
|
||||
@@ -72,6 +75,7 @@ import { projectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/proje
|
||||
import { projectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||
import { instanceProxyConfigDalFactory } from "@app/ee/services/proxy/instance-proxy-config-dal";
|
||||
import { orgProxyConfigDalFactory } from "@app/ee/services/proxy/org-proxy-config-dal";
|
||||
import { proxyDalFactory } from "@app/ee/services/proxy/proxy-dal";
|
||||
import { proxyServiceFactory } from "@app/ee/services/proxy/proxy-service";
|
||||
import { rateLimitDALFactory } from "@app/ee/services/rate-limit/rate-limit-dal";
|
||||
import { rateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||
@@ -147,8 +151,6 @@ import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service
|
||||
import { certificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal";
|
||||
import { certificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||
import { certificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal";
|
||||
import { gatewayV2ServiceFactory } from "@app/ee/services/gateway-v2/gateway-v2-service";
|
||||
import { orgGatewayConfigV2DalFactory } from "@app/ee/services/gateway-v2/org-gateway-config-v2-dal";
|
||||
import { certificateServiceFactory } from "@app/services/certificate/certificate-service";
|
||||
import { certificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
||||
import { certificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||
@@ -319,7 +321,6 @@ import { registerV1Routes } from "./v1";
|
||||
import { initializeOauthConfigSync } from "./v1/sso-router";
|
||||
import { registerV2Routes } from "./v2";
|
||||
import { registerV3Routes } from "./v3";
|
||||
import { proxyDalFactory } from "@app/ee/services/proxy/proxy-dal";
|
||||
|
||||
const histogram = monitorEventLoopDelay({ resolution: 20 });
|
||||
histogram.enable();
|
||||
@@ -948,6 +949,7 @@ export const registerRoutes = async (
|
||||
const instanceProxyConfigDAL = instanceProxyConfigDalFactory(db);
|
||||
const orgProxyConfigDAL = orgProxyConfigDalFactory(db);
|
||||
const proxyDAL = proxyDalFactory(db);
|
||||
const gatewayV2DAL = gatewayV2DalFactory(db);
|
||||
|
||||
const orgGatewayConfigV2DAL = orgGatewayConfigV2DalFactory(db);
|
||||
|
||||
@@ -1626,9 +1628,26 @@ export const registerRoutes = async (
|
||||
identityAuthTemplateDAL
|
||||
});
|
||||
|
||||
const dynamicSecretProviders = buildDynamicSecretProviders({
|
||||
gatewayService
|
||||
const proxyService = proxyServiceFactory({
|
||||
instanceProxyConfigDAL,
|
||||
orgProxyConfigDAL,
|
||||
proxyDAL,
|
||||
kmsService
|
||||
});
|
||||
|
||||
const gatewayV2Service = gatewayV2ServiceFactory({
|
||||
kmsService,
|
||||
proxyService,
|
||||
orgGatewayConfigV2DAL,
|
||||
gatewayV2DAL,
|
||||
proxyDAL
|
||||
});
|
||||
|
||||
const dynamicSecretProviders = buildDynamicSecretProviders({
|
||||
gatewayService,
|
||||
gatewayV2Service
|
||||
});
|
||||
|
||||
const dynamicSecretQueueService = dynamicSecretLeaseQueueServiceFactory({
|
||||
queueService,
|
||||
dynamicSecretLeaseDAL,
|
||||
@@ -1648,6 +1667,7 @@ export const registerRoutes = async (
|
||||
licenseService,
|
||||
kmsService,
|
||||
gatewayDAL,
|
||||
gatewayV2DAL,
|
||||
resourceMetadataDAL
|
||||
});
|
||||
|
||||
@@ -1972,19 +1992,6 @@ export const registerRoutes = async (
|
||||
appConnectionDAL
|
||||
});
|
||||
|
||||
const proxyService = proxyServiceFactory({
|
||||
instanceProxyConfigDAL,
|
||||
orgProxyConfigDAL,
|
||||
proxyDAL,
|
||||
kmsService
|
||||
});
|
||||
|
||||
const gatewayV2Service = gatewayV2ServiceFactory({
|
||||
kmsService,
|
||||
proxyService,
|
||||
orgGatewayConfigV2DAL
|
||||
});
|
||||
|
||||
// setup the communication with license key server
|
||||
await licenseService.init();
|
||||
|
||||
|
||||
1
frontend/src/hooks/api/gateways-v2/index.tsx
Normal file
1
frontend/src/hooks/api/gateways-v2/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { gatewaysV2QueryKeys } from "./queries";
|
||||
18
frontend/src/hooks/api/gateways-v2/queries.tsx
Normal file
18
frontend/src/hooks/api/gateways-v2/queries.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { TGatewayV2 } from "./types";
|
||||
|
||||
export const gatewaysV2QueryKeys = {
|
||||
allKey: () => ["gateways-v2"],
|
||||
listKey: () => [...gatewaysV2QueryKeys.allKey(), "list"],
|
||||
list: () =>
|
||||
queryOptions({
|
||||
queryKey: gatewaysV2QueryKeys.listKey(),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ gateways: TGatewayV2[] }>("/api/v2/gateways");
|
||||
return data.gateways;
|
||||
}
|
||||
})
|
||||
};
|
||||
11
frontend/src/hooks/api/gateways-v2/types.ts
Normal file
11
frontend/src/hooks/api/gateways-v2/types.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type TGatewayV2 = {
|
||||
id: string;
|
||||
identityId: string;
|
||||
name: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
identity: {
|
||||
name: string;
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
@@ -2,6 +2,7 @@ import { queryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { TGatewayV2 } from "../gateways-v2/types";
|
||||
import { TGateway } from "./types";
|
||||
|
||||
export const gatewaysQueryKeys = {
|
||||
@@ -12,7 +13,9 @@ export const gatewaysQueryKeys = {
|
||||
queryKey: gatewaysQueryKeys.listKey(),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ gateways: TGateway[] }>("/api/v1/gateways");
|
||||
return data.gateways;
|
||||
const { data: dataV2 } = await apiRequest.get<TGatewayV2[]>("/api/v2/gateways");
|
||||
|
||||
return [...data.gateways, ...dataV2];
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user