mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 04:29:36 +00:00
feature: app connections
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { AppConnection } from "@app/lib/app-connections";
|
||||
import { APP_CONNECTION_NAME_MAP } from "@app/lib/app-connections/maps";
|
||||
|
||||
export const GROUPS = {
|
||||
CREATE: {
|
||||
name: "The name of the group to create.",
|
||||
@@ -1515,3 +1518,32 @@ export const ProjectTemplates = {
|
||||
templateId: "The ID of the project template to be deleted."
|
||||
}
|
||||
};
|
||||
|
||||
export const AppConnections = {
|
||||
GET_BY_ID: (app: AppConnection) => ({
|
||||
connectionId: `The ID of the ${APP_CONNECTION_NAME_MAP[app]} Connection to retrieve.`
|
||||
}),
|
||||
GET_BY_NAME: (app: AppConnection) => ({
|
||||
connectionName: `The name of the ${APP_CONNECTION_NAME_MAP[app]} Connection to retrieve.`
|
||||
}),
|
||||
CREATE: (app: AppConnection) => {
|
||||
const appName = APP_CONNECTION_NAME_MAP[app];
|
||||
return {
|
||||
name: `The name of the ${appName} Connection to create. Must be slug-friendly.`,
|
||||
credentials: `The credentials used to connect with ${appName}.`,
|
||||
method: `The method used to authenticate with ${appName}.`
|
||||
};
|
||||
},
|
||||
UPDATE: (app: AppConnection) => {
|
||||
const appName = APP_CONNECTION_NAME_MAP[app];
|
||||
return {
|
||||
connectionId: `The ID of the ${appName} Connection to be updated.`,
|
||||
name: `The updated name of the ${appName} Connection. Must be slug-friendly.`,
|
||||
credentials: `The credentials used to connect with ${appName}.`,
|
||||
method: `The method used to authenticate with ${appName}.`
|
||||
};
|
||||
},
|
||||
DELETE: (app: AppConnection) => ({
|
||||
connectionId: `The ID of the ${app} connection to be deleted.`
|
||||
})
|
||||
};
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum AppConnection {
|
||||
GitHub = "github",
|
||||
AWS = "aws"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { TAwsConnection } from "@app/lib/app-connections/aws/aws-connection-types";
|
||||
import { TGitHubConnection, TGitHubConnectionInput } from "@app/lib/app-connections/github";
|
||||
import { DiscriminativePick } from "@app/lib/types";
|
||||
|
||||
import { AppConnection } from "./app-connection-enums";
|
||||
|
||||
export type AppConnectionListItem = {
|
||||
app: AppConnection;
|
||||
name: string;
|
||||
methods: string[];
|
||||
};
|
||||
|
||||
export type TAppConnection = { id: string } & (TAwsConnection | TGitHubConnection);
|
||||
|
||||
export type TAppConnectionInput = { id: string } & (TAwsConnection | TGitHubConnectionInput);
|
||||
|
||||
export type TCreateAppConnectionDTO = Pick<TAppConnectionInput, "credentials" | "method" | "name" | "app">;
|
||||
|
||||
export type TUpdateAppConnectionDTO = Partial<Omit<TCreateAppConnectionDTO, "method" | "app">> & {
|
||||
connectionId: string;
|
||||
};
|
||||
|
||||
export type TAppConnectionConfig = { orgId: string } & DiscriminativePick<
|
||||
TAppConnectionInput,
|
||||
"app" | "method" | "credentials"
|
||||
>;
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum AwsConnectionMethod {
|
||||
AssumeRole = "assume-role",
|
||||
AccessKey = "access-key"
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
|
||||
import AWS from "aws-sdk";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
import { AppConnection } from "@app/lib/app-connections/app-connection-enums";
|
||||
import { TAwsConnectionConfig } from "@app/lib/app-connections/aws/aws-connection-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
||||
|
||||
import { AwsConnectionMethod } from "./aws-connection-enums";
|
||||
|
||||
export const getAwsAppConnectionListItem = () => {
|
||||
const { INF_APP_CONNECTION_AWS_ACCESS_KEY_ID } = getConfig();
|
||||
|
||||
return {
|
||||
name: "AWS",
|
||||
app: AppConnection.AWS,
|
||||
methods: Object.values(AwsConnectionMethod),
|
||||
accessKeyId: INF_APP_CONNECTION_AWS_ACCESS_KEY_ID
|
||||
};
|
||||
};
|
||||
|
||||
export const getAwsConnectionConfig = async (appConnection: TAwsConnectionConfig, region = "us-east-1") => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
let accessKeyId: string;
|
||||
let secretAccessKey: string;
|
||||
let sessionToken: undefined | string;
|
||||
|
||||
const { method, credentials, orgId } = appConnection;
|
||||
|
||||
switch (method) {
|
||||
case AwsConnectionMethod.AssumeRole: {
|
||||
const client = new STSClient({
|
||||
region,
|
||||
credentials:
|
||||
appCfg.INF_APP_CONNECTION_AWS_ACCESS_KEY_ID && appCfg.INF_APP_CONNECTION_AWS_SECRET_ACCESS_KEY
|
||||
? {
|
||||
accessKeyId: appCfg.INF_APP_CONNECTION_AWS_ACCESS_KEY_ID,
|
||||
secretAccessKey: appCfg.INF_APP_CONNECTION_AWS_SECRET_ACCESS_KEY
|
||||
}
|
||||
: undefined // if hosting on AWS
|
||||
});
|
||||
|
||||
const command = new AssumeRoleCommand({
|
||||
RoleArn: credentials.roleArn,
|
||||
RoleSessionName: `infisical-app-connection-${randomUUID()}`,
|
||||
DurationSeconds: 900, // 15 mins
|
||||
ExternalId: orgId
|
||||
});
|
||||
|
||||
const assumeRes = await client.send(command);
|
||||
|
||||
if (!assumeRes.Credentials?.AccessKeyId || !assumeRes.Credentials?.SecretAccessKey) {
|
||||
throw new BadRequestError({ message: "Failed to assume role - verify credentials and role configuration" });
|
||||
}
|
||||
|
||||
accessKeyId = assumeRes.Credentials.AccessKeyId;
|
||||
secretAccessKey = assumeRes.Credentials.SecretAccessKey;
|
||||
sessionToken = assumeRes.Credentials?.SessionToken;
|
||||
break;
|
||||
}
|
||||
case AwsConnectionMethod.AccessKey: {
|
||||
accessKeyId = credentials.accessKeyId;
|
||||
secretAccessKey = credentials.secretAccessKey;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
throw new InternalServerError({ message: `Unsupported AWS connection method: ${method}` });
|
||||
}
|
||||
|
||||
return new AWS.Config({
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
sessionToken
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const validateAwsConnectionCredentials = async (appConnection: TAwsConnectionConfig) => {
|
||||
const awsConfig = await getAwsConnectionConfig(appConnection);
|
||||
const sts = new AWS.STS(awsConfig);
|
||||
let resp: Awaited<ReturnType<ReturnType<typeof sts.getCallerIdentity>["promise"]>>;
|
||||
|
||||
try {
|
||||
resp = await sts.getCallerIdentity().promise();
|
||||
} catch (e: unknown) {
|
||||
throw new BadRequestError({
|
||||
message: `Unable to validate connection - verify credentials`
|
||||
});
|
||||
}
|
||||
|
||||
if (resp.$response.httpResponse.statusCode !== 200)
|
||||
throw new InternalServerError({
|
||||
message: `Unable to validate credentials: ${
|
||||
resp.$response.error?.message ??
|
||||
`AWS responded with a status code of ${resp.$response.httpResponse.statusCode}. Verify credentials and try again.`
|
||||
}`
|
||||
});
|
||||
|
||||
return appConnection.credentials;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { AppConnections } from "@app/lib/api-docs";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { BaseAppConnectionSchema } from "@app/services/app-connection/app-connection-schemas";
|
||||
|
||||
import { AppConnection } from "../app-connection-enums";
|
||||
import { AwsConnectionMethod } from "./aws-connection-enums";
|
||||
|
||||
export const AwsConnectionAssumeRoleCredentialsSchema = z.object({
|
||||
roleArn: z.string().min(1, "Role ARN required")
|
||||
});
|
||||
|
||||
export const AwsConnectionAccessTokenCredentialsSchema = z.object({
|
||||
accessKeyId: z.string().min(1, "Access Key ID required"),
|
||||
secretAccessKey: z.string().min(1, "Secret Access Key required")
|
||||
});
|
||||
|
||||
const BaseAwsConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.AWS) });
|
||||
|
||||
export const AwsConnectionSchema = z.intersection(
|
||||
BaseAwsConnectionSchema,
|
||||
z.discriminatedUnion("method", [
|
||||
z.object({
|
||||
method: z.literal(AwsConnectionMethod.AssumeRole),
|
||||
credentials: AwsConnectionAssumeRoleCredentialsSchema
|
||||
}),
|
||||
z.object({
|
||||
method: z.literal(AwsConnectionMethod.AccessKey),
|
||||
credentials: AwsConnectionAccessTokenCredentialsSchema
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
export const SanitizedAwsConnectionSchema = z.discriminatedUnion("method", [
|
||||
BaseAwsConnectionSchema.extend({
|
||||
method: z.literal(AwsConnectionMethod.AssumeRole),
|
||||
credentials: AwsConnectionAssumeRoleCredentialsSchema.omit({ roleArn: true })
|
||||
}),
|
||||
BaseAwsConnectionSchema.extend({
|
||||
method: z.literal(AwsConnectionMethod.AccessKey),
|
||||
credentials: AwsConnectionAccessTokenCredentialsSchema.omit({ secretAccessKey: true })
|
||||
})
|
||||
]);
|
||||
|
||||
export const CreateAwsConnectionSchema = z
|
||||
.discriminatedUnion("method", [
|
||||
z.object({
|
||||
method: z.literal(AwsConnectionMethod.AssumeRole).describe(AppConnections.CREATE(AppConnection.AWS).method),
|
||||
credentials: AwsConnectionAssumeRoleCredentialsSchema.describe(
|
||||
AppConnections.CREATE(AppConnection.AWS).credentials
|
||||
)
|
||||
}),
|
||||
z.object({
|
||||
method: z.literal(AwsConnectionMethod.AccessKey).describe(AppConnections.CREATE(AppConnection.AWS).method),
|
||||
credentials: AwsConnectionAccessTokenCredentialsSchema.describe(
|
||||
AppConnections.CREATE(AppConnection.AWS).credentials
|
||||
)
|
||||
})
|
||||
])
|
||||
.and(z.object({ name: slugSchema({ field: "name" }).describe(AppConnections.CREATE(AppConnection.AWS).name) }));
|
||||
|
||||
export const UpdateAwsConnectionSchema = z.object({
|
||||
name: slugSchema({ field: "name" }).optional().describe(AppConnections.UPDATE(AppConnection.AWS).name),
|
||||
credentials: z
|
||||
.union([AwsConnectionAccessTokenCredentialsSchema, AwsConnectionAssumeRoleCredentialsSchema])
|
||||
.optional()
|
||||
.describe(AppConnections.UPDATE(AppConnection.AWS).credentials)
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { DiscriminativePick } from "@app/lib/types";
|
||||
|
||||
import { AwsConnectionSchema } from "./aws-connection-schemas";
|
||||
|
||||
export type TAwsConnection = z.infer<typeof AwsConnectionSchema>;
|
||||
|
||||
export type TAwsConnectionConfig = DiscriminativePick<TAwsConnection, "orgId" | "method" | "app" | "credentials">;
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./aws-connection-enums";
|
||||
export * from "./aws-connection-fns";
|
||||
export * from "./aws-connection-schemas";
|
||||
export * from "./aws-connection-types";
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum GitHubConnectionMethod {
|
||||
OAuth = "oauth",
|
||||
App = "github-app"
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import { AxiosResponse } from "axios";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { BadRequestError, ForbiddenRequestError, InternalServerError } from "@app/lib/errors";
|
||||
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
|
||||
|
||||
import { AppConnection } from "../app-connection-enums";
|
||||
import { APP_CONNECTION_METHOD_NAME_MAP } from "../maps";
|
||||
import { GitHubConnectionMethod } from "./github-connection-enums";
|
||||
import { TGitHubConnectionConfig } from "./github-connection-types";
|
||||
|
||||
export const getGitHubConnectionListItem = () => {
|
||||
const { INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, INF_APP_CONNECTION_GITHUB_APP_SLUG } = getConfig();
|
||||
|
||||
return {
|
||||
name: "GitHub",
|
||||
app: AppConnection.GitHub,
|
||||
methods: Object.values(GitHubConnectionMethod),
|
||||
oauthClientId: INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID,
|
||||
appClientSlug: INF_APP_CONNECTION_GITHUB_APP_SLUG
|
||||
};
|
||||
};
|
||||
|
||||
type TokenRespData = {
|
||||
access_token: string;
|
||||
scope: string;
|
||||
token_type: string;
|
||||
};
|
||||
|
||||
export const validateGitHubConnectionCredentials = async (config: TGitHubConnectionConfig) => {
|
||||
const { credentials, method } = config;
|
||||
|
||||
const {
|
||||
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID,
|
||||
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET,
|
||||
INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID,
|
||||
INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET,
|
||||
SITE_URL
|
||||
} = getConfig();
|
||||
|
||||
const { clientId, clientSecret } =
|
||||
method === GitHubConnectionMethod.App
|
||||
? {
|
||||
clientId: INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID,
|
||||
clientSecret: INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET
|
||||
}
|
||||
: // oauth
|
||||
{
|
||||
clientId: INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID,
|
||||
clientSecret: INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET
|
||||
};
|
||||
|
||||
if (!clientId || !clientSecret) {
|
||||
throw new InternalServerError({
|
||||
message: `GitHub ${APP_CONNECTION_METHOD_NAME_MAP[method]} environment variables have not been configured`
|
||||
});
|
||||
}
|
||||
|
||||
let tokenResp: AxiosResponse<TokenRespData>;
|
||||
|
||||
try {
|
||||
tokenResp = await request.get<TokenRespData>("https://github.com/login/oauth/access_token", {
|
||||
params: {
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
code: credentials.code,
|
||||
redirect_uri: `${SITE_URL}/app-connections/github/oauth/callback`
|
||||
},
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
throw new BadRequestError({
|
||||
message: `Unable to validate connection - verify credentials`
|
||||
});
|
||||
}
|
||||
|
||||
if (tokenResp.status !== 200) {
|
||||
throw new BadRequestError({
|
||||
message: `Unable to validate credentials: GitHub responded with a status code of ${tokenResp.status} (${tokenResp.statusText}). Verify credentials and try again.`
|
||||
});
|
||||
}
|
||||
|
||||
if (method === GitHubConnectionMethod.App) {
|
||||
const installationsResp = await request.get<{
|
||||
installations: {
|
||||
id: number;
|
||||
account: {
|
||||
login: string;
|
||||
};
|
||||
}[];
|
||||
}>(IntegrationUrls.GITHUB_USER_INSTALLATIONS, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${tokenResp.data.access_token}`,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
const matchingInstallation = installationsResp.data.installations.find(
|
||||
(installation) => installation.id === +credentials.installationId
|
||||
);
|
||||
|
||||
if (!matchingInstallation) {
|
||||
throw new ForbiddenRequestError({
|
||||
message: "User does not have access to the provided installation"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case GitHubConnectionMethod.App:
|
||||
return {
|
||||
// access token not needed for GitHub App
|
||||
installationId: credentials.installationId
|
||||
};
|
||||
case GitHubConnectionMethod.OAuth:
|
||||
return {
|
||||
accessToken: tokenResp.data.access_token
|
||||
};
|
||||
default:
|
||||
throw new InternalServerError({
|
||||
message: `Unhandled GitHub connection method: ${method as GitHubConnectionMethod}`
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { AppConnections } from "@app/lib/api-docs";
|
||||
import { AppConnection } from "@app/lib/app-connections";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { BaseAppConnectionSchema } from "@app/services/app-connection/app-connection-schemas";
|
||||
|
||||
import { GitHubConnectionMethod } from "./github-connection-enums";
|
||||
|
||||
export const GitHubConnectionOAuthInputCredentialsSchema = z.object({
|
||||
code: z.string().min(1, "OAuth code required")
|
||||
});
|
||||
|
||||
export const GitHubConnectionAppInputCredentialsSchema = z.object({
|
||||
code: z.string().min(1, "GitHub App code required"),
|
||||
installationId: z.string().min(1, "GitHub App Installation ID required")
|
||||
});
|
||||
|
||||
export const GitHubConnectionOAuthOutputCredentialsSchema = z.object({
|
||||
accessToken: z.string()
|
||||
});
|
||||
|
||||
export const GitHubConnectionAppOutputCredentialsSchema = z.object({
|
||||
installationId: z.string()
|
||||
});
|
||||
|
||||
export const CreateGitHubConnectionSchema = z
|
||||
.discriminatedUnion("method", [
|
||||
z.object({
|
||||
method: z.literal(GitHubConnectionMethod.App).describe(AppConnections.CREATE(AppConnection.GitHub).method),
|
||||
credentials: GitHubConnectionAppInputCredentialsSchema.describe(
|
||||
AppConnections.CREATE(AppConnection.GitHub).credentials
|
||||
)
|
||||
}),
|
||||
z.object({
|
||||
method: z.literal(GitHubConnectionMethod.OAuth).describe(AppConnections.CREATE(AppConnection.GitHub).method),
|
||||
credentials: GitHubConnectionOAuthInputCredentialsSchema.describe(
|
||||
AppConnections.CREATE(AppConnection.GitHub).credentials
|
||||
)
|
||||
})
|
||||
])
|
||||
.and(z.object({ name: slugSchema({ field: "name" }).describe(AppConnections.CREATE(AppConnection.GitHub).name) }));
|
||||
|
||||
export const UpdateGitHubConnectionSchema = z.object({
|
||||
name: slugSchema({ field: "name" }).optional().describe(AppConnections.UPDATE(AppConnection.GitHub).name),
|
||||
credentials: z
|
||||
.union([GitHubConnectionAppInputCredentialsSchema, GitHubConnectionOAuthInputCredentialsSchema])
|
||||
.optional()
|
||||
.describe(AppConnections.UPDATE(AppConnection.GitHub).credentials)
|
||||
});
|
||||
|
||||
const BaseGitHubConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.GitHub) });
|
||||
|
||||
export const GitHubAppConnectionSchema = z.intersection(
|
||||
BaseGitHubConnectionSchema,
|
||||
z.discriminatedUnion("method", [
|
||||
z.object({
|
||||
method: z.literal(GitHubConnectionMethod.App),
|
||||
credentials: GitHubConnectionAppOutputCredentialsSchema
|
||||
}),
|
||||
z.object({
|
||||
method: z.literal(GitHubConnectionMethod.OAuth),
|
||||
credentials: GitHubConnectionOAuthOutputCredentialsSchema
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
export const SanitizedGitHubConnectionSchema = z.discriminatedUnion("method", [
|
||||
BaseGitHubConnectionSchema.extend({
|
||||
method: z.literal(GitHubConnectionMethod.App),
|
||||
credentials: GitHubConnectionAppOutputCredentialsSchema.omit({ installationId: true })
|
||||
}),
|
||||
BaseGitHubConnectionSchema.extend({
|
||||
method: z.literal(GitHubConnectionMethod.OAuth),
|
||||
credentials: GitHubConnectionOAuthOutputCredentialsSchema.omit({ accessToken: true })
|
||||
})
|
||||
]);
|
||||
@@ -0,0 +1,14 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { DiscriminativePick } from "@app/lib/types";
|
||||
|
||||
import { AppConnection } from "../app-connection-enums";
|
||||
import { CreateGitHubConnectionSchema, GitHubAppConnectionSchema } from "./github-connection-schemas";
|
||||
|
||||
export type TGitHubConnectionConfig = DiscriminativePick<TGitHubConnectionInput, "method" | "app" | "credentials">;
|
||||
|
||||
export type TGitHubConnection = z.infer<typeof GitHubAppConnectionSchema>;
|
||||
|
||||
export type TGitHubConnectionInput = z.infer<typeof CreateGitHubConnectionSchema> & {
|
||||
app: AppConnection.GitHub;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./github-connection-enums";
|
||||
export * from "./github-connection-fns";
|
||||
export * from "./github-connection-schemas";
|
||||
export * from "./github-connection-types";
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./app-connection-enums";
|
||||
export * from "./app-connection-types";
|
||||
@@ -0,0 +1,17 @@
|
||||
import { TAppConnection } from "@app/lib/app-connections/app-connection-types";
|
||||
|
||||
import { AppConnection } from "./app-connection-enums";
|
||||
import { AwsConnectionMethod } from "./aws/aws-connection-enums";
|
||||
import { GitHubConnectionMethod } from "./github/github-connection-enums";
|
||||
|
||||
export const APP_CONNECTION_NAME_MAP: Record<AppConnection, string> = {
|
||||
[AppConnection.AWS]: "AWS",
|
||||
[AppConnection.GitHub]: "GitHub"
|
||||
};
|
||||
|
||||
export const APP_CONNECTION_METHOD_NAME_MAP: Record<TAppConnection["method"], string> = {
|
||||
[AwsConnectionMethod.AssumeRole]: "Assume Role",
|
||||
[AwsConnectionMethod.AccessKey]: "Access Key",
|
||||
[GitHubConnectionMethod.App]: "Github App",
|
||||
[GitHubConnectionMethod.OAuth]: "OAuth"
|
||||
};
|
||||
@@ -180,7 +180,24 @@ const envSchema = z
|
||||
HSM_SLOT: z.coerce.number().optional().default(0),
|
||||
|
||||
USE_PG_QUEUE: zodStrBool.default("false"),
|
||||
SHOULD_INIT_PG_QUEUE: zodStrBool.default("false")
|
||||
SHOULD_INIT_PG_QUEUE: zodStrBool.default("false"),
|
||||
|
||||
/* App Connections ----------------------------------------------------------------------------- */
|
||||
|
||||
// aws
|
||||
INF_APP_CONNECTION_AWS_ACCESS_KEY_ID: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_AWS_SECRET_ACCESS_KEY: zpStr(z.string().optional()),
|
||||
|
||||
// github oauth
|
||||
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET: zpStr(z.string().optional()),
|
||||
|
||||
// github app
|
||||
INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_GITHUB_APP_SLUG: zpStr(z.string().optional()),
|
||||
INF_APP_CONNECTION_GITHUB_APP_ID: zpStr(z.string().optional())
|
||||
})
|
||||
// To ensure that basic encryption is always possible.
|
||||
.refine(
|
||||
|
||||
@@ -43,6 +43,8 @@ export type RequiredKeys<T> = {
|
||||
|
||||
export type PickRequired<T> = Pick<T, RequiredKeys<T>>;
|
||||
|
||||
export type DiscriminativePick<T, K extends keyof T> = T extends unknown ? Pick<T, K> : never;
|
||||
|
||||
export enum EnforcementLevel {
|
||||
Hard = "hard",
|
||||
Soft = "soft"
|
||||
|
||||
Reference in New Issue
Block a user