From 2911751e96908793dc1b042b07c28bba340f1134 Mon Sep 17 00:00:00 2001 From: "mariano.pizarro" Date: Wed, 6 Apr 2022 09:34:47 -0300 Subject: [PATCH 1/2] feat: Handle TODOs for dynamoDB --- .../cloudFormationStack/connections.ts | 10 +- src/services/cloudFormationStack/format.ts | 2 +- src/services/cognitoUserPool/connections.ts | 144 +++++++++++++++--- src/services/cognitoUserPool/schema.graphql | 10 +- src/services/iamRole/schema.graphql | 1 + src/services/kms/schema.graphql | 1 + src/services/lambda/schema.graphql | 2 +- src/services/ses/schema.graphql | 1 + src/types/generated.ts | 10 +- 9 files changed, 146 insertions(+), 35 deletions(-) diff --git a/src/services/cloudFormationStack/connections.ts b/src/services/cloudFormationStack/connections.ts index f9cd5a23..80bc057b 100644 --- a/src/services/cloudFormationStack/connections.ts +++ b/src/services/cloudFormationStack/connections.ts @@ -1,12 +1,10 @@ import { ServiceConnection } from '@cloudgraph/sdk' import { Stack } from 'aws-sdk/clients/cloudformation' import isEmpty from 'lodash/isEmpty' -import resources from '../../enums/resources' import services from '../../enums/services' import { RawAwsCloudFormationStack } from './data' import { RawAwsIamRole } from '../iamRole/data' import { TagMap } from '../../types' -import { getIamId } from '../../utils/ids' import { globalRegionName } from '../../enums/regions' /** @@ -84,14 +82,10 @@ export default ({ ) if (!isEmpty(dataAtRegion)) { for (const instance of dataAtRegion) { - const { RoleId: roleId, RoleName: roleName } = instance + const { Arn: arn }: RawAwsIamRole = instance connections.push({ - id: getIamId({ - resourceId: roleId, - resourceName: roleName, - resourceType: resources.iamRole, - }), + id: arn, resourceType: services.iamRole, relation: 'child', field: 'iamRole', diff --git a/src/services/cloudFormationStack/format.ts b/src/services/cloudFormationStack/format.ts index a53aeb31..15af402b 100644 --- a/src/services/cloudFormationStack/format.ts +++ b/src/services/cloudFormationStack/format.ts @@ -124,7 +124,7 @@ export default ({ timeoutInMinutes, capabilities, outputs: outputsList, - roleArn: roleArn || '', // TODO: create connection to IAM role if possible + roleArn: roleArn || '', tags: formatTagsFromMap(tags), enableTerminationProtection: enableTerminationProtection ? t.yes : t.no, parentId: parentId || '', diff --git a/src/services/cognitoUserPool/connections.ts b/src/services/cognitoUserPool/connections.ts index 32e81e66..1be0efbb 100644 --- a/src/services/cognitoUserPool/connections.ts +++ b/src/services/cognitoUserPool/connections.ts @@ -1,7 +1,47 @@ -import { UserPoolType } from 'aws-sdk/clients/cognitoidentityserviceprovider'; +import { UserPoolType, LambdaConfigType } from 'aws-sdk/clients/cognitoidentityserviceprovider' -import { ServiceConnection } from '@cloudgraph/sdk'; -import services from '../../enums/services'; +import { ServiceConnection } from '@cloudgraph/sdk' +import { isEmpty } from 'lodash' +import services from '../../enums/services' +import { sesArn } from '../../utils/generateArns' +import { RawAwsLambdaFunction } from '../lambda/data' +import { RawAwsSes } from '../ses/data' +import { RawAwsIamRole } from '../iamRole/data' +import { AwsKms } from '../kms/data' + +const getLambdasArn = ( + lambdaConfig?: LambdaConfigType +): string[] => { + if (isEmpty(lambdaConfig)) { + return [] + } + + const { + PreSignUp, + CustomMessage, + PostConfirmation, + PreAuthentication, + PostAuthentication, + DefineAuthChallenge, + CreateAuthChallenge, + VerifyAuthChallengeResponse, + PreTokenGeneration, + UserMigration, + } = lambdaConfig + + return [ + PreSignUp, + CustomMessage, + PostConfirmation, + PreAuthentication, + PostAuthentication, + DefineAuthChallenge, + CreateAuthChallenge, + VerifyAuthChallengeResponse, + PreTokenGeneration, + UserMigration, + ]?.filter(l => l) +} /** * Cognito User Pool @@ -11,7 +51,9 @@ export default ({ service: userPool, data, region, + account, }: { + account: string data: { name: string; data: { [property: string]: any[] } }[] service: UserPoolType & { region: string @@ -23,38 +65,104 @@ export default ({ const { Id: id, LambdaConfig: lambdaConfig, + EmailConfiguration: emailConfiguration, + SmsConfiguration: smsConfiguration, } = userPool - const defineAuthChallengeArn = lambdaConfig?.DefineAuthChallenge - /** * Find Lambda Functions - * related to this Auto Scaling Group + * related to this cognito user pool */ + const lambdasArn: string[] = getLambdasArn(lambdaConfig) const lambdas = data.find(({ name }) => name === services.lambda) - if (defineAuthChallengeArn && lambdas?.data?.[region]) { - const lambdaInRegion = lambdas.data[region].find(lambda => - defineAuthChallengeArn === lambda.FunctionArn) - - if (lambdaInRegion) { - const lambdaFunctionArn = lambdaInRegion.FunctionArn + if (lambdasArn?.length > 0 && lambdas?.data?.[region]) { + const lambdasInRegion: RawAwsLambdaFunction[] = lambdas.data[region].filter( + ({ FunctionArn }: RawAwsLambdaFunction) => + lambdasArn.includes(FunctionArn) + ) + if (!isEmpty(lambdasInRegion)) { + for (const lambda of lambdasInRegion) { + connections.push({ + id: lambda.FunctionArn, + resourceType: services.lambda, + relation: 'child', + field: 'lambdas', + }) + } + } + } + + /** + * Find MKS + * related to this cognito user pool + */ + const kmsKeyID = lambdaConfig?.KMSKeyID + const kms = data.find(({ name }) => name === services.kms) + + if (kmsKeyID && kms?.data?.[region]) { + const kmsInRegion: AwsKms = kms.data[region].find( + ({ KeyId }: AwsKms) => kmsKeyID === KeyId + ) + + if (kmsInRegion) { connections.push({ - id: lambdaFunctionArn, - resourceType: services.lambda, + id: kmsInRegion.KeyId, + resourceType: services.kms, relation: 'child', - field: 'lambda', + field: 'kms', }) } } - // TODO Email Sender + /** + * Find SES sender + * related to this cognito user pool + */ + const emailConfigSourceArn = emailConfiguration?.SourceArn + const emails = data.find(({ name }) => name === services.ses) - // TODO SMS Sender + if (emailConfigSourceArn && emails?.data?.[region]) { + const emailInRegion: RawAwsSes = emails.data[region].find( + ({ Identity }: RawAwsSes) => + emailConfigSourceArn === sesArn({ region, account, email: Identity }) + ) + + if (emailInRegion) { + connections.push({ + id: sesArn({ region, account, email: emailInRegion.Identity }), + resourceType: services.ses, + relation: 'child', + field: 'ses', + }) + } + } + + /** + * Find SNS caller + * related to this cognito user pool + */ + const smsConfigSnsCallerArn = smsConfiguration?.SnsCallerArn + const iamRoles = data.find(({ name }) => name === services.iamRole) + + if (smsConfigSnsCallerArn && iamRoles?.data?.[region]) { + const iamRoleInRegion: RawAwsIamRole = iamRoles.data[region].find( + ({ Arn }: RawAwsIamRole) => smsConfigSnsCallerArn === Arn + ) + + if (iamRoleInRegion) { + connections.push({ + id: iamRoleInRegion.Arn, + resourceType: services.iamRole, + relation: 'child', + field: 'iamRole', + }) + } + } const userPoolResult = { [id]: connections, } return userPoolResult -} +} \ No newline at end of file diff --git a/src/services/cognitoUserPool/schema.graphql b/src/services/cognitoUserPool/schema.graphql index ea3ce00a..504b41c4 100644 --- a/src/services/cognitoUserPool/schema.graphql +++ b/src/services/cognitoUserPool/schema.graphql @@ -115,9 +115,9 @@ type awsCognitoUserPool @key(fields: "id") { usernameConfigurationCaseSensitive: String @search(by: [hash, regexp]) accountRecoverySettings: [awsAccountRecoverySetting] tags: [awsRawTag] - lambda: [awsLambda] @hasInverse(field: cognitoUserPool) #change to plural + lambdas: [awsLambda] @hasInverse(field: cognitoUserPools) appSync: [awsAppSync] @hasInverse(field: cognitoUserPool) -} - -# TODO: add connetion to kms -# TODO: add connection to iamRole using SmsConfiguration.SnsCallerArn + kms: [awsKms] @hasInverse(field: cognitoUserPools) + ses: [awsSes] @hasInverse(field: cognitoUserPools) + iamRole: [awsIamRole] @hasInverse(field: cognitoUserPools) +} \ No newline at end of file diff --git a/src/services/iamRole/schema.graphql b/src/services/iamRole/schema.graphql index a1bc288c..c8a57543 100644 --- a/src/services/iamRole/schema.graphql +++ b/src/services/iamRole/schema.graphql @@ -23,4 +23,5 @@ type awsIamRole @key(fields: "id") { sageMakerNotebookInstances: [awsSageMakerNotebookInstance] @hasInverse(field: iamRole) systemsManagerInstances: [awsSystemsManagerInstance] @hasInverse(field: iamRole) iamInstanceProfiles: [awsIamInstanceProfile] @hasInverse(field: iamRole) + cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: iamRole) } diff --git a/src/services/kms/schema.graphql b/src/services/kms/schema.graphql index 65d47713..1edd2596 100644 --- a/src/services/kms/schema.graphql +++ b/src/services/kms/schema.graphql @@ -30,4 +30,5 @@ type awsKms @key(fields: "id"){ dmsReplicationInstances: [awsDmsReplicationInstance] @hasInverse(field: kms) sageMakerNotebookInstances: [awsSageMakerNotebookInstance] @hasInverse(field: kms) rdsClusterSnapshots: [awsRdsClusterSnapshot] @hasInverse(field: kms) + cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: kms) } diff --git a/src/services/lambda/schema.graphql b/src/services/lambda/schema.graphql index 0335cd6f..aa85807e 100644 --- a/src/services/lambda/schema.graphql +++ b/src/services/lambda/schema.graphql @@ -24,7 +24,7 @@ type awsLambda @key(fields: "arn") { securityGroups: [awsSecurityGroup] @hasInverse(field: lambda) subnet: [awsSubnet] @hasInverse(field: lambda) #change to plural vpc: [awsVpc] @hasInverse(field: lambda) - cognitoUserPool: [awsCognitoUserPool] @hasInverse(field: lambda) #change to plural + cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: lambdas) appSync: [awsAppSync] @hasInverse(field: lambda) } diff --git a/src/services/ses/schema.graphql b/src/services/ses/schema.graphql index d7a539cc..f190e56f 100644 --- a/src/services/ses/schema.graphql +++ b/src/services/ses/schema.graphql @@ -5,4 +5,5 @@ type awsSes @key(fields: "arn") { region: String @search(by: [hash, regexp]) email: String @search(by: [hash, regexp]) verificationStatus: String @search(by: [hash, regexp]) + cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: ses) } diff --git a/src/types/generated.ts b/src/types/generated.ts index 2e759360..4dca52cf 100644 --- a/src/types/generated.ts +++ b/src/types/generated.ts @@ -1206,15 +1206,18 @@ export type AwsCognitoUserPool = { emailVerificationMessage?: Maybe; emailVerificationSubject?: Maybe; estimatedNumberOfUsers?: Maybe; + iamRole?: Maybe>>; id: Scalars['String']; - lambda?: Maybe>>; + kms?: Maybe>>; lambdaConfig?: Maybe; + lambdas?: Maybe>>; lastModifiedDate?: Maybe; mfaConfiguration?: Maybe; name?: Maybe; policies?: Maybe; region?: Maybe; schemaAttributes?: Maybe>>; + ses?: Maybe>>; smsAuthenticationMessage?: Maybe; smsConfigurationExternalId?: Maybe; smsConfigurationFailure?: Maybe; @@ -3187,6 +3190,7 @@ export type AwsIamRole = { assumeRolePolicy?: Maybe; cloudFormationStack?: Maybe>>; codebuilds?: Maybe>>; + cognitoUserPools?: Maybe>>; configurationRecorder?: Maybe>>; createdAt?: Maybe; description?: Maybe; @@ -3338,6 +3342,7 @@ export type AwsKms = { cloudtrail?: Maybe>>; cloudwatchLog?: Maybe>>; codebuilds?: Maybe>>; + cognitoUserPools?: Maybe>>; creationDate?: Maybe; customerMasterKeySpec?: Maybe; deletionDate?: Maybe; @@ -3370,7 +3375,7 @@ export type AwsLambda = { accountId: Scalars['String']; appSync?: Maybe>>; arn: Scalars['String']; - cognitoUserPool?: Maybe>>; + cognitoUserPools?: Maybe>>; description?: Maybe; environmentVariables?: Maybe>>; handler?: Maybe; @@ -4034,6 +4039,7 @@ export type AwsServiceBillingInfo = { export type AwsSes = { accountId: Scalars['String']; arn: Scalars['String']; + cognitoUserPools?: Maybe>>; email?: Maybe; id: Scalars['String']; region?: Maybe; From 625701ea2a47b6be8bdf1fe910a541fd6f1ed132 Mon Sep 17 00:00:00 2001 From: "mariano.pizarro" Date: Thu, 7 Apr 2022 09:02:16 -0300 Subject: [PATCH 2/2] feat: Handle TODOs for dynamoDB --- src/types/generated.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/types/generated.ts b/src/types/generated.ts index 6552ad72..5333dd5d 100644 --- a/src/types/generated.ts +++ b/src/types/generated.ts @@ -1153,7 +1153,6 @@ export type AwsCognitoUserPool = AwsBaseService & { emailVerificationSubject?: Maybe; estimatedNumberOfUsers?: Maybe; iamRole?: Maybe>>; - id: Scalars['String']; kms?: Maybe>>; lambdaConfig?: Maybe; lambdas?: Maybe>>; @@ -3168,7 +3167,6 @@ export type AwsKms = AwsBaseService & { export type AwsLambda = AwsBaseService & { appSync?: Maybe>>; - arn: Scalars['String']; cognitoUserPools?: Maybe>>; description?: Maybe; environmentVariables?: Maybe>>; @@ -3767,9 +3765,7 @@ export type AwsServiceBillingInfo = { name: Scalars['String']; }; -export type AwsSes = { - accountId: Scalars['String']; - arn: Scalars['String']; +export type AwsSes = AwsBaseService & { cognitoUserPools?: Maybe>>; email?: Maybe; verificationStatus?: Maybe;