Skip to content

Commit d1b43d0

Browse files
author
Marco Franceschi
authored
Merge pull request #144 from cloudgraphdev/feat/EP-3185
feat: Added missing data to RDS
2 parents af41b86 + 1671478 commit d1b43d0

24 files changed

Lines changed: 960 additions & 22 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
147147
| organization |
148148
| rdsCluster | appSync, rdsClusterSnapshot, rdsDbInstance, route53HostedZone, securityGroup, subnet, iamRole, kms |
149149
| rdsClusterSnapshot | kms, rdsCluster, vpc |
150+
| rdsDbProxies | |
151+
| rdsEventSubscription | |
152+
| rdsGlobalCluster | |
150153
| rdsDbInstance | kms, iamRole, rdsCluster, securityGroup, vpc, subnet, cloudwatchLog |
151154
| redshiftCluster | kms, vpc |
152155
| route53Record | alb, apiGatewayRestApi, elb, route53HostedZone |

src/enums/serviceMap.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ import NATGateway from '../services/natGateway'
5151
import NetworkAcl from '../services/nacl'
5252
import NetworkInterface from '../services/networkInterface'
5353
import RDSCluster from '../services/rdsCluster'
54+
import RDSGlobalCluster from '../services/rdsGlobalCluster '
5455
import RDSDbInstance from '../services/rdsDbInstance'
56+
import RDSEventSubscription from '../services/rdsEventSubscription'
57+
import RdsDbProxies from '../services/rdsDbProxies'
5558
import RedshiftCluster from '../services/redshift'
5659
import Route53HostedZone from '../services/route53HostedZone'
5760
import Route53Record from '../services/route53Record'
@@ -183,8 +186,11 @@ export default {
183186
[services.vpcPeeringConnection]: VpcPeeringConnection,
184187
[services.sqs]: SQS,
185188
[services.rdsCluster]: RDSCluster,
189+
[services.rdsGlobalCluster]: RDSGlobalCluster,
186190
[services.rdsClusterSnapshot]: RdsClusterSnapshot,
187191
[services.rdsDbInstance]: RDSDbInstance,
192+
[services.rdsEventSubscription]: RDSEventSubscription,
193+
[services.rdsDbProxies]: RdsDbProxies,
188194
[services.redshiftCluster]: RedshiftCluster,
189195
[services.route53HostedZone]: Route53HostedZone,
190196
[services.route53Record]: Route53Record,

src/enums/services.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ export default {
7878
networkInterface: 'networkInterface',
7979
organization: 'organization',
8080
rdsCluster: 'rdsCluster',
81+
rdsGlobalCluster: 'rdsGlobalCluster',
8182
rdsClusterSnapshot: 'rdsClusterSnapshot',
8283
rdsDbInstance: 'rdsDbInstance',
84+
rdsEventSubscription: 'rdsEventSubscription',
85+
rdsDbProxies: 'rdsDbProxies',
8386
redshiftCluster: 'redshiftCluster',
8487
route53HostedZone: 'route53HostedZone',
8588
route53Record: 'route53Record',

src/properties/logger.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,13 @@ export default {
291291
lookingforRdsClusters: 'Looking for RDS Clusters...',
292292
creatingRdsInstance: (num: number): string => `Creating RDS Instance #${num}`,
293293
fetchedRdsClusters: (num: number): string => `Fetched ${num} RDS Clusters`,
294+
fetchedRdsGlobalClusters: (num: number): string => `Fetched ${num} RDS Global Clusters`,
294295
fetchedRdsInstances: (num: number): string =>
295296
`Fetched ${num} RDS DB Instances`,
297+
fetchedRdsEventSubscriptions: (num: number): string =>
298+
`Fetched ${num} RDS DB Event Subscriptions`,
299+
fetchedRdsDbProxies: (num: number): string =>
300+
`Fetched ${num} RDS DB Proxies`,
296301
noClusterFound: '❎ DB Instance is not part of a cluster ❎ ',
297302
foundCluster: 'Found the cluster the instance belongs to',
298303
addingRdsInstances: (num: number): string =>

src/services/account/schema.graphql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ type awsAccount implements awsOptionalService @key(fields: "id") {
7575
networkInterfaces: [awsNetworkInterface]
7676
organizations: [awsOrganization]
7777
rdsClusters: [awsRdsCluster]
78+
rdsGlobalCluster : [awsRdsGlobalCluster]
7879
rdsClusterSnapshots: [awsRdsClusterSnapshot]
7980
rdsDbInstances: [awsRdsDbInstance]
81+
rdsEventSubscription: [awsRdsEventSubscription]
82+
rdsDbProxies: [awsRdsDbProxies]
8083
redshiftClusters: [awsRedshiftCluster]
8184
route53HostedZones: [awsRoute53HostedZone]
8285
route53Records: [awsRoute53Record]

src/services/rdsDbInstance/data.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import RDS, {
44
DBInstance,
55
DescribeDBInstancesMessage,
66
DBInstanceMessage,
7+
DBSnapshotMessage,
8+
DBSnapshot,
79
} from 'aws-sdk/clients/rds'
810
import { AWSError } from 'aws-sdk/lib/error'
911
import groupBy from 'lodash/groupBy'
@@ -57,6 +59,28 @@ const listDBInstancesForRegion = async (rds: RDS): Promise<DBInstance[]> =>
5759
listAllDBInstances()
5860
})
5961

62+
const getInstanceSnapshots = async (rds: RDS, arn: string): Promise<DBSnapshot[]> =>
63+
new Promise(resolve => {
64+
try {
65+
rds.describeDBSnapshots(
66+
{ DBInstanceIdentifier: arn },
67+
(err: AWSError, data: DBSnapshotMessage) => {
68+
if (err) {
69+
errorLog.generateAwsErrorLog({
70+
functionName: 'rds:describeDBSnapshots',
71+
err,
72+
})
73+
return resolve([])
74+
}
75+
const { DBSnapshots: snapshots = [] } = data || {}
76+
resolve(snapshots)
77+
}
78+
)
79+
} catch (error) {
80+
resolve([])
81+
}
82+
})
83+
6084
const getResourceTags = async (rds: RDS, arn: string): Promise<TagMap> =>
6185
new Promise(resolve => {
6286
try {
@@ -81,6 +105,7 @@ const getResourceTags = async (rds: RDS, arn: string): Promise<TagMap> =>
81105

82106
export interface RawAwsRdsDbInstance extends DBInstance {
83107
Tags?: TagMap
108+
Snapshots?: DBSnapshot[]
84109
region: string
85110
}
86111

@@ -123,6 +148,7 @@ export default async ({
123148
const rds = new RDS({ ...config, region, endpoint })
124149
const tagsPromise = new Promise<void>(async resolveTags => {
125150
rdsData[idx].Tags = await getResourceTags(rds, DBInstanceArn)
151+
rdsData[idx].Snapshots = await getInstanceSnapshots(rds, DBInstanceArn)
126152
resolveTags()
127153
})
128154
tagsPromises.push(tagsPromise)

src/services/rdsDbInstance/format.ts

Lines changed: 99 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1+
import { generateUniqueId } from '@cloudgraph/sdk'
2+
13
import upperFirst from 'lodash/upperFirst'
24
import { RawAwsRdsDbInstance } from './data'
3-
import {
4-
AwsRdsDbInstance,
5+
import {
6+
AwsRdsDbInstance, AwsRdsDbInstanceGroupOption, AwsRdsDbInstanceParameterGroup, AwsRdsDbInstanceSnapshot,
57
} from '../../types/generated'
6-
import { formatTagsFromMap } from '../../utils/format'
8+
import { convertAwsTagsToTagMap, formatTagsFromMap } from '../../utils/format'
9+
import { AwsTag } from '../../types'
710

811
export default ({
912
service,
1013
account,
1114
region
12-
}:
13-
{
14-
service: RawAwsRdsDbInstance
15-
account: string
16-
region: string
17-
}): AwsRdsDbInstance => {
15+
}:
16+
{
17+
service: RawAwsRdsDbInstance
18+
account: string
19+
region: string
20+
}): AwsRdsDbInstance => {
1821
const {
1922
DBInstanceArn: arn,
2023
DBInstanceIdentifier: dBInstanceIdentifier,
@@ -42,19 +45,96 @@ export default ({
4245
Endpoint: endpoint,
4346
LicenseModel: licenseModel,
4447
Tags = {},
48+
Snapshots = []
4549
} = service
4650

4751
const subnetGroup = service.DBSubnetGroup?.DBSubnetGroupName || ''
4852

49-
const parameterGroup = service.DBParameterGroups.map(
50-
({ DBParameterGroupName, ParameterApplyStatus }) =>
51-
`${DBParameterGroupName} (${ParameterApplyStatus})`
52-
).join(' | ')
53+
const parameterGroups: AwsRdsDbInstanceParameterGroup[] = service.DBParameterGroups.map(
54+
(parameter) => {
55+
const { DBParameterGroupName, ParameterApplyStatus } = parameter
56+
return ({
57+
id: generateUniqueId({
58+
arn,
59+
...parameter
60+
}),
61+
description: `${DBParameterGroupName} (${ParameterApplyStatus})`,
62+
name: DBParameterGroupName,
63+
status: ParameterApplyStatus
64+
})
65+
}
66+
)
67+
68+
const optionsGroups: AwsRdsDbInstanceGroupOption[] = service.OptionGroupMemberships.map(
69+
(option) => {
70+
const { OptionGroupName, Status } = option
71+
return ({
72+
id: generateUniqueId({
73+
arn,
74+
...option
75+
}),
76+
description: `${OptionGroupName} (${upperFirst(Status)})`,
77+
groupName: OptionGroupName,
78+
status: Status
79+
})
80+
}
81+
82+
)
83+
84+
const snapshots: AwsRdsDbInstanceSnapshot[] = Snapshots.map(
85+
(snapshot) => {
86+
const tags = convertAwsTagsToTagMap(snapshot.TagList as AwsTag[])
87+
return ({
88+
id: generateUniqueId({
89+
arn,
90+
...snapshot
91+
}),
92+
dBSnapshotIdentifier: snapshot.DBSnapshotIdentifier,
93+
dBInstanceIdentifier: snapshot.DBInstanceIdentifier,
94+
snapshotCreateTime: snapshot.SnapshotCreateTime?.toISOString(),
95+
engine: snapshot.Engine,
96+
allocatedStorage: snapshot.AllocatedStorage,
97+
status: snapshot.Status,
98+
port: snapshot.Port,
99+
availabilityZone: snapshot.AvailabilityZone,
100+
vpcId: snapshot.VpcId,
101+
instanceCreateTime: snapshot.InstanceCreateTime?.toISOString(),
102+
masterUsername: snapshot.MasterUsername,
103+
engineVersion: snapshot.EngineVersion,
104+
licenseModel: snapshot.LicenseModel,
105+
snapshotType: snapshot.SnapshotType,
106+
iops: snapshot.Iops,
107+
optionGroupName: snapshot.OptionGroupName,
108+
percentProgress: snapshot.PercentProgress,
109+
sourceRegion: snapshot.SourceRegion,
110+
sourceDBSnapshotIdentifier: snapshot.SourceDBSnapshotIdentifier,
111+
storageType: snapshot.StorageType,
112+
tdeCredentialArn: snapshot.TdeCredentialArn,
113+
encrypted: snapshot.Encrypted,
114+
kmsKeyId: snapshot.KmsKeyId,
115+
dBSnapshotArn: snapshot.DBSnapshotArn,
116+
timezone: snapshot.Timezone,
117+
iAMDatabaseAuthenticationEnabled: snapshot.IAMDatabaseAuthenticationEnabled,
118+
processorFeatures: snapshot.ProcessorFeatures?.map(p => ({
119+
id: generateUniqueId({
120+
arn,
121+
...p
122+
}),
123+
name: p.Name,
124+
value: p.Value
125+
})),
126+
dbiResourceId: snapshot.DbiResourceId,
127+
tagList: snapshot.TagList,
128+
originalSnapshotCreateTime: snapshot.OriginalSnapshotCreateTime?.toISOString(),
129+
snapshotDatabaseTime: snapshot.SnapshotDatabaseTime?.toISOString(),
130+
snapshotTarget: snapshot.SnapshotTarget,
131+
storageThroughput: snapshot.StorageThroughput,
132+
tags: formatTagsFromMap(tags)
133+
})
134+
}
135+
)
136+
53137

54-
const optionsGroups = service.OptionGroupMemberships.map(
55-
({ OptionGroupName, Status }) =>
56-
`${OptionGroupName} (${upperFirst(Status)})`
57-
).join(' | ')
58138

59139
return {
60140
id: arn,
@@ -77,7 +157,7 @@ export default ({
77157
autoMinorVersionUpgrade,
78158
iamDbAuthenticationEnabled,
79159
optionsGroups,
80-
parameterGroup,
160+
parameterGroups,
81161
storageType,
82162
instanceClass,
83163
allocatedStorage,
@@ -91,6 +171,7 @@ export default ({
91171
kmsKey,
92172
encrypted,
93173
licenseModel,
174+
snapshots,
94175
tags: formatTagsFromMap(Tags),
95176
}
96177
}

src/services/rdsDbInstance/schema.graphql

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,69 @@
1+
type awsRdsDbInstanceParameterGroup {
2+
id: String! @id
3+
name: String @search(by: [hash, regexp])
4+
status: String @search(by: [hash, regexp])
5+
description: String @search(by: [hash, regexp])
6+
}
7+
8+
type awsRdsDbInstanceGroupOption {
9+
id: String! @id
10+
groupName: String @search(by: [hash, regexp])
11+
status: String @search(by: [hash, regexp])
12+
description: String @search(by: [hash, regexp])
13+
}
14+
15+
type awsRdsDbInstanceSnapshot {
16+
id: String! @id
17+
groupName: String @search(by: [hash, regexp])
18+
status: String @search(by: [hash, regexp])
19+
description: String @search(by: [hash, regexp])
20+
}
21+
22+
23+
type awsRdsDbInstanceProcessorFeature {
24+
id: String! @id
25+
name: String @search(by: [hash, regexp])
26+
value: String @search(by: [hash, regexp])
27+
}
28+
29+
type awsRdsDbInstanceSnapshot {
30+
id: String! @id
31+
dBSnapshotIdentifier: String @search(by: [hash, regexp])
32+
dBInstanceIdentifier: String @search(by: [hash, regexp])
33+
snapshotCreateTime: DateTime @search(by: [day])
34+
engine: String @search(by: [hash, regexp])
35+
allocatedStorage: Int @search
36+
status: String @search(by: [hash, regexp])
37+
port: Int @search
38+
availabilityZone: String @search(by: [hash, regexp])
39+
vpcId: String @search(by: [hash, regexp])
40+
instanceCreateTime: DateTime @search(by: [day])
41+
masterUsername: String @search(by: [hash, regexp])
42+
engineVersion: String @search(by: [hash, regexp])
43+
licenseModel: String @search(by: [hash, regexp])
44+
snapshotType: String @search(by: [hash, regexp])
45+
iops: Int @search
46+
optionGroupName: String @search(by: [hash, regexp])
47+
percentProgress: Int @search
48+
sourceRegion: String @search(by: [hash, regexp])
49+
sourceDBSnapshotIdentifier: String @search(by: [hash, regexp])
50+
storageType: String @search(by: [hash, regexp])
51+
tdeCredentialArn: String @search(by: [hash, regexp])
52+
encrypted: Boolean @search
53+
kmsKeyId: String @search(by: [hash, regexp])
54+
dBSnapshotArn: String @search(by: [hash, regexp])
55+
timezone: String @search(by: [hash, regexp])
56+
iAMDatabaseAuthenticationEnabled: Boolean @search
57+
processorFeatures: [awsRdsDbInstanceProcessorFeature]
58+
dbiResourceId: String @search(by: [hash, regexp])
59+
tags: [awsRawTag]
60+
originalSnapshotCreateTime: DateTime @search(by: [day])
61+
snapshotDatabaseTime: DateTime @search(by: [day])
62+
snapshotTarget: String @search(by: [hash, regexp])
63+
storageThroughput: Int @search
64+
}
65+
66+
167
type awsRdsDbInstance implements awsBaseService @key(fields: "arn") {
268
name: String @search(by: [hash, regexp])
369
port: Int @search
@@ -14,8 +80,8 @@ type awsRdsDbInstance implements awsBaseService @key(fields: "arn") {
1480
performanceInsightsEnabled: Boolean @search
1581
autoMinorVersionUpgrade: Boolean @search
1682
iamDbAuthenticationEnabled: Boolean @search
17-
optionsGroups: String
18-
parameterGroup: String
83+
optionsGroups: [awsRdsDbInstanceGroupOption]
84+
parameterGroups: [awsRdsDbInstanceParameterGroup]
1985
storageType: String @search(by: [hash, regexp])
2086
instanceClass: String @search(by: [hash, regexp])
2187
allocatedStorage: Int @search
@@ -30,6 +96,7 @@ type awsRdsDbInstance implements awsBaseService @key(fields: "arn") {
3096
encrypted: Boolean @search
3197
licenseModel: String @search(by: [hash, regexp])
3298
tags: [awsRawTag]
99+
snapshots: [awsRdsDbInstanceSnapshot]
33100
cluster: [awsRdsCluster] @hasInverse(field: instances)
34101
kms: [awsKms] @hasInverse(field: rdsDbInstance)
35102
securityGroups: [awsSecurityGroup] @hasInverse(field: rdsDbInstance)

0 commit comments

Comments
 (0)