From 5819b8c576995c21d210103e8432915afb61992f Mon Sep 17 00:00:00 2001 From: carlosmonastyrski Date: Tue, 22 Apr 2025 17:40:15 -0300 Subject: [PATCH] PR fix suggestions for aws secret rotations --- .../aws-iam-user-secret-rotation-constants.ts | 2 +- .../aws-iam-user-secret-rotation-fns.ts | 52 ++++++++++--------- .../aws-iam-user-secret-rotation-schemas.ts | 4 +- .../secret-rotation-v2-maps.ts | 2 +- backend/src/lib/api-docs/constants.ts | 2 +- .../aws-connection-router.ts | 12 ++++- .../aws/aws-connection-service.ts | 11 +++- .../platform/secret-rotation/aws-iam.mdx | 4 +- ...sIamUserSecretRotationParametersFields.tsx | 6 +-- .../AwsIamUserSecretRotationReviewFields.tsx | 6 +-- ...UserSecretRotationSecretsMappingFields.tsx | 2 +- .../aws-iam-user-secret-rotation-schema.ts | 2 +- .../src/hooks/api/appConnections/aws/types.ts | 5 +- ...ion.ts => aws-iam-user-secret-rotation.ts} | 2 +- .../api/secretRotationsV2/types/index.ts | 2 +- 15 files changed, 66 insertions(+), 48 deletions(-) rename frontend/src/hooks/api/secretRotationsV2/types/{aws-iam-access-key-rotation.ts => aws-iam-user-secret-rotation.ts} (97%) diff --git a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-constants.ts b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-constants.ts index b4e0928fc..1b36b5f30 100644 --- a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-constants.ts +++ b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-constants.ts @@ -8,7 +8,7 @@ export const AWS_IAM_USER_SECRET_ROTATION_LIST_OPTION: TSecretRotationV2ListItem connection: AppConnection.AWS, template: { secretsMapping: { - accessKeyId: "AWS_ACCESS_KEY", + accessKeyId: "AWS_ACCESS_KEY_ID", secretAccessKey: "AWS_SECRET_ACCESS_KEY" } } diff --git a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-fns.ts b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-fns.ts index 1c6e5d3bb..fe9cd4200 100644 --- a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-fns.ts +++ b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-fns.ts @@ -18,7 +18,7 @@ export const awsIamUserSecretRotationFactory: TRotationFactory< TAwsIamUserSecretRotationGeneratedCredentials > = (secretRotation) => { const { - parameters: { region, clientName }, + parameters: { region, userName }, connection, secretsMapping } = secretRotation; @@ -27,26 +27,29 @@ export const awsIamUserSecretRotationFactory: TRotationFactory< const { credentials } = await getAwsConnectionConfig(connection, region); const iam = new AWS.IAM({ credentials }); - const { AccessKeyMetadata } = await iam.listAccessKeys({ UserName: clientName }).promise(); + const { AccessKeyMetadata } = await iam.listAccessKeys({ UserName: userName }).promise(); if (AccessKeyMetadata && AccessKeyMetadata.length > 0) { - for (const key of AccessKeyMetadata) { - if (key.Status === "Inactive" && key.AccessKeyId) { - // eslint-disable-next-line no-await-in-loop - await iam - .deleteAccessKey({ - UserName: clientName, - AccessKeyId: key.AccessKeyId - }) - .promise(); - } - } + // Delete inactive keys + await Promise.all( + AccessKeyMetadata.map((key) => { + if (key.Status === "Inactive" && key.AccessKeyId) { + return iam + .deleteAccessKey({ + UserName: userName, + AccessKeyId: key.AccessKeyId + }) + .promise(); + } + return Promise.resolve(); + }) + ); const activeKey = AccessKeyMetadata.find((k) => k.Status === "Active"); if (activeKey && activeKey.AccessKeyId) { await iam .updateAccessKey({ - UserName: clientName, + UserName: userName, AccessKeyId: activeKey.AccessKeyId, Status: "Inactive" }) @@ -54,7 +57,7 @@ export const awsIamUserSecretRotationFactory: TRotationFactory< } } - const { AccessKey } = await iam.createAccessKey({ UserName: clientName }).promise(); + const { AccessKey } = await iam.createAccessKey({ UserName: userName }).promise(); return { accessKeyId: AccessKey.AccessKeyId, @@ -77,15 +80,16 @@ export const awsIamUserSecretRotationFactory: TRotationFactory< const { credentials } = await getAwsConnectionConfig(connection, region); const iam = new AWS.IAM({ credentials }); - for (const generatedCredential of generatedCredentials) { - // eslint-disable-next-line no-await-in-loop - await iam - .deleteAccessKey({ - UserName: clientName, - AccessKeyId: generatedCredential.accessKeyId - }) - .promise(); - } + await Promise.all( + generatedCredentials.map((generatedCredential) => + iam + .deleteAccessKey({ + UserName: userName, + AccessKeyId: generatedCredential.accessKeyId + }) + .promise() + ) + ); return callback(); }; diff --git a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-schemas.ts b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-schemas.ts index 70104d93a..007a2534e 100644 --- a/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-schemas.ts +++ b/backend/src/ee/services/secret-rotation-v2/aws-iam-user-secret/aws-iam-user-secret-rotation-schemas.ts @@ -20,11 +20,11 @@ export const AwsIamUserSecretRotationGeneratedCredentialsSchema = z .max(2); const AwsIamUserSecretRotationParametersSchema = z.object({ - clientName: z + userName: z .string() .trim() .min(1, "Client Name Required") - .describe(SecretRotations.PARAMETERS.AWS_IAM_USER_SECRET.clientName), + .describe(SecretRotations.PARAMETERS.AWS_IAM_USER_SECRET.userName), region: z.nativeEnum(AWSRegion).describe(SecretRotations.PARAMETERS.AWS_IAM_USER_SECRET.region) }); diff --git a/backend/src/ee/services/secret-rotation-v2/secret-rotation-v2-maps.ts b/backend/src/ee/services/secret-rotation-v2/secret-rotation-v2-maps.ts index 74aba0017..9af78e19a 100644 --- a/backend/src/ee/services/secret-rotation-v2/secret-rotation-v2-maps.ts +++ b/backend/src/ee/services/secret-rotation-v2/secret-rotation-v2-maps.ts @@ -3,7 +3,7 @@ import { AppConnection } from "@app/services/app-connection/app-connection-enums export const SECRET_ROTATION_NAME_MAP: Record = { [SecretRotation.PostgresCredentials]: "PostgreSQL Credentials", - [SecretRotation.MsSqlCredentials]: "Microsoft SQL Sever Credentials", + [SecretRotation.MsSqlCredentials]: "Microsoft SQL Server Credentials", [SecretRotation.Auth0ClientSecret]: "Auth0 Client Secret", [SecretRotation.AwsIamUserSecret]: "AWS IAM User Secret" }; diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 70c4b743e..c128a99a3 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -2017,7 +2017,7 @@ export const SecretRotations = { clientId: "The client ID of the Auth0 Application to rotate the client secret for." }, AWS_IAM_USER_SECRET: { - clientName: "The name of the client to rotate credentials for.", + userName: "The name of the client to rotate credentials for.", region: "The AWS region to rotate credentials for." } }, diff --git a/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts index ff4ef96f9..3226a6aa8 100644 --- a/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts +++ b/backend/src/server/routes/v1/app-connection-routers/aws-connection-router.ts @@ -69,7 +69,17 @@ export const registerAwsConnectionRouter = async (server: FastifyZodProvider) => schema: { params: z.object({ connectionId: z.string().uuid() - }) + }), + response: { + 200: z.object({ + iamUsers: z + .object({ + UserName: z.string(), + Arn: z.string() + }) + .array() + }) + } }, onRequest: verifyAuth([AuthMode.JWT]), handler: async (req) => { diff --git a/backend/src/services/app-connection/aws/aws-connection-service.ts b/backend/src/services/app-connection/aws/aws-connection-service.ts index 891d12997..369116a9c 100644 --- a/backend/src/services/app-connection/aws/aws-connection-service.ts +++ b/backend/src/services/app-connection/aws/aws-connection-service.ts @@ -78,9 +78,16 @@ const listAwsIamUsers = async (appConnection: TAwsConnection) => { const iam = new AWS.IAM({ credentials }); - const users = await iam.listUsers().promise(); + const userEntries: AWS.IAM.User[] = []; + let userMarker: string | undefined; + do { + // eslint-disable-next-line no-await-in-loop + const response = await iam.listUsers({ MaxItems: 100, Marker: userMarker }).promise(); + userEntries.push(...(response.Users || [])); + userMarker = response.Marker; + } while (userMarker); - return users.Users; + return userEntries; }; export const awsConnectionService = (getAppConnection: TGetAppConnectionFunc) => { diff --git a/docs/documentation/platform/secret-rotation/aws-iam.mdx b/docs/documentation/platform/secret-rotation/aws-iam.mdx index 01ae7e3f7..ee491eb6a 100644 --- a/docs/documentation/platform/secret-rotation/aws-iam.mdx +++ b/docs/documentation/platform/secret-rotation/aws-iam.mdx @@ -114,7 +114,7 @@ In the following steps, we explore the end-to-end workflow for setting up this s "minutes": 29.5 }, "parameters": { - "clientName": "", + "userName": "", "region": "us-east-1" }, "secretsMapping": { @@ -171,7 +171,7 @@ In the following steps, we explore the end-to-end workflow for setting up this s "lastRotationMessage": "", "type": "aws-iam-user-secret", "parameters": { - "clientName": "", + "userName": "", "region": "us-east-1" } } diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AwsIamUserSecretRotationParametersFields.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AwsIamUserSecretRotationParametersFields.tsx index d1429dd55..bc3ce86e8 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AwsIamUserSecretRotationParametersFields.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ParametersFields/AwsIamUserSecretRotationParametersFields.tsx @@ -25,7 +25,7 @@ export const AwsIamUserSecretRotationParametersFields = () => { return ( <> ( { )} /> ( )} - control={control} - name="parameters.region" /> ); diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ReviewFields/AwsIamUserSecretRotationReviewFields.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ReviewFields/AwsIamUserSecretRotationReviewFields.tsx index c685691dc..d84c0753f 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ReviewFields/AwsIamUserSecretRotationReviewFields.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2ReviewFields/AwsIamUserSecretRotationReviewFields.tsx @@ -19,11 +19,11 @@ export const AwsIamUserSecretRotationReviewFields = () => { <> {parameters.region} - {parameters.clientName} + {parameters.userName} - {accessKeyId} - {secretAccessKey} + {accessKeyId} + {secretAccessKey} ); diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2SecretsMappingFields/AwsIamUserSecretRotationSecretsMappingFields.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2SecretsMappingFields/AwsIamUserSecretRotationSecretsMappingFields.tsx index f7b32494d..2c6432122 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2SecretsMappingFields/AwsIamUserSecretRotationSecretsMappingFields.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2SecretsMappingFields/AwsIamUserSecretRotationSecretsMappingFields.tsx @@ -35,7 +35,7 @@ export const AwsIamUserSecretRotationSecretsMappingFields = () => { ) }, { - name: "Client Secret", + name: "Secret Access Key", input: ( ( diff --git a/frontend/src/components/secret-rotations-v2/forms/schemas/aws-iam-user-secret-rotation-schema.ts b/frontend/src/components/secret-rotations-v2/forms/schemas/aws-iam-user-secret-rotation-schema.ts index 799ec22a5..9481d400c 100644 --- a/frontend/src/components/secret-rotations-v2/forms/schemas/aws-iam-user-secret-rotation-schema.ts +++ b/frontend/src/components/secret-rotations-v2/forms/schemas/aws-iam-user-secret-rotation-schema.ts @@ -7,7 +7,7 @@ export const AwsIamUserSecretRotationSchema = z .object({ type: z.literal(SecretRotation.AwsIamUserSecret), parameters: z.object({ - clientName: z.string().trim().min(1, "Client Name required"), + userName: z.string().trim().min(1, "User Name required"), region: z.string().trim().min(1, "Region required") }), secretsMapping: z.object({ diff --git a/frontend/src/hooks/api/appConnections/aws/types.ts b/frontend/src/hooks/api/appConnections/aws/types.ts index 8509344ea..d2c7c39cb 100644 --- a/frontend/src/hooks/api/appConnections/aws/types.ts +++ b/frontend/src/hooks/api/appConnections/aws/types.ts @@ -28,7 +28,4 @@ export type TAwsConnectionListIamUsersResponse = { iamUsers: TAwsConnectionIamUser[]; }; -export type TAwsIamUserSecret = { - arn: string; - UserName: string; -}; +export type TAwsIamUserSecret = TAwsConnectionIamUser; diff --git a/frontend/src/hooks/api/secretRotationsV2/types/aws-iam-access-key-rotation.ts b/frontend/src/hooks/api/secretRotationsV2/types/aws-iam-user-secret-rotation.ts similarity index 97% rename from frontend/src/hooks/api/secretRotationsV2/types/aws-iam-access-key-rotation.ts rename to frontend/src/hooks/api/secretRotationsV2/types/aws-iam-user-secret-rotation.ts index 70d6a74e0..20f1c874c 100644 --- a/frontend/src/hooks/api/secretRotationsV2/types/aws-iam-access-key-rotation.ts +++ b/frontend/src/hooks/api/secretRotationsV2/types/aws-iam-user-secret-rotation.ts @@ -9,7 +9,7 @@ export type TAwsIamUserSecretRotation = TSecretRotationV2Base & { type: SecretRotation.AwsIamUserSecret; parameters: { region: string; - clientName: string; + userName: string; }; secretsMapping: { accessKeyId: string; diff --git a/frontend/src/hooks/api/secretRotationsV2/types/index.ts b/frontend/src/hooks/api/secretRotationsV2/types/index.ts index af860e40e..212175ae0 100644 --- a/frontend/src/hooks/api/secretRotationsV2/types/index.ts +++ b/frontend/src/hooks/api/secretRotationsV2/types/index.ts @@ -8,7 +8,7 @@ import { TAwsIamUserSecretRotation, TAwsIamUserSecretRotationGeneratedCredentialsResponse, TAwsIamUserSecretRotationOption -} from "@app/hooks/api/secretRotationsV2/types/aws-iam-access-key-rotation"; +} from "@app/hooks/api/secretRotationsV2/types/aws-iam-user-secret-rotation"; import { TMsSqlCredentialsRotation, TMsSqlCredentialsRotationGeneratedCredentialsResponse