Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
| iamServerCertificate | |
| iamUser | iamGroup |
| iamPolicy | iamRole, iamGroup |
| iamRole | appSync, cloudformationStackSet, codebuild, configurationRecorder, ec2, iamInstanceProfile, iamPolicy, eksCluster, ecsService, flowLog, glueJob, managedAirflow, sageMakerNotebookInstance, systemsManagerInstance guardDutyDetector, lambda, kinesisFirehose, rdsCluster |
| iamRole | appSync, cloudformationStackSet, codebuild, configurationRecorder, ec2, iamInstanceProfile, iamPolicy, eksCluster, ecsService, flowLog, glueJob, managedAirflow, s3, sageMakerNotebookInstance, systemsManagerInstance guardDutyDetector, lambda, kinesisFirehose, rdsCluster |
| iamGroup | iamUser, iamPolicy |
| igw | vpc |
| iot | |
| kinesisFirehose | kinesisStream, s3, iamRole |
| kinesisStream | kinesisFirehose |
| kms | cloudtrail, cloudwatchLog, codebuild, ecsCluster, efs, eksCluster, elastiCacheReplicationGroup, elasticSearchDomain, emrCluster, lambda, rdsClusterSnapshot, sns, sageMakerNotebookInstance, secretsManager, dmsReplicationInstance, redshiftCluster, rdsCluster |
| lambda | appSync, cognitoUserPool, kms, secretsManager, securityGroup, subnet, vpc, iamRole |
| lambda | appSync, cognitoUserPool, kms, s3, secretsManager, securityGroup, subnet, vpc, iamRole |
| managedAirflow | iamRole, securityGroups, subnet, s3 |
| nacl | vpc |
| natGateway | networkInterface, subnet, vpc |
Expand All @@ -147,12 +147,12 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
| sageMakerExperiment | |
| sageMakerNotebookInstance | iamRole, kms, networkInterface, subnet, securityGroup |
| sageMakerProject | |
| s3 | cloudfront, cloudtrail, ecsCluster, kinesisFirehose, managedAirflow |
| s3 | cloudfront, cloudtrail, ecsCluster, iamRole, kinesisFirehose, lambda, managedAirflow, sns, sqs |
| secretsManager | kms, lambda |
| securityGroup | alb, asg, clientVpnEndpoint, codebuild, dmsReplicationInstance, ecsService, lambda, ec2, elasticSearchDomain, elb, rdsCluster, rdsDbInstance, eksCluster, elastiCacheCluster, managedAirflow, sageMakerNotebookInstance |
| ses | |
| sns | kms, cloudtrail, cloudwatch |
| sqs | |
| sns | kms, cloudtrail, cloudwatch, s3 |
| sqs | s3 |
| subnet | alb, asg, codebuild, dmsReplicationInstance, ec2, ecsService, efsMountTarget, elastiCacheCluster, elasticSearchDomain, elb, lambda, managedAirflow, natGateway, networkInterface, sageMakerNotebookInstance, routeTable, vpc, eksCluster, emrCluster, flowLog |
| systemsManagerInstance | ec2, iamRole |
| systemsManagerDocument | |
Expand Down
2 changes: 1 addition & 1 deletion src/services/cloudfront/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type awsCloudfront implements awsBaseService @key(fields: "id") {
origins: [awsCloudfrontOriginData]
logging: awsCloudfrontLoggingConfig
elb: [awsElb] @hasInverse(field: cloudfrontDistribution)
s3: [awsS3] @hasInverse(field: cloudfrontDistribution)
s3: [awsS3] @hasInverse(field: cloudfrontDistributions)
tags: [awsRawTag]
webAcl: [awsWafV2WebAcl] @hasInverse(field: cloudfront)
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/cloudtrail/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type awsCloudtrail implements awsOptionalService @key(fields: "id") {
status: awsCloudtrailStatus
eventSelectors: [awsCloudtrailEventSelector]
tags: [awsRawTag]
s3: [awsS3] @hasInverse(field: cloudtrail)
s3: [awsS3] @hasInverse(field: cloudtrails)
sns: [awsSns] @hasInverse(field: cloudtrail)
kms: [awsKms] @hasInverse(field: cloudtrail)
cloudwatchLog: [awsCloudwatchLog] @hasInverse(field: cloudtrail)
Expand Down
1 change: 1 addition & 0 deletions src/services/iamRole/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type awsIamRole implements awsBaseService @key(fields: "id") {
systemsManagerInstances: [awsSystemsManagerInstance]
@hasInverse(field: iamRole)
iamInstanceProfiles: [awsIamInstanceProfile] @hasInverse(field: iamRole)
s3: [awsS3] @hasInverse(field: iamRole)
dynamodb: [awsDynamoDbTable] @hasInverse(field: iamRoles)
ec2Instances: [awsEc2] @hasInverse(field: iamRole)
cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: iamRole)
Expand Down
1 change: 1 addition & 0 deletions src/services/lambda/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type awsLambda implements awsBaseService @key(fields: "arn") {
vpc: [awsVpc] @hasInverse(field: lambda)
cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: lambdas)
appSync: [awsAppSync] @hasInverse(field: lambda)
s3: [awsS3] @hasInverse(field: lambdas)
secretsManager: [awsSecretsManager] @hasInverse(field: lambda)
iamRole: [awsIamRole] @hasInverse(field: lambda)
}
Expand Down
151 changes: 151 additions & 0 deletions src/services/s3/connections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { ServiceConnection } from '@cloudgraph/sdk'
import isEmpty from 'lodash/isEmpty'
import services from '../../enums/services'
import { RawAwsS3 } from './data'
import { RawAwsIamRole } from '../iamRole/data'
import { RawAwsLambdaFunction } from '../lambda/data'
import { RawAwsSns } from '../sns/data'
import { AwsSqs } from '../sqs/data'
import { globalRegionName } from '../../enums/regions'

/**
* S3
*/

export default ({
service,
data,
region,
}: {
data: { name: string; data: { [property: string]: any[] } }[]
service: RawAwsS3
region: string
}): { [key: string]: ServiceConnection[] } => {
const connections: ServiceConnection[] = []

const {
Id: id,
AdditionalInfo: {
ReplicationConfig: replicationConfig,
NotificationConfiguration: {
LambdaFunctionConfigurations: lambdaFunctionConfigurations,
TopicConfigurations: topicConfigurations,
QueueConfigurations: queueConfigurations,
},
},
} = service

/**
* Find IAM Roles
* related to this S3
*/
const roles: { name: string; data: { [property: string]: any[] } } =
data.find(({ name }) => name === services.iamRole)
if (replicationConfig?.Role && roles?.data?.[globalRegionName]) {
const dataAtRegion: RawAwsIamRole[] = roles.data[globalRegionName].filter(
role => role.Arn === replicationConfig.Role
)
if (!isEmpty(dataAtRegion)) {
for (const instance of dataAtRegion) {
const { Arn: arn }: RawAwsIamRole = instance

connections.push({
id: arn,
resourceType: services.iamRole,
relation: 'child',
field: 'iamRole',
})
}
}
}

/**
* Find lambda functions
* related to this S3
*/
const lambdaFunctions: {
name: string
data: { [property: string]: any[] }
} = data.find(({ name }) => name === services.lambda)

const functionArns = lambdaFunctionConfigurations?.map(
lambdaConfig => lambdaConfig?.LambdaFunctionArn
)

if (!isEmpty(functionArns) && lambdaFunctions?.data?.[region]) {
const dataAtRegion: RawAwsLambdaFunction[] = lambdaFunctions.data[
region
].filter(({ FunctionArn }: RawAwsLambdaFunction) =>
functionArns.includes(FunctionArn)
)

if (!isEmpty(dataAtRegion)) {
for (const lambdaFunction of dataAtRegion) {
const { FunctionArn: functionArn }: RawAwsLambdaFunction =
lambdaFunction
connections.push({
id: functionArn,
resourceType: services.lambda,
relation: 'child',
field: 'lambdas',
})
}
}
}

/**
* Find SNS topic
* related to this S3
*/
const snsTopics = data.find(({ name }) => name === services.sns)
const topicArns = topicConfigurations?.map(topic => topic?.TopicArn)
if (!isEmpty(topicArns) && snsTopics?.data?.[region]) {
const snsTopicsInRegion: RawAwsSns[] = snsTopics.data[region].filter(
({ TopicArn: topicArn }: RawAwsSns) => topicArns.includes(topicArn)
)

if (!isEmpty(snsTopicsInRegion)) {
for (const topic of snsTopicsInRegion) {
const { TopicArn: topicArn }: RawAwsSns = topic
connections.push({
id: topicArn,
resourceType: services.sns,
relation: 'child',
field: 'sns',
})
}
}
}

/**
* Find SQS
* related to this S3
*/
const sqsQueues = data.find(({ name }) => name === services.sqs)
const sqsArns = queueConfigurations?.map(queue => queue?.QueueArn)
if (!isEmpty(sqsArns) && sqsQueues?.data?.[region]) {
const dataAtRegion: AwsSqs[] = sqsQueues.data[region].filter(
({ sqsAttributes: { QueueArn: queueArn } }: AwsSqs) =>
sqsArns.includes(queueArn)
)
if (!isEmpty(dataAtRegion)) {
for (const instance of dataAtRegion) {
const {
sqsAttributes: { QueueArn: queueArn },
}: AwsSqs = instance

connections.push({
id: queueArn,
resourceType: services.sqs,
relation: 'child',
field: 'sqs',
})
}
}
}

const s3Result = {
[id]: connections,
}
return s3Result
}
28 changes: 28 additions & 0 deletions src/services/s3/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import S3, {
ListBucketsOutput,
ListObjectsV2Output,
LoggingEnabled,
NotificationConfiguration,
Object as S3Object,
Owner,
Payer,
Expand Down Expand Up @@ -301,6 +302,29 @@ const getBucketWebsite = async (s3: S3, name: BucketName) =>
)
})

const getBucketNotificationConfiguration = async (s3: S3, name: BucketName) =>
new Promise<NotificationConfiguration | any>(resolve => {
s3.getBucketNotificationConfiguration(
{
Bucket: name,
},
(err: AWSError, data: NotificationConfiguration) => {
if (err) {
errorLog.generateAwsErrorLog({
functionName: 's3:getBucketNotificationConfiguration',
err,
})
}

if (!isEmpty(data)) {
resolve(data)
}

resolve({})
}
)
})

const getBucketAdditionalInfo = async (s3: S3, name: BucketName) =>
new Promise<any>(async resolve => {
const promises = [
Expand All @@ -318,6 +342,7 @@ const getBucketAdditionalInfo = async (s3: S3, name: BucketName) =>
getBucketTagging(s3, name),
getBucketVersioning(s3, name),
getBucketWebsite(s3, name),
getBucketNotificationConfiguration(s3, name),
]

const [
Expand All @@ -335,6 +360,7 @@ const getBucketAdditionalInfo = async (s3: S3, name: BucketName) =>
Tags,
VersioningInfo,
WebsiteInfo,
NotificationConfig,
] = (await Promise.allSettled(promises)).map(
/** We force the PromiseFulfilledResult interface
* because all promises that we input to Promise.allSettled
Expand Down Expand Up @@ -364,6 +390,7 @@ const getBucketAdditionalInfo = async (s3: S3, name: BucketName) =>
Tags: convertAwsTagsToTagMap(Tags),
VersioningInfo,
StaticWebsiteInfo: WebsiteInfo,
NotificationConfiguration: NotificationConfig,
})
})

Expand Down Expand Up @@ -455,6 +482,7 @@ export interface RawAwsS3 {
ReqPaymentConfig: Payer
StaticWebsiteInfo?: GetBucketWebsiteOutput
VersioningInfo?: GetBucketVersioningOutput
NotificationConfiguration?: NotificationConfiguration
}
Tags: TagMap
Contents?: S3Object[]
Expand Down
Loading