mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 11:29:21 +00:00
1009 lines
39 KiB
TypeScript
1009 lines
39 KiB
TypeScript
import * as x509 from "@peculiar/x509";
|
|
|
|
import { TRelays } from "@app/db/schemas";
|
|
import { PgSqlLock } from "@app/keystore/keystore";
|
|
import { crypto } from "@app/lib/crypto";
|
|
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
|
import { constructPemChainFromCerts, prependCertToPemChain } from "@app/services/certificate/certificate-fns";
|
|
import { CertExtendedKeyUsage, CertKeyAlgorithm, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
|
import {
|
|
createSerialNumber,
|
|
keyAlgorithmToAlgCfg
|
|
} from "@app/services/certificate-authority/certificate-authority-fns";
|
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
|
import { KmsDataKey } from "@app/services/kms/kms-types";
|
|
|
|
import { createSshCert, createSshKeyPair } from "../ssh/ssh-certificate-authority-fns";
|
|
import { SshCertType } from "../ssh/ssh-certificate-authority-types";
|
|
import { SshCertKeyAlgorithm } from "../ssh-certificate/ssh-certificate-types";
|
|
import { TInstanceRelayConfigDALFactory } from "./instance-relay-config-dal";
|
|
import { TOrgRelayConfigDALFactory } from "./org-relay-config-dal";
|
|
import { TRelayDALFactory } from "./relay-dal";
|
|
import { isInstanceRelay } from "./relay-fns";
|
|
|
|
export type TRelayServiceFactory = ReturnType<typeof relayServiceFactory>;
|
|
|
|
const INSTANCE_RELAY_CONFIG_UUID = "00000000-0000-0000-0000-000000000000";
|
|
|
|
export const relayServiceFactory = ({
|
|
instanceRelayConfigDAL,
|
|
orgRelayConfigDAL,
|
|
relayDAL,
|
|
kmsService
|
|
}: {
|
|
instanceRelayConfigDAL: TInstanceRelayConfigDALFactory;
|
|
orgRelayConfigDAL: TOrgRelayConfigDALFactory;
|
|
relayDAL: TRelayDALFactory;
|
|
kmsService: TKmsServiceFactory;
|
|
}) => {
|
|
const $getInstanceCAs = async () => {
|
|
const instanceConfig = await instanceRelayConfigDAL.transaction(async (tx) => {
|
|
const existingInstanceRelayConfig = await instanceRelayConfigDAL.findById(INSTANCE_RELAY_CONFIG_UUID);
|
|
if (existingInstanceRelayConfig) return existingInstanceRelayConfig;
|
|
|
|
await tx.raw("SELECT pg_advisory_xact_lock(?)", [PgSqlLock.InstanceRelayConfigInit()]);
|
|
|
|
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
|
const rootCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
|
|
// generate root CA
|
|
const rootCaSerialNumber = createSerialNumber();
|
|
const rootCaSkObj = crypto.nativeCrypto.KeyObject.from(rootCaKeys.privateKey);
|
|
const rootCaIssuedAt = new Date();
|
|
const rootCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const rootCaCert = await x509.X509CertificateGenerator.createSelfSigned({
|
|
name: `O=Infisical,CN=Infisical Instance Root Relay CA`,
|
|
serialNumber: rootCaSerialNumber,
|
|
notBefore: rootCaIssuedAt,
|
|
notAfter: rootCaExpiration,
|
|
signingAlgorithm: alg,
|
|
keys: rootCaKeys,
|
|
extensions: [
|
|
// eslint-disable-next-line no-bitwise
|
|
new x509.KeyUsagesExtension(x509.KeyUsageFlags.keyCertSign | x509.KeyUsageFlags.cRLSign, true),
|
|
await x509.SubjectKeyIdentifierExtension.create(rootCaKeys.publicKey)
|
|
]
|
|
});
|
|
|
|
// generate org relay CA
|
|
const orgRelayCaSerialNumber = createSerialNumber();
|
|
const orgRelayCaIssuedAt = new Date();
|
|
const orgRelayCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const orgRelayCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const orgRelayCaSkObj = crypto.nativeCrypto.KeyObject.from(orgRelayCaKeys.privateKey);
|
|
const orgRelayCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: orgRelayCaSerialNumber,
|
|
subject: `O=Infisical,CN=Infisical Organization Relay CA`,
|
|
issuer: rootCaCert.subject,
|
|
notBefore: orgRelayCaIssuedAt,
|
|
notAfter: orgRelayCaExpiration,
|
|
signingKey: rootCaKeys.privateKey,
|
|
publicKey: orgRelayCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 2, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(rootCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(orgRelayCaKeys.publicKey)
|
|
]
|
|
});
|
|
const orgRelayCaChain = constructPemChainFromCerts([rootCaCert]);
|
|
|
|
// generate instance relay CA
|
|
const instanceRelayCaSerialNumber = createSerialNumber();
|
|
const instanceRelayCaIssuedAt = new Date();
|
|
const instanceRelayCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const instanceRelayCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const instanceRelayCaSkObj = crypto.nativeCrypto.KeyObject.from(instanceRelayCaKeys.privateKey);
|
|
const instanceRelayCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: instanceRelayCaSerialNumber,
|
|
subject: `O=Infisical,CN=Infisical Instance Relay CA`,
|
|
issuer: rootCaCert.subject,
|
|
notBefore: instanceRelayCaIssuedAt,
|
|
notAfter: instanceRelayCaExpiration,
|
|
signingKey: rootCaKeys.privateKey,
|
|
publicKey: instanceRelayCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 1, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(rootCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(instanceRelayCaKeys.publicKey)
|
|
]
|
|
});
|
|
const instanceRelayCaChain = constructPemChainFromCerts([rootCaCert]);
|
|
|
|
// generate instance relay client CA
|
|
const instanceRelayClientCaSerialNumber = createSerialNumber();
|
|
const instanceRelayClientCaIssuedAt = new Date();
|
|
const instanceRelayClientCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const instanceRelayClientCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const instanceRelayClientCaSkObj = crypto.nativeCrypto.KeyObject.from(instanceRelayClientCaKeys.privateKey);
|
|
const instanceRelayClientCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: instanceRelayClientCaSerialNumber,
|
|
subject: `O=Infisical,CN=Infisical Instance Relay Client CA`,
|
|
issuer: instanceRelayCaCert.subject,
|
|
notBefore: instanceRelayClientCaIssuedAt,
|
|
notAfter: instanceRelayClientCaExpiration,
|
|
signingKey: instanceRelayCaKeys.privateKey,
|
|
publicKey: instanceRelayClientCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 0, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(instanceRelayCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(instanceRelayClientCaKeys.publicKey)
|
|
]
|
|
});
|
|
const instanceRelayClientCaChain = constructPemChainFromCerts([instanceRelayCaCert, rootCaCert]);
|
|
|
|
// generate instance relay server CA
|
|
const instanceRelayServerCaSerialNumber = createSerialNumber();
|
|
const instanceRelayServerCaIssuedAt = new Date();
|
|
const instanceRelayServerCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const instanceRelayServerCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const instanceRelayServerCaSkObj = crypto.nativeCrypto.KeyObject.from(instanceRelayServerCaKeys.privateKey);
|
|
const instanceRelayServerCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: instanceRelayServerCaSerialNumber,
|
|
subject: `O=Infisical,CN=Infisical Instance Relay Server CA`,
|
|
issuer: instanceRelayCaCert.subject,
|
|
notBefore: instanceRelayServerCaIssuedAt,
|
|
notAfter: instanceRelayServerCaExpiration,
|
|
signingKey: instanceRelayCaKeys.privateKey,
|
|
publicKey: instanceRelayServerCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 0, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(instanceRelayCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(instanceRelayServerCaKeys.publicKey)
|
|
]
|
|
});
|
|
const instanceRelayServerCaChain = constructPemChainFromCerts([instanceRelayCaCert, rootCaCert]);
|
|
|
|
const instanceSshServerCaKeyPair = await createSshKeyPair(SshCertKeyAlgorithm.RSA_2048);
|
|
const instanceSshClientCaKeyPair = await createSshKeyPair(SshCertKeyAlgorithm.RSA_2048);
|
|
|
|
const encryptWithRoot = kmsService.encryptWithRootKey();
|
|
|
|
// root relay CA
|
|
const encryptedRootRelayPkiCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(
|
|
rootCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
);
|
|
const encryptedRootRelayPkiCaCertificate = encryptWithRoot(Buffer.from(rootCaCert.rawData));
|
|
|
|
// org relay CA
|
|
const encryptedOrgRelayPkiCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(
|
|
orgRelayCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
);
|
|
const encryptedOrgRelayPkiCaCertificate = encryptWithRoot(Buffer.from(orgRelayCaCert.rawData));
|
|
const encryptedOrgRelayPkiCaCertificateChain = encryptWithRoot(Buffer.from(orgRelayCaChain));
|
|
|
|
// instance relay CA
|
|
const encryptedInstanceRelayPkiCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(
|
|
instanceRelayCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
);
|
|
const encryptedInstanceRelayPkiCaCertificate = encryptWithRoot(Buffer.from(instanceRelayCaCert.rawData));
|
|
const encryptedInstanceRelayPkiCaCertificateChain = encryptWithRoot(Buffer.from(instanceRelayCaChain));
|
|
|
|
// instance relay client CA
|
|
const encryptedInstanceRelayPkiClientCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(
|
|
instanceRelayClientCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
);
|
|
const encryptedInstanceRelayPkiClientCaCertificate = encryptWithRoot(
|
|
Buffer.from(instanceRelayClientCaCert.rawData)
|
|
);
|
|
const encryptedInstanceRelayPkiClientCaCertificateChain = encryptWithRoot(
|
|
Buffer.from(instanceRelayClientCaChain)
|
|
);
|
|
|
|
// instance relay server CA
|
|
const encryptedInstanceRelayPkiServerCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(
|
|
instanceRelayServerCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
);
|
|
const encryptedInstanceRelayPkiServerCaCertificate = encryptWithRoot(
|
|
Buffer.from(instanceRelayServerCaCert.rawData)
|
|
);
|
|
const encryptedInstanceRelayPkiServerCaCertificateChain = encryptWithRoot(
|
|
Buffer.from(instanceRelayServerCaChain)
|
|
);
|
|
|
|
const encryptedInstanceRelaySshClientCaPublicKey = encryptWithRoot(
|
|
Buffer.from(instanceSshClientCaKeyPair.publicKey)
|
|
);
|
|
const encryptedInstanceRelaySshClientCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(instanceSshClientCaKeyPair.privateKey)
|
|
);
|
|
|
|
const encryptedInstanceRelaySshServerCaPublicKey = encryptWithRoot(
|
|
Buffer.from(instanceSshServerCaKeyPair.publicKey)
|
|
);
|
|
const encryptedInstanceRelaySshServerCaPrivateKey = encryptWithRoot(
|
|
Buffer.from(instanceSshServerCaKeyPair.privateKey)
|
|
);
|
|
|
|
return instanceRelayConfigDAL.create({
|
|
// @ts-expect-error id is kept as fixed for idempotence and to avoid race condition
|
|
id: INSTANCE_RELAY_CONFIG_UUID,
|
|
encryptedRootRelayPkiCaPrivateKey,
|
|
encryptedRootRelayPkiCaCertificate,
|
|
encryptedInstanceRelayPkiCaPrivateKey,
|
|
encryptedInstanceRelayPkiCaCertificate,
|
|
encryptedInstanceRelayPkiCaCertificateChain,
|
|
encryptedInstanceRelayPkiClientCaPrivateKey,
|
|
encryptedInstanceRelayPkiClientCaCertificate,
|
|
encryptedInstanceRelayPkiClientCaCertificateChain,
|
|
encryptedInstanceRelayPkiServerCaPrivateKey,
|
|
encryptedInstanceRelayPkiServerCaCertificate,
|
|
encryptedInstanceRelayPkiServerCaCertificateChain,
|
|
encryptedOrgRelayPkiCaPrivateKey,
|
|
encryptedOrgRelayPkiCaCertificate,
|
|
encryptedOrgRelayPkiCaCertificateChain,
|
|
encryptedInstanceRelaySshClientCaPublicKey,
|
|
encryptedInstanceRelaySshClientCaPrivateKey,
|
|
encryptedInstanceRelaySshServerCaPublicKey,
|
|
encryptedInstanceRelaySshServerCaPrivateKey
|
|
});
|
|
});
|
|
|
|
// decrypt the instance config
|
|
const decryptWithRoot = kmsService.decryptWithRootKey();
|
|
|
|
// decrypt root relay CA
|
|
const rootRelayPkiCaPrivateKey = decryptWithRoot(instanceConfig.encryptedRootRelayPkiCaPrivateKey);
|
|
const rootRelayPkiCaCertificate = decryptWithRoot(instanceConfig.encryptedRootRelayPkiCaCertificate);
|
|
|
|
// decrypt org relay CA
|
|
const orgRelayPkiCaPrivateKey = decryptWithRoot(instanceConfig.encryptedOrgRelayPkiCaPrivateKey);
|
|
const orgRelayPkiCaCertificate = decryptWithRoot(instanceConfig.encryptedOrgRelayPkiCaCertificate);
|
|
const orgRelayPkiCaCertificateChain = decryptWithRoot(instanceConfig.encryptedOrgRelayPkiCaCertificateChain);
|
|
|
|
// decrypt instance relay CA
|
|
const instanceRelayPkiCaPrivateKey = decryptWithRoot(instanceConfig.encryptedInstanceRelayPkiCaPrivateKey);
|
|
const instanceRelayPkiCaCertificate = decryptWithRoot(instanceConfig.encryptedInstanceRelayPkiCaCertificate);
|
|
const instanceRelayPkiCaCertificateChain = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiCaCertificateChain
|
|
);
|
|
|
|
// decrypt instance relay client CA
|
|
const instanceRelayPkiClientCaPrivateKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiClientCaPrivateKey
|
|
);
|
|
const instanceRelayPkiClientCaCertificate = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiClientCaCertificate
|
|
);
|
|
const instanceRelayPkiClientCaCertificateChain = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiClientCaCertificateChain
|
|
);
|
|
|
|
// decrypt instance relay server CA
|
|
const instanceRelayPkiServerCaPrivateKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiServerCaPrivateKey
|
|
);
|
|
const instanceRelayPkiServerCaCertificate = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiServerCaCertificate
|
|
);
|
|
const instanceRelayPkiServerCaCertificateChain = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelayPkiServerCaCertificateChain
|
|
);
|
|
|
|
// decrypt SSH keys
|
|
const instanceRelaySshClientCaPublicKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelaySshClientCaPublicKey
|
|
);
|
|
const instanceRelaySshClientCaPrivateKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelaySshClientCaPrivateKey
|
|
);
|
|
const instanceRelaySshServerCaPublicKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelaySshServerCaPublicKey
|
|
);
|
|
const instanceRelaySshServerCaPrivateKey = decryptWithRoot(
|
|
instanceConfig.encryptedInstanceRelaySshServerCaPrivateKey
|
|
);
|
|
|
|
return {
|
|
rootRelayPkiCaPrivateKey,
|
|
rootRelayPkiCaCertificate,
|
|
orgRelayPkiCaPrivateKey,
|
|
orgRelayPkiCaCertificate,
|
|
orgRelayPkiCaCertificateChain,
|
|
instanceRelayPkiCaPrivateKey,
|
|
instanceRelayPkiCaCertificate,
|
|
instanceRelayPkiCaCertificateChain,
|
|
instanceRelayPkiClientCaPrivateKey,
|
|
instanceRelayPkiClientCaCertificate,
|
|
instanceRelayPkiClientCaCertificateChain,
|
|
instanceRelayPkiServerCaPrivateKey,
|
|
instanceRelayPkiServerCaCertificate,
|
|
instanceRelayPkiServerCaCertificateChain,
|
|
instanceRelaySshClientCaPublicKey,
|
|
instanceRelaySshClientCaPrivateKey,
|
|
instanceRelaySshServerCaPublicKey,
|
|
instanceRelaySshServerCaPrivateKey
|
|
};
|
|
};
|
|
|
|
const $getOrgCAs = async (orgId: string) => {
|
|
const instanceCAs = await $getInstanceCAs();
|
|
const { encryptor: orgKmsEncryptor, decryptor: orgKmsDecryptor } = await kmsService.createCipherPairWithDataKey({
|
|
type: KmsDataKey.Organization,
|
|
orgId
|
|
});
|
|
|
|
const orgRelayConfig = await orgRelayConfigDAL.transaction(async (tx) => {
|
|
const existingOrgRelayConfig = await orgRelayConfigDAL.findOne(
|
|
{
|
|
orgId
|
|
},
|
|
tx
|
|
);
|
|
|
|
if (existingOrgRelayConfig) {
|
|
return existingOrgRelayConfig;
|
|
}
|
|
|
|
await tx.raw("SELECT pg_advisory_xact_lock(?)", [PgSqlLock.OrgRelayConfigInit(orgId)]);
|
|
|
|
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
|
const orgRelayCaCert = new x509.X509Certificate(instanceCAs.orgRelayPkiCaCertificate);
|
|
const rootRelayCaCert = new x509.X509Certificate(instanceCAs.rootRelayPkiCaCertificate);
|
|
const orgRelayCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
|
key: instanceCAs.orgRelayPkiCaPrivateKey,
|
|
format: "der",
|
|
type: "pkcs8"
|
|
});
|
|
const orgRelayCaPrivateKey = await crypto.nativeCrypto.subtle.importKey(
|
|
"pkcs8",
|
|
orgRelayCaSkObj.export({ format: "der", type: "pkcs8" }),
|
|
alg,
|
|
true,
|
|
["sign"]
|
|
);
|
|
|
|
// generate org relay client CA
|
|
const orgRelayClientCaSerialNumber = createSerialNumber();
|
|
const orgRelayClientCaIssuedAt = new Date();
|
|
const orgRelayClientCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const orgRelayClientCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const orgRelayClientCaSkObj = crypto.nativeCrypto.KeyObject.from(orgRelayClientCaKeys.privateKey);
|
|
const orgRelayClientCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: orgRelayClientCaSerialNumber,
|
|
subject: `O=${orgId},CN=Infisical Org Relay Client CA`,
|
|
issuer: orgRelayCaCert.subject,
|
|
notBefore: orgRelayClientCaIssuedAt,
|
|
notAfter: orgRelayClientCaExpiration,
|
|
signingKey: orgRelayCaPrivateKey,
|
|
publicKey: orgRelayClientCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 0, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(orgRelayCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(orgRelayClientCaKeys.publicKey)
|
|
]
|
|
});
|
|
const orgRelayClientCaChain = constructPemChainFromCerts([orgRelayCaCert, rootRelayCaCert]);
|
|
|
|
// generate org SSH CA
|
|
const orgSshServerCaKeyPair = await createSshKeyPair(SshCertKeyAlgorithm.RSA_2048);
|
|
const orgSshClientCaKeyPair = await createSshKeyPair(SshCertKeyAlgorithm.RSA_2048);
|
|
|
|
// generate org relay server CA
|
|
const orgRelayServerCaSerialNumber = createSerialNumber();
|
|
const orgRelayServerCaIssuedAt = new Date();
|
|
const orgRelayServerCaExpiration = new Date(new Date().setFullYear(2045));
|
|
const orgRelayServerCaKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const orgRelayServerCaSkObj = crypto.nativeCrypto.KeyObject.from(orgRelayServerCaKeys.privateKey);
|
|
const orgRelayServerCaCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: orgRelayServerCaSerialNumber,
|
|
subject: `O=${orgId},CN=Infisical Org Relay Server CA`,
|
|
issuer: orgRelayCaCert.subject,
|
|
notBefore: orgRelayServerCaIssuedAt,
|
|
notAfter: orgRelayServerCaExpiration,
|
|
signingKey: orgRelayCaPrivateKey,
|
|
publicKey: orgRelayServerCaKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: [
|
|
new x509.KeyUsagesExtension(
|
|
// eslint-disable-next-line no-bitwise
|
|
x509.KeyUsageFlags.keyCertSign |
|
|
x509.KeyUsageFlags.cRLSign |
|
|
x509.KeyUsageFlags.digitalSignature |
|
|
x509.KeyUsageFlags.keyEncipherment,
|
|
true
|
|
),
|
|
new x509.BasicConstraintsExtension(true, 0, true),
|
|
await x509.AuthorityKeyIdentifierExtension.create(orgRelayCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(orgRelayServerCaKeys.publicKey)
|
|
]
|
|
});
|
|
const orgRelayServerCaChain = constructPemChainFromCerts([orgRelayCaCert, rootRelayCaCert]);
|
|
|
|
const encryptedRelayPkiClientCaPrivateKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(
|
|
orgRelayClientCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
}).cipherTextBlob;
|
|
const encryptedRelayPkiClientCaCertificate = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgRelayClientCaCert.rawData)
|
|
}).cipherTextBlob;
|
|
|
|
const encryptedRelayPkiClientCaCertificateChain = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgRelayClientCaChain)
|
|
}).cipherTextBlob;
|
|
|
|
const encryptedRelayPkiServerCaPrivateKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(
|
|
orgRelayServerCaSkObj.export({
|
|
type: "pkcs8",
|
|
format: "der"
|
|
})
|
|
)
|
|
}).cipherTextBlob;
|
|
const encryptedRelayPkiServerCaCertificate = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgRelayServerCaCert.rawData)
|
|
}).cipherTextBlob;
|
|
const encryptedRelayPkiServerCaCertificateChain = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgRelayServerCaChain)
|
|
}).cipherTextBlob;
|
|
|
|
const encryptedRelaySshClientCaPublicKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgSshClientCaKeyPair.publicKey)
|
|
}).cipherTextBlob;
|
|
const encryptedRelaySshClientCaPrivateKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgSshClientCaKeyPair.privateKey)
|
|
}).cipherTextBlob;
|
|
|
|
const encryptedRelaySshServerCaPublicKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgSshServerCaKeyPair.publicKey)
|
|
}).cipherTextBlob;
|
|
const encryptedRelaySshServerCaPrivateKey = orgKmsEncryptor({
|
|
plainText: Buffer.from(orgSshServerCaKeyPair.privateKey)
|
|
}).cipherTextBlob;
|
|
|
|
return orgRelayConfigDAL.create({
|
|
orgId,
|
|
encryptedRelayPkiClientCaPrivateKey,
|
|
encryptedRelayPkiClientCaCertificate,
|
|
encryptedRelayPkiClientCaCertificateChain,
|
|
encryptedRelayPkiServerCaPrivateKey,
|
|
encryptedRelayPkiServerCaCertificate,
|
|
encryptedRelayPkiServerCaCertificateChain,
|
|
encryptedRelaySshClientCaPublicKey,
|
|
encryptedRelaySshClientCaPrivateKey,
|
|
encryptedRelaySshServerCaPublicKey,
|
|
encryptedRelaySshServerCaPrivateKey
|
|
});
|
|
});
|
|
|
|
const relayPkiClientCaPrivateKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiClientCaPrivateKey
|
|
});
|
|
const relayPkiClientCaCertificate = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiClientCaCertificate
|
|
});
|
|
const relayPkiClientCaCertificateChain = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiClientCaCertificateChain
|
|
});
|
|
|
|
const relayPkiServerCaPrivateKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiServerCaPrivateKey
|
|
});
|
|
const relayPkiServerCaCertificate = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiServerCaCertificate
|
|
});
|
|
const relayPkiServerCaCertificateChain = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelayPkiServerCaCertificateChain
|
|
});
|
|
|
|
const relaySshClientCaPublicKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelaySshClientCaPublicKey
|
|
});
|
|
const relaySshClientCaPrivateKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelaySshClientCaPrivateKey
|
|
});
|
|
|
|
const relaySshServerCaPublicKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelaySshServerCaPublicKey
|
|
});
|
|
const relaySshServerCaPrivateKey = orgKmsDecryptor({
|
|
cipherTextBlob: orgRelayConfig.encryptedRelaySshServerCaPrivateKey
|
|
});
|
|
|
|
return {
|
|
relayPkiClientCaPrivateKey,
|
|
relayPkiClientCaCertificate,
|
|
relayPkiClientCaCertificateChain,
|
|
relayPkiServerCaPrivateKey,
|
|
relayPkiServerCaCertificate,
|
|
relayPkiServerCaCertificateChain,
|
|
relaySshClientCaPublicKey,
|
|
relaySshClientCaPrivateKey,
|
|
relaySshServerCaPublicKey,
|
|
relaySshServerCaPrivateKey
|
|
};
|
|
};
|
|
|
|
const $generateRelayServerCredentials = async ({
|
|
ip,
|
|
orgId,
|
|
relayPkiServerCaCertificate,
|
|
relayPkiServerCaPrivateKey,
|
|
relayPkiClientCaCertificate,
|
|
relayPkiClientCaCertificateChain,
|
|
relaySshClientCaPublicKey,
|
|
relaySshServerCaPrivateKey
|
|
}: {
|
|
ip: string;
|
|
relayPkiServerCaCertificate: Buffer;
|
|
relayPkiServerCaPrivateKey: Buffer;
|
|
relayPkiClientCaCertificateChain: Buffer;
|
|
relayPkiClientCaCertificate: Buffer;
|
|
relaySshServerCaPrivateKey: Buffer;
|
|
relaySshClientCaPublicKey: Buffer;
|
|
orgId?: string;
|
|
}) => {
|
|
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
|
const relayServerCaCert = new x509.X509Certificate(relayPkiServerCaCertificate);
|
|
const relayClientCaCert = new x509.X509Certificate(relayPkiClientCaCertificate);
|
|
const relayServerCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
|
key: relayPkiServerCaPrivateKey,
|
|
format: "der",
|
|
type: "pkcs8"
|
|
});
|
|
|
|
const relayServerCaPrivateKey = await crypto.nativeCrypto.subtle.importKey(
|
|
"pkcs8",
|
|
relayServerCaSkObj.export({ format: "der", type: "pkcs8" }),
|
|
alg,
|
|
true,
|
|
["sign"]
|
|
);
|
|
|
|
const relayServerKeys = await crypto.nativeCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
|
const relayServerCertIssuedAt = new Date();
|
|
const relayServerCertExpireAt = new Date(new Date().setMonth(new Date().getMonth() + 1));
|
|
const relayServerCertPrivateKey = crypto.nativeCrypto.KeyObject.from(relayServerKeys.privateKey);
|
|
|
|
const relayServerCertExtensions: x509.Extension[] = [
|
|
new x509.BasicConstraintsExtension(false),
|
|
await x509.AuthorityKeyIdentifierExtension.create(relayServerCaCert, false),
|
|
await x509.SubjectKeyIdentifierExtension.create(relayServerKeys.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],
|
|
true
|
|
),
|
|
new x509.ExtendedKeyUsageExtension([x509.ExtendedKeyUsage[CertExtendedKeyUsage.SERVER_AUTH]], true),
|
|
// san
|
|
new x509.SubjectAlternativeNameExtension([{ type: "ip", value: ip }], false)
|
|
];
|
|
|
|
const relayServerSerialNumber = createSerialNumber();
|
|
const relayServerCertificate = await x509.X509CertificateGenerator.create({
|
|
serialNumber: relayServerSerialNumber,
|
|
subject: `CN=${ip},O=${orgId ?? "Infisical"},OU=Relay`,
|
|
issuer: relayServerCaCert.subject,
|
|
notBefore: relayServerCertIssuedAt,
|
|
notAfter: relayServerCertExpireAt,
|
|
signingKey: relayServerCaPrivateKey,
|
|
publicKey: relayServerKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions: relayServerCertExtensions
|
|
});
|
|
|
|
// generate relay server SSH certificate
|
|
const keyAlgorithm = SshCertKeyAlgorithm.RSA_2048;
|
|
const { publicKey: relayServerSshPublicKey, privateKey: relayServerSshPrivateKey } =
|
|
await createSshKeyPair(keyAlgorithm);
|
|
|
|
const relayServerSshCert = await createSshCert({
|
|
caPrivateKey: relaySshServerCaPrivateKey.toString("utf8"),
|
|
clientPublicKey: relayServerSshPublicKey,
|
|
keyId: "relay-server",
|
|
principals: [`${ip}:2222`],
|
|
certType: SshCertType.HOST,
|
|
requestedTtl: "30d"
|
|
});
|
|
|
|
return {
|
|
pki: {
|
|
serverCertificate: relayServerCertificate.toString("pem"),
|
|
serverPrivateKey: relayServerCertPrivateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
|
clientCertificateChain: prependCertToPemChain(
|
|
relayClientCaCert,
|
|
relayPkiClientCaCertificateChain.toString("utf8")
|
|
)
|
|
},
|
|
ssh: {
|
|
serverCertificate: relayServerSshCert.signedPublicKey,
|
|
serverPrivateKey: relayServerSshPrivateKey,
|
|
clientCAPublicKey: relaySshClientCaPublicKey.toString("utf8")
|
|
}
|
|
};
|
|
};
|
|
|
|
const $generateRelayClientCredentials = async ({
|
|
gatewayId,
|
|
orgId,
|
|
relayPkiClientCaCertificate,
|
|
relayPkiClientCaPrivateKey,
|
|
relayPkiServerCaCertificate,
|
|
relayPkiServerCaCertificateChain
|
|
}: {
|
|
gatewayId: string;
|
|
orgId: string;
|
|
relayPkiClientCaCertificate: Buffer;
|
|
relayPkiClientCaPrivateKey: Buffer;
|
|
relayPkiServerCaCertificate: Buffer;
|
|
relayPkiServerCaCertificateChain: Buffer;
|
|
}) => {
|
|
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
|
const relayClientCaCert = new x509.X509Certificate(relayPkiClientCaCertificate);
|
|
const relayServerCaCert = new x509.X509Certificate(relayPkiServerCaCertificate);
|
|
const relayClientCaSkObj = crypto.nativeCrypto.createPrivateKey({
|
|
key: relayPkiClientCaPrivateKey,
|
|
format: "der",
|
|
type: "pkcs8"
|
|
});
|
|
|
|
const importedRelayClientCaPrivateKey = await crypto.nativeCrypto.subtle.importKey(
|
|
"pkcs8",
|
|
relayClientCaSkObj.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();
|
|
|
|
// Build standard extensions
|
|
const extensions: x509.Extension[] = [
|
|
new x509.BasicConstraintsExtension(false),
|
|
await x509.AuthorityKeyIdentifierExtension.create(relayClientCaCert, 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 clientCert = await x509.X509CertificateGenerator.create({
|
|
serialNumber: clientCertSerialNumber,
|
|
subject: `O=${orgId},OU=relay-client,CN=${gatewayId}`,
|
|
issuer: relayClientCaCert.subject,
|
|
notAfter: clientCertExpiration,
|
|
notBefore: clientCertIssuedAt,
|
|
signingKey: importedRelayClientCaPrivateKey,
|
|
publicKey: clientKeys.publicKey,
|
|
signingAlgorithm: alg,
|
|
extensions
|
|
});
|
|
|
|
return {
|
|
clientCertificate: clientCert.toString("pem"),
|
|
clientPrivateKey: clientCertPrivateKey.export({ format: "pem", type: "pkcs8" }).toString(),
|
|
serverCertificateChain: prependCertToPemChain(
|
|
relayServerCaCert,
|
|
relayPkiServerCaCertificateChain.toString("utf8")
|
|
)
|
|
};
|
|
};
|
|
|
|
const getCredentialsForGateway = async ({
|
|
relayName,
|
|
orgId,
|
|
gatewayId
|
|
}: {
|
|
relayName: string;
|
|
orgId: string;
|
|
gatewayId: string;
|
|
}) => {
|
|
let relay: TRelays | null;
|
|
if (isInstanceRelay(relayName)) {
|
|
relay = await relayDAL.findOne({
|
|
name: relayName
|
|
});
|
|
} else {
|
|
relay = await relayDAL.findOne({
|
|
orgId,
|
|
name: relayName
|
|
});
|
|
}
|
|
|
|
if (!relay) {
|
|
throw new NotFoundError({
|
|
message: "Relay not found"
|
|
});
|
|
}
|
|
|
|
const keyAlgorithm = SshCertKeyAlgorithm.RSA_2048;
|
|
const { publicKey: relayClientSshPublicKey, privateKey: relayClientSshPrivateKey } =
|
|
await createSshKeyPair(keyAlgorithm);
|
|
|
|
if (isInstanceRelay(relayName)) {
|
|
const instanceCAs = await $getInstanceCAs();
|
|
const relayClientSshCert = await createSshCert({
|
|
caPrivateKey: instanceCAs.instanceRelaySshClientCaPrivateKey.toString("utf8"),
|
|
clientPublicKey: relayClientSshPublicKey,
|
|
keyId: `client-${relayName}`,
|
|
principals: [gatewayId],
|
|
certType: SshCertType.USER,
|
|
requestedTtl: "30d"
|
|
});
|
|
|
|
return {
|
|
relayIp: relay.ip,
|
|
clientSshCert: relayClientSshCert.signedPublicKey,
|
|
clientSshPrivateKey: relayClientSshPrivateKey,
|
|
serverCAPublicKey: instanceCAs.instanceRelaySshServerCaPublicKey.toString("utf8")
|
|
};
|
|
}
|
|
|
|
const orgCAs = await $getOrgCAs(orgId);
|
|
const relayClientSshCert = await createSshCert({
|
|
caPrivateKey: orgCAs.relaySshClientCaPrivateKey.toString("utf8"),
|
|
clientPublicKey: relayClientSshPublicKey,
|
|
keyId: `relay-client-${relay.id}`,
|
|
principals: [gatewayId],
|
|
certType: SshCertType.USER,
|
|
requestedTtl: "30d"
|
|
});
|
|
|
|
return {
|
|
relayIp: relay.ip,
|
|
clientSshCert: relayClientSshCert.signedPublicKey,
|
|
clientSshPrivateKey: relayClientSshPrivateKey,
|
|
serverCAPublicKey: orgCAs.relaySshServerCaPublicKey.toString("utf8")
|
|
};
|
|
};
|
|
|
|
const getCredentialsForClient = async ({
|
|
relayId,
|
|
orgId,
|
|
gatewayId
|
|
}: {
|
|
relayId: string;
|
|
orgId: string;
|
|
gatewayId: string;
|
|
}) => {
|
|
const relay = await relayDAL.findOne({
|
|
id: relayId
|
|
});
|
|
|
|
if (!relay) {
|
|
throw new NotFoundError({
|
|
message: "Relay not found"
|
|
});
|
|
}
|
|
|
|
if (isInstanceRelay(relay.name)) {
|
|
const instanceCAs = await $getInstanceCAs();
|
|
const relayCertificateCredentials = await $generateRelayClientCredentials({
|
|
gatewayId,
|
|
orgId,
|
|
relayPkiClientCaCertificate: instanceCAs.instanceRelayPkiClientCaCertificate,
|
|
relayPkiClientCaPrivateKey: instanceCAs.instanceRelayPkiClientCaPrivateKey,
|
|
relayPkiServerCaCertificate: instanceCAs.instanceRelayPkiServerCaCertificate,
|
|
relayPkiServerCaCertificateChain: instanceCAs.instanceRelayPkiServerCaCertificateChain
|
|
});
|
|
|
|
return {
|
|
...relayCertificateCredentials,
|
|
relayIp: relay.ip
|
|
};
|
|
}
|
|
|
|
const orgCAs = await $getOrgCAs(orgId);
|
|
const relayCertificateCredentials = await $generateRelayClientCredentials({
|
|
gatewayId,
|
|
orgId,
|
|
relayPkiClientCaCertificate: orgCAs.relayPkiClientCaCertificate,
|
|
relayPkiClientCaPrivateKey: orgCAs.relayPkiClientCaPrivateKey,
|
|
relayPkiServerCaCertificate: orgCAs.relayPkiServerCaCertificate,
|
|
relayPkiServerCaCertificateChain: orgCAs.relayPkiServerCaCertificateChain
|
|
});
|
|
|
|
return {
|
|
...relayCertificateCredentials,
|
|
relayIp: relay.ip
|
|
};
|
|
};
|
|
|
|
const registerRelay = async ({
|
|
ip,
|
|
name,
|
|
identityId,
|
|
orgId
|
|
}: {
|
|
ip: string;
|
|
name: string;
|
|
identityId?: string;
|
|
orgId?: string;
|
|
}) => {
|
|
let relay: TRelays;
|
|
const isOrgRelay = identityId && orgId;
|
|
|
|
if (isOrgRelay) {
|
|
if (isInstanceRelay(name)) {
|
|
throw new BadRequestError({
|
|
message: "Org relay name cannot start with 'infisical-'. This is reserved for internal use."
|
|
});
|
|
}
|
|
|
|
relay = await relayDAL.transaction(async (tx) => {
|
|
const existingRelay = await relayDAL.findOne(
|
|
{
|
|
identityId,
|
|
orgId
|
|
},
|
|
tx
|
|
);
|
|
|
|
if (existingRelay && (existingRelay.ip !== ip || existingRelay.name !== name)) {
|
|
throw new BadRequestError({
|
|
message: "Org relay with this machine identity already exists."
|
|
});
|
|
}
|
|
|
|
if (!existingRelay) {
|
|
return relayDAL.create(
|
|
{
|
|
ip,
|
|
name,
|
|
identityId,
|
|
orgId
|
|
},
|
|
tx
|
|
);
|
|
}
|
|
|
|
return existingRelay;
|
|
});
|
|
} else {
|
|
if (!isInstanceRelay(name)) {
|
|
throw new BadRequestError({
|
|
message: "Instance relay name must start with 'infisical-'."
|
|
});
|
|
}
|
|
|
|
relay = await relayDAL.transaction(async (tx) => {
|
|
const existingRelay = await relayDAL.findOne(
|
|
{
|
|
name
|
|
},
|
|
tx
|
|
);
|
|
|
|
if (existingRelay && existingRelay.ip !== ip) {
|
|
throw new BadRequestError({
|
|
message: "Instance relay with this name already exists with a different IP address"
|
|
});
|
|
}
|
|
|
|
if (!existingRelay) {
|
|
return relayDAL.create(
|
|
{
|
|
ip,
|
|
name
|
|
},
|
|
tx
|
|
);
|
|
}
|
|
|
|
return existingRelay;
|
|
});
|
|
}
|
|
|
|
if (isInstanceRelay(name)) {
|
|
const instanceCAs = await $getInstanceCAs();
|
|
return $generateRelayServerCredentials({
|
|
ip,
|
|
relayPkiServerCaCertificate: instanceCAs.instanceRelayPkiServerCaCertificate,
|
|
relayPkiServerCaPrivateKey: instanceCAs.instanceRelayPkiServerCaPrivateKey,
|
|
relayPkiClientCaCertificate: instanceCAs.instanceRelayPkiClientCaCertificate,
|
|
relayPkiClientCaCertificateChain: instanceCAs.instanceRelayPkiClientCaCertificateChain,
|
|
relaySshServerCaPrivateKey: instanceCAs.instanceRelaySshServerCaPrivateKey,
|
|
relaySshClientCaPublicKey: instanceCAs.instanceRelaySshClientCaPublicKey
|
|
});
|
|
}
|
|
|
|
if (relay.orgId) {
|
|
const orgCAs = await $getOrgCAs(relay.orgId);
|
|
return $generateRelayServerCredentials({
|
|
ip,
|
|
orgId: relay.orgId,
|
|
relayPkiServerCaCertificate: orgCAs.relayPkiServerCaCertificate,
|
|
relayPkiServerCaPrivateKey: orgCAs.relayPkiServerCaPrivateKey,
|
|
relayPkiClientCaCertificate: orgCAs.relayPkiClientCaCertificate,
|
|
relayPkiClientCaCertificateChain: orgCAs.relayPkiClientCaCertificateChain,
|
|
relaySshServerCaPrivateKey: orgCAs.relaySshServerCaPrivateKey,
|
|
relaySshClientCaPublicKey: orgCAs.relaySshClientCaPublicKey
|
|
});
|
|
}
|
|
|
|
throw new BadRequestError({
|
|
message: "Unhandled relay type"
|
|
});
|
|
};
|
|
|
|
return {
|
|
registerRelay,
|
|
getCredentialsForGateway,
|
|
getCredentialsForClient
|
|
};
|
|
};
|