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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
| clientVpnEndpoint | securityGroup |
| cloud9 | |
| cloudformationStack | cloudformationStack, iamRole, sns |
| cloudformationStackSet | |
| cloudformationStackSet | iamRole |
| cloudfront | elb, s3 |
| cloudtrail | cloudwatch, cloudwatchLog, kms, s3, sns |
| cloudwatch | cloudtrail, cloudwatchLog, sns |
Expand Down Expand Up @@ -124,7 +124,7 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
| iamServerCertificate | |
| iamUser | iamGroup |
| iamPolicy | iamRole, iamGroup |
| iamRole | appSync, 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, sageMakerNotebookInstance, systemsManagerInstance guardDutyDetector, lambda, kinesisFirehose, rdsCluster |
| iamGroup | iamUser, iamPolicy |
| igw | vpc |
| iot | |
Expand Down
86 changes: 56 additions & 30 deletions src/services/cloudFormationStackSet/connections.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,60 @@
// TODO: Enable when IAM is added
// import { ServiceConnection } from '@cloudgraph/sdk';
// import { Stack } from 'aws-sdk/clients/cloudformation';
// import { TagMap } from '../../types'
import isEmpty from 'lodash/isEmpty'
import { ServiceConnection } from '@cloudgraph/sdk';
import { StackSet } from 'aws-sdk/clients/cloudformation';
import { TagMap } from '../../types'
import services from '../../enums/services'
import { RawAwsIamRole } from '../iamRole/data'
import { globalRegionName } from '../../enums/regions'

// /**
// * Cloud Formation StackSet
// */
/**
* Cloud Formation StackSet
*/

// export default ({
// service: cfStackSet,
// data,
// region,
// }: {
// data: { name: string; data: { [property: string]: any[] } }[]
// service: Stack & {
// region: string
// Tags: TagMap,
// },
// region: string
// }): { [key: string]: ServiceConnection[] } => {
// const connections: ServiceConnection[] = []
export default ({
service: cfStackSet,
data,
region,
}: {
data: { name: string; data: { [property: string]: any[] } }[]
service: StackSet & {
region: string
Tags: TagMap,
},
region: string
}): { [key: string]: ServiceConnection[] } => {
const connections: ServiceConnection[] = []

// const {
// StackId: id,
// // TODO add connection role
// // AdministrationRoleARN: administrationRoleARN
// } = cfStackSet
const {
StackSetId: id,
AdministrationRoleARN: administrationRoleARN,
ExecutionRoleName: executionRoleName,
} = cfStackSet

// const cfStackSetResult = {
// [id]: connections,
// }
// return cfStackSetResult
// }
/**
* Find related IAM Roles
*/
const roles: { name: string; data: { [property: string]: any[] } } =
data.find(({ name }) => name === services.iamRole)
if (roles?.data?.[globalRegionName]) {
const dataAtRegion: RawAwsIamRole[] = roles.data[globalRegionName].filter(
role => role.Arn === administrationRoleARN || role.RoleName === executionRoleName
)
if (!isEmpty(dataAtRegion)) {
for (const instance of dataAtRegion) {
const { Arn: arn }: RawAwsIamRole = instance

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

const cfStackSetResult = {
[id]: connections,
}
return cfStackSetResult
}
5 changes: 2 additions & 3 deletions src/services/cloudFormationStackSet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { Service } from '@cloudgraph/sdk';
import BaseService from '../base';
import format from './format';
import getData from './data';
// import getConnections from './connections'
import getConnections from './connections'
import mutation from './mutation';

export default class AwsCloudFormation extends BaseService implements Service {
format = format.bind(this);

getData = getData.bind(this);

// TODO: Enable when IAM is added
// getConnections = getConnections.bind(this)
getConnections = getConnections.bind(this)

mutation = mutation;
}
5 changes: 2 additions & 3 deletions src/services/cloudFormationStackSet/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type awsCloudFormationStackAutoDeploymentConfig {
enabled: String @search(by: [hash, regexp])
retainStacksOnAccountRemoval: String @search(by: [hash, regexp])
}
# TODO: add accountId to cloudFormationStackSet

type awsCloudFormationStackSet implements awsBaseService @key(fields: "arn") {
name: String @search(by: [hash, regexp])
description: String @search(by: [hash, regexp])
Expand All @@ -55,6 +55,5 @@ type awsCloudFormationStackSet implements awsBaseService @key(fields: "arn") {
autoDeploymentConfig: awsCloudFormationStackAutoDeploymentConfig
permissionModel: String @search(by: [hash, regexp])
organizationalUnitIds: [String] @search
iamRoles: [awsIamRole] @hasInverse(field: cloudFormationStackSet)
}

# TODO: add iam role connection using AdministrationRoleARN (also see if a connection can be made using ExecutionRoleName)
1 change: 1 addition & 0 deletions src/services/iamRole/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ type awsIamRole implements awsBaseService @key(fields: "id") {
rdsClusterMonitoringRole: [awsRdsCluster]
@hasInverse(field: monitoringIamRole)
rdsClusterIamRoles: [awsRdsCluster] @hasInverse(field: iamRoles)
cloudFormationStackSet: [awsCloudFormationStackSet] @hasInverse(field: iamRoles)
}
2 changes: 2 additions & 0 deletions src/types/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ export type AwsCloudFormationStackSet = AwsBaseService & {
description?: Maybe<Scalars['String']>;
driftDetectionDetail?: Maybe<AwsCloudFormationStackSetDriftDetectionDetail>;
executionRoleName?: Maybe<Scalars['String']>;
iamRoles?: Maybe<Array<Maybe<AwsIamRole>>>;
name?: Maybe<Scalars['String']>;
organizationalUnitIds?: Maybe<Array<Maybe<Scalars['String']>>>;
parameters?: Maybe<Array<Maybe<AwsCloudFormationStackSetParameter>>>;
Expand Down Expand Up @@ -3049,6 +3050,7 @@ export type AwsIamRole = AwsBaseService & {
appSync?: Maybe<Array<Maybe<AwsAppSync>>>;
assumeRolePolicy?: Maybe<AwsIamJsonPolicy>;
cloudFormationStack?: Maybe<Array<Maybe<AwsCloudFormationStack>>>;
cloudFormationStackSet?: Maybe<Array<Maybe<AwsCloudFormationStackSet>>>;
codebuilds?: Maybe<Array<Maybe<AwsCodebuild>>>;
cognitoUserPools?: Maybe<Array<Maybe<AwsCognitoUserPool>>>;
configurationRecorder?: Maybe<Array<Maybe<AwsConfigurationRecorder>>>;
Expand Down
45 changes: 42 additions & 3 deletions tests/aws_cloudFormationStackSet.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import CloudGraph from '@cloudgraph/sdk'

import CloudFormationClass from '../src/services/cloudFormationStackSet'

import { credentials, region } from '../src/properties/test'
import IamRoleService from '../src/services/iamRole'
import { account, credentials, region } from '../src/properties/test'
import { initTestConfig } from '../src/utils'
import { RawAwsCloudFormationStackSet } from '../src/services/cloudFormationStackSet/data'
import services from '../src/enums/services'

describe('Cloud formation Service Test: ', () => {
let getDataResult
let formatResult
let cfConnections
let cfStackSetId

initTestConfig()

beforeAll(
async () =>
new Promise<void>(async resolve => {
try {
const iamRoleService = new IamRoleService({ logger: CloudGraph.logger })
const cfClass = new CloudFormationClass({ logger: CloudGraph.logger })

getDataResult = await cfClass.getData({
Expand All @@ -27,6 +30,29 @@ describe('Cloud formation Service Test: ', () => {
(item: RawAwsCloudFormationStackSet) =>
cfClass.format({ service: item, region })
)

// Get IAM Role data
const securityGroupData = await iamRoleService.getData({
credentials,
regions: region,
})

const [cfStackSet] = getDataResult[region]
cfStackSetId = cfStackSet.StackSetId

cfConnections = cfClass.getConnections({
service: cfStackSet,
data: [
{
name: services.iamRole,
data: securityGroupData,
account,
region,
},
],
region,
account,
})
} catch (error) {
console.error(error) // eslint-disable-line no-console
}
Expand Down Expand Up @@ -67,4 +93,17 @@ describe('Cloud formation Service Test: ', () => {
)
})
})

describe('connections', () => {
test('should verify the connection to iam roles', () => {
const iamRoleConnections = cfConnections[
cfStackSetId
]?.filter(
connection => connection.resourceType === services.iamRole
)

expect(iamRoleConnections).toBeDefined()
expect(iamRoleConnections.length).toBe(1)
})
})
})