Skip to content

Commit d9be811

Browse files
authored
Merge pull request #29 from cloudgraphdev/fix/CG-1070
fix: Added missing connections to RDS DB Instance
2 parents 7658127 + 206bd29 commit d9be811

16 files changed

Lines changed: 383 additions & 180 deletions

File tree

README.md

Lines changed: 94 additions & 94 deletions
Large diffs are not rendered by default.

src/services/cloudwatchLogs/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type awsCloudwatchLog @key(fields: "arn") {
1414
cloudwatch: [awsCloudwatch] @hasInverse(field: cloudwatchLog)
1515
cloudtrail: [awsCloudtrail] @hasInverse(field: cloudwatchLog)
1616
ecsCluster: [awsEcsCluster] @hasInverse(field: cloudwatchLog)
17+
rdsDbInstance: [awsRdsDbInstance] @hasInverse(field: cloudwatchLogs)
1718
}
1819

1920
type awsMetricFilter

src/services/iamRole/schema.graphql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ type awsIamRole implements awsBaseService @key(fields: "id") {
2929
appSync: [awsAppSync] @hasInverse(field: iamRoles)
3030
lambda: [awsLambda] @hasInverse(field: iamRole)
3131
kinesisFirehose: [awsKinesisFirehose] @hasInverse(field: iamRole)
32-
rdsClusterMonitoringRole: [awsRdsCluster]
33-
@hasInverse(field: monitoringIamRole)
34-
rdsClusterIamRoles: [awsRdsCluster] @hasInverse(field: iamRoles)
35-
cloudFormationStackSet: [awsCloudFormationStackSet] @hasInverse(field: iamRoles)
32+
rdsCluster: [awsRdsCluster] @hasInverse(field: iamRoles)
33+
cloudFormationStackSet: [awsCloudFormationStackSet]
34+
@hasInverse(field: iamRoles)
3635
asg: [awsAsg] @hasInverse(field: iamRole)
36+
rdsDbInstance: [awsRdsDbInstance] @hasInverse(field: iamRoles)
3737
}

src/services/kms/schema.graphql

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ type awsKms implements awsBaseService @key(fields: "id") {
4747
ecsCluster: [awsEcsCluster] @hasInverse(field: kms)
4848
dynamodb: [awsDynamoDbTable] @hasInverse(field: kms)
4949
cognitoUserPools: [awsCognitoUserPool] @hasInverse(field: kms)
50-
rdsClusterStorageEncryption: [awsRdsCluster]
51-
@hasInverse(field: storageEncryptedKms)
52-
rdsClusterActivityStream: [awsRdsCluster]
53-
@hasInverse(field: activityStreamKms)
54-
rdsClusterPerformanceInsights: [awsRdsCluster]
55-
@hasInverse(field: performanceInsightsKms)
50+
rdsCluster: [awsRdsCluster] @hasInverse(field: kms)
51+
rdsDbInstance: [awsRdsDbInstance] @hasInverse(field: kms)
5652
}

src/services/rdsCluster/connections.ts

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { ServiceConnection } from '@cloudgraph/sdk'
22
import { isEmpty } from 'lodash'
33
import { SecurityGroup } from 'aws-sdk/clients/ec2'
4-
import { DBInstance, DBCluster } from 'aws-sdk/clients/rds'
4+
import { DBInstance } from 'aws-sdk/clients/rds'
55

66
import services from '../../enums/services'
7+
import { RawAwsRdsCluster } from './data'
8+
import { RawAwsRoute53HostedZone } from '../route53HostedZone/data'
79
import { RawAwsRdsClusterSnapshot } from '../rdsClusterSnapshot/data'
810
import { RawAwsIamRole } from '../iamRole/data'
11+
import { RawAwsSubnet } from '../subnet/data'
912
import { AwsKms } from '../kms/data'
1013
import { globalRegionName } from '../../enums/regions'
1114

@@ -14,7 +17,7 @@ export default ({
1417
data,
1518
region,
1619
}: {
17-
service: DBCluster
20+
service: RawAwsRdsCluster
1821
data: Array<{ name: string; data: { [property: string]: any[] } }>
1922
region: string
2023
}): {
@@ -24,12 +27,14 @@ export default ({
2427
const {
2528
DBClusterArn: id,
2629
DBClusterIdentifier: clusterId,
30+
dbSubnetGroups,
2731
MonitoringRoleArn: monitoringRoleArn,
2832
AssociatedRoles: associatedRoles = [],
2933
KmsKeyId,
3034
ActivityStreamKmsKeyId,
3135
PerformanceInsightsKMSKeyId,
3236
VpcSecurityGroups,
37+
HostedZoneId: hostedZoneId,
3338
} = service
3439
const sgIds = VpcSecurityGroups.map(
3540
({ VpcSecurityGroupId }) => VpcSecurityGroupId
@@ -122,47 +127,19 @@ export default ({
122127
} = data.find(({ name }) => name === services.kms)
123128

124129
if (kms?.data?.[region]) {
125-
// set storage encryption kms key
126-
let kmsInRegion: AwsKms[] = kms.data[region].filter(
127-
({ Arn }: AwsKms) => Arn === KmsKeyId
130+
const kmsInRegion: AwsKms[] = kms.data[region].filter(
131+
({ Arn }: AwsKms) =>
132+
Arn === KmsKeyId ||
133+
Arn === ActivityStreamKmsKeyId ||
134+
Arn === PerformanceInsightsKMSKeyId
128135
)
129136
if (!isEmpty(kmsInRegion)) {
130137
for (const instance of kmsInRegion) {
131138
connections.push({
132139
id: instance.KeyId,
133140
resourceType: services.kms,
134141
relation: 'child',
135-
field: 'storageEncryptedKms',
136-
})
137-
}
138-
}
139-
140-
// set activity stream kms key
141-
kmsInRegion = kms.data[region].filter(
142-
({ Arn }: AwsKms) => Arn === ActivityStreamKmsKeyId
143-
)
144-
if (!isEmpty(kmsInRegion)) {
145-
for (const instance of kmsInRegion) {
146-
connections.push({
147-
id: instance.KeyId,
148-
resourceType: services.kms,
149-
relation: 'child',
150-
field: 'activityStreamKms',
151-
})
152-
}
153-
}
154-
155-
// set performance insights kms key
156-
kmsInRegion = kms.data[region].filter(
157-
({ Arn }: AwsKms) => Arn === PerformanceInsightsKMSKeyId
158-
)
159-
if (!isEmpty(kmsInRegion)) {
160-
for (const instance of kmsInRegion) {
161-
connections.push({
162-
id: instance.KeyId,
163-
resourceType: services.kms,
164-
relation: 'child',
165-
field: 'performanceInsightsKms',
142+
field: 'kms',
166143
})
167144
}
168145
}
@@ -178,10 +155,12 @@ export default ({
178155
} = data.find(({ name }) => name === services.iamRole)
179156

180157
if (iamRoles?.data?.[globalRegionName]) {
181-
let iamRolesInRegion: RawAwsIamRole[] = iamRoles.data[
158+
const iamRolesInRegion: RawAwsIamRole[] = iamRoles.data[
182159
globalRegionName
183-
].filter(({ Arn }: RawAwsIamRole) =>
184-
associatedRoles.find(r => r.RoleArn === Arn)
160+
].filter(
161+
({ Arn }: RawAwsIamRole) =>
162+
Arn === monitoringRoleArn ||
163+
associatedRoles.find(r => r.RoleArn === Arn)
185164
)
186165
if (!isEmpty(iamRolesInRegion)) {
187166
for (const instance of iamRolesInRegion) {
@@ -193,16 +172,56 @@ export default ({
193172
})
194173
}
195174
}
196-
iamRolesInRegion = iamRoles.data[globalRegionName].filter(
197-
({ Arn }: RawAwsIamRole) => Arn === monitoringRoleArn
175+
}
176+
177+
/**
178+
* Find Route53 hosted zones
179+
*/
180+
const route53HostedZones: {
181+
name: string
182+
data: { [property: string]: RawAwsRoute53HostedZone[] }
183+
} = data.find(({ name }) => name === services.route53HostedZone)
184+
185+
if (route53HostedZones?.data?.[region]) {
186+
const instancesInRegion: RawAwsRoute53HostedZone[] =
187+
route53HostedZones.data[region].filter(
188+
({ Id }: RawAwsRoute53HostedZone) => Id === hostedZoneId
189+
)
190+
if (!isEmpty(instancesInRegion)) {
191+
for (const instance of instancesInRegion) {
192+
const { Id: id } = instance
193+
connections.push({
194+
id,
195+
resourceType: services.route53HostedZone,
196+
relation: 'child',
197+
field: 'route53HostedZone',
198+
})
199+
}
200+
}
201+
}
202+
203+
/**
204+
* Find Subnets
205+
* related to this RDS Cluster
206+
*/
207+
const subnets = data.find(({ name }) => name === services.subnet)
208+
const subnetIds = dbSubnetGroups?.map(({ Subnets }) =>
209+
Subnets?.map(subnet => subnet.SubnetIdentifier)
210+
)
211+
if (subnets?.data?.[region]) {
212+
const subnetsInRegion = subnets.data[region].filter(
213+
(subnet: RawAwsSubnet) =>
214+
subnetIds.some(ids => ids.includes(subnet.SubnetId))
198215
)
199-
if (!isEmpty(iamRolesInRegion)) {
200-
for (const instance of iamRolesInRegion) {
216+
if (!isEmpty(subnetsInRegion)) {
217+
for (const subnet of subnetsInRegion) {
218+
const { SubnetId } = subnet
219+
201220
connections.push({
202-
id: instance.Arn,
203-
resourceType: services.iamRole,
221+
id: SubnetId,
222+
resourceType: services.subnet,
204223
relation: 'child',
205-
field: 'monitoringIamRole',
224+
field: 'subnets',
206225
})
207226
}
208227
}

src/services/rdsCluster/data.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import RDS, {
44
TagListMessage,
55
DescribeDBClustersMessage,
66
DBClusterMessage,
7+
DBSubnetGroup,
8+
DBSubnetGroupMessage,
79
} from 'aws-sdk/clients/rds'
810
import { AWSError } from 'aws-sdk/lib/error'
911
import groupBy from 'lodash/groupBy'
@@ -57,6 +59,29 @@ const listClustersForRegion = async rds =>
5759
listAllClusters()
5860
})
5961

62+
const describeDBSubnetGroups = async (rds: RDS, DBSubnetGroupName: string): Promise<DBSubnetGroup[]> =>
63+
new Promise(resolve => {
64+
try {
65+
rds.describeDBSubnetGroups(
66+
{ DBSubnetGroupName },
67+
(err: AWSError, data: DBSubnetGroupMessage) => {
68+
if (err) {
69+
errorLog.generateAwsErrorLog({
70+
functionName: 'rds:describeDBSubnetGroups',
71+
err,
72+
})
73+
return resolve([])
74+
}
75+
if (!isEmpty(data)) {
76+
resolve(data.DBSubnetGroups)
77+
}
78+
}
79+
)
80+
} catch (error) {
81+
resolve([])
82+
}
83+
})
84+
6085
const getResourceTags = async (rds: RDS, arn: string): Promise<TagMap> =>
6186
new Promise(resolve => {
6287
try {
@@ -80,6 +105,7 @@ const getResourceTags = async (rds: RDS, arn: string): Promise<TagMap> =>
80105
})
81106

82107
export interface RawAwsRdsCluster extends DBCluster {
108+
dbSubnetGroups: DBSubnetGroup[]
83109
Tags?: TagMap
84110
region: string
85111
}
@@ -104,10 +130,11 @@ export default async ({
104130

105131
if (!isEmpty(clusters)) {
106132
rdsData.push(
107-
...clusters.map(cluster => ({
133+
...await Promise.all(clusters.map(async (cluster) => ({
108134
...cluster,
135+
dbSubnetGroups: await describeDBSubnetGroups(rds, cluster.DBSubnetGroup),
109136
region,
110-
}))
137+
})))
111138
)
112139
}
113140
resolveRegion()

src/services/rdsCluster/format.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export default ({
1414
const {
1515
DBClusterArn: arn,
1616
DBClusterIdentifier: dbClusterIdentifier,
17-
DBSubnetGroup: subnets,
17+
DBClusterParameterGroup: dbClusterParameterGroup,
18+
DBSubnetGroup: dbSubnetGroup,
1819
Status: status,
1920
Engine: engine,
2021
EngineVersion: engineVersion,
@@ -55,7 +56,8 @@ export default ({
5556
characterSetName,
5657
databaseName,
5758
dbClusterIdentifier,
58-
subnets,
59+
dbClusterParameterGroup,
60+
dbSubnetGroup,
5961
status,
6062
percentProgress,
6163
readerEndpoint,

src/services/rdsCluster/schema.graphql

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ type awsRdsCluster implements awsBaseService @key(fields: "arn") {
44
characterSetName: String @search(by: [hash, regexp])
55
databaseName: String @search(by: [hash, regexp])
66
dbClusterIdentifier: String @search(by: [hash])
7-
subnets: String @search(by: [hash])
7+
dbClusterParameterGroup: String @search(by: [hash])
8+
dbSubnetGroup: String @search(by: [hash])
89
status: String @search(by: [hash, regexp])
910
percentProgress: String @search(by: [hash, regexp])
1011
readerEndpoint: String @search(by: [hash, regexp])
@@ -32,11 +33,9 @@ type awsRdsCluster implements awsBaseService @key(fields: "arn") {
3233
instances: [awsRdsDbInstance] @hasInverse(field: cluster)
3334
snapshots: [awsRdsClusterSnapshot] @hasInverse(field: cluster)
3435
securityGroups: [awsSecurityGroup] @hasInverse(field: rdsCluster)
36+
subnets: [awsSubnet] @hasInverse(field: rdsCluster)
3537
appSync: [awsAppSync] @hasInverse(field: rdsCluster)
36-
monitoringIamRole: [awsIamRole] @hasInverse(field: rdsClusterMonitoringRole)
37-
iamRoles: [awsIamRole] @hasInverse(field: rdsClusterIamRoles)
38-
storageEncryptedKms: [awsKms] @hasInverse(field: rdsClusterStorageEncryption)
39-
activityStreamKms: [awsKms] @hasInverse(field: rdsClusterActivityStream)
40-
performanceInsightsKms: [awsKms]
41-
@hasInverse(field: rdsClusterPerformanceInsights)
38+
kms: [awsKms] @hasInverse(field: rdsCluster)
39+
route53HostedZone: [awsRoute53HostedZone] @hasInverse(field: rdsCluster)
40+
iamRoles: [awsIamRole] @hasInverse(field: rdsCluster)
4241
}

0 commit comments

Comments
 (0)