feat: updated integration api and queue to support aws secret manager assume role feature

This commit is contained in:
=
2024-06-26 22:33:49 +05:30
parent 2e3aedc62b
commit 58f6c6b409
12 changed files with 1207 additions and 12 deletions
@@ -17,14 +17,17 @@ import {
UntagResourceCommand,
UpdateSecretCommand
} from "@aws-sdk/client-secrets-manager";
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
import { Octokit } from "@octokit/rest";
import AWS, { AWSError } from "aws-sdk";
import { AxiosError } from "axios";
import { randomUUID } from "crypto";
import sodium from "libsodium-wrappers";
import isEqual from "lodash.isequal";
import { z } from "zod";
import { SecretType, TIntegrationAuths, TIntegrations, TSecrets } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
@@ -695,24 +698,61 @@ const syncSecretsAWSSecretManager = async ({
integration,
secrets,
accessId,
accessToken
accessToken,
awsAssumeRoleArn,
projectId
}: {
integration: TIntegrations;
secrets: Record<string, { value: string; comment?: string }>;
accessId: string | null;
accessToken: string;
awsAssumeRoleArn: string | null;
projectId?: string;
}) => {
const appCfg = getConfig();
const metadata = z.record(z.any()).parse(integration.metadata || {});
if (!accessId) {
throw new Error("AWS access ID is required");
if (!accessId && !awsAssumeRoleArn) {
throw new Error("AWS access ID/AWS Assume Role is required");
}
let accessKeyId = "";
let secretAccessKey = "";
let sessionToken;
if (awsAssumeRoleArn) {
if (!appCfg.CLIENT_ID_AWS_INTEGRATION || !appCfg.CLIENT_SECRET_AWS_INTEGRATION)
throw new Error("Missing AWS Credentials for Assuming Role. Contact server admin.");
const client = new STSClient({
region: integration.region as string,
credentials: {
accessKeyId: appCfg.CLIENT_ID_AWS_INTEGRATION,
secretAccessKey: appCfg.CLIENT_SECRET_AWS_INTEGRATION
}
});
const command = new AssumeRoleCommand({
RoleArn: awsAssumeRoleArn,
RoleSessionName: `infisical-sm-${randomUUID()}`,
DurationSeconds: 900, // 15mins
ExternalId: projectId
});
const response = await client.send(command);
if (!response.Credentials?.AccessKeyId || !response.Credentials?.SecretAccessKey)
throw new Error("Failed to assume role");
accessKeyId = response.Credentials?.AccessKeyId;
secretAccessKey = response.Credentials?.SecretAccessKey;
sessionToken = response.Credentials?.SessionToken;
} else {
accessKeyId = accessId as string;
secretAccessKey = accessToken;
}
const secretsManager = new SecretsManagerClient({
region: integration.region as string,
credentials: {
accessKeyId: accessId,
secretAccessKey: accessToken
accessKeyId,
secretAccessKey,
sessionToken
}
});
@@ -3568,7 +3608,9 @@ export const syncIntegrationSecrets = async ({
secrets,
accessId,
accessToken,
appendices
awsAssumeRoleArn,
appendices,
projectId
}: {
createManySecretsRawFn: (params: TCreateManySecretsRawFn) => Promise<Array<TSecrets & { _id: string }>>;
updateManySecretsRawFn: (params: TUpdateManySecretsRawFn) => Promise<Array<TSecrets & { _id: string }>>;
@@ -3585,8 +3627,10 @@ export const syncIntegrationSecrets = async ({
integrationAuth: TIntegrationAuths;
secrets: Record<string, { value: string; comment?: string }>;
accessId: string | null;
awsAssumeRoleArn: string | null;
accessToken: string;
appendices?: { prefix: string; suffix: string };
projectId?: string;
}) => {
let response: { isSynced: boolean; syncMessage: string } | null = null;
@@ -3620,7 +3664,9 @@ export const syncIntegrationSecrets = async ({
integration,
secrets,
accessId,
accessToken
accessToken,
awsAssumeRoleArn,
projectId
});
break;
case Integrations.HEROKU: