Skip to content
This repository was archived by the owner on Jun 25, 2024. It is now read-only.

Commit b5d4a54

Browse files
Gaston YelminiGaston Yelmini
Gaston Yelmini
authored and
Gaston Yelmini
committed
feat(INT-5918): add cloud function source repo relationship
1 parent ca2cca1 commit b5d4a54

File tree

7 files changed

+133
-34
lines changed

7 files changed

+133
-34
lines changed

docs/jupiterone.md

+1
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ The following relationships are created:
459459
| `internet` | **ALLOWS** | `google_compute_firewall` |
460460
| `google_cloud_folder` | **HAS** | `google_cloud_folder` |
461461
| `google_cloud_function` | **USES** | `google_iam_service_account` |
462+
| `google_cloud_function` | **USES** | `google_cloud_source_repository` |
462463
| `google_cloud_organization` | **HAS** | `google_cloud_folder` |
463464
| `google_cloud_project` | **HAS** | `google_cloud_api_service` |
464465
| `google_cloud_project` | **HAS** | `google_billing_budget` |

docs/spec/src/steps/services/functions/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export const functionSteps: StepSpec<IntegrationInstanceConfig>[] = [
8282
},
8383
],
8484
dependsOn: ['fetch-cloud-functions', 'fetch-cloud-source-repositories'],
85-
implemented: false,
85+
implemented: true,
8686
},
8787
{
8888
/**

src/getStepStartStates.ts

+5
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ import * as enablement from './steps/enablement';
112112
import {
113113
STEP_CLOUD_FUNCTIONS,
114114
STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS,
115+
STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS,
115116
} from './steps/functions';
116117
import {
117118
STEP_IAM_CUSTOM_ROLES,
@@ -301,6 +302,7 @@ function getDefaultStepStartStates(params: {
301302
[STEP_CREATE_API_SERVICE_ANY_RESOURCE_RELATIONSHIPS]: { disabled: false },
302303
[STEP_CLOUD_FUNCTIONS]: { disabled: false },
303304
[STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS]: { disabled: false },
305+
[STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS]: { disabled: false },
304306
[STEP_CLOUD_STORAGE_BUCKETS]: { disabled: false },
305307
[STEP_IAM_CUSTOM_ROLES]: { disabled: false },
306308
[STEP_IAM_CUSTOM_ROLE_SERVICE_API_RELATIONSHIPS]: { disabled: false },
@@ -591,6 +593,9 @@ async function getStepStartStatesUsingServiceEnablements(params: {
591593
[STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS]: createStepStartState(
592594
ServiceUsageName.CLOUD_FUNCTIONS,
593595
),
596+
[STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS]: createStepStartState(
597+
ServiceUsageName.CLOUD_FUNCTIONS,
598+
),
594599
[STEP_CLOUD_STORAGE_BUCKETS]: createStepStartState(
595600
ServiceUsageName.STORAGE,
596601
ServiceUsageName.STORAGE_COMPONENT,

src/index.test.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ import {
123123
STEP_DNS_MANAGED_ZONES,
124124
STEP_DNS_POLICIES,
125125
} from './steps/dns/constants';
126-
import {
127-
STEP_CLOUD_FUNCTIONS,
128-
STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS,
129-
} from './steps/functions';
130126
import {
131127
STEP_IAM_CUSTOM_ROLES,
132128
STEP_IAM_CUSTOM_ROLE_SERVICE_API_RELATIONSHIPS,
@@ -175,6 +171,11 @@ import {
175171
import { SqlAdminSteps, STEP_SQL_ADMIN_INSTANCES } from './steps/sql-admin';
176172
import { STEP_CLOUD_STORAGE_BUCKETS } from './steps/storage';
177173
import { IntegrationConfig } from './types';
174+
import {
175+
STEP_CLOUD_FUNCTIONS,
176+
STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS,
177+
STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS,
178+
} from './steps/functions';
178179

179180
interface ValidateInvocationInvalidConfigTestParams {
180181
instanceConfig?: Partial<IntegrationConfig>;
@@ -326,6 +327,9 @@ describe('#getStepStartStates success', () => {
326327
[STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS]: {
327328
disabled: false,
328329
},
330+
[STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS]: {
331+
disabled: false,
332+
},
329333
[STEP_CLOUD_STORAGE_BUCKETS]: {
330334
disabled: false,
331335
},

src/steps/functions/constants.ts

+42-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,49 @@
1+
import { RelationshipClass } from '@jupiterone/integration-sdk-core';
2+
import { IAM_SERVICE_ACCOUNT_ENTITY_TYPE } from '../iam';
3+
14
export const CLOUD_FUNCTION_ENTITY_CLASS = 'Function';
25
export const CLOUD_FUNCTION_ENTITY_TYPE = 'google_cloud_function';
36

47
export const STEP_CLOUD_FUNCTIONS = 'fetch-cloud-functions';
58
export const STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS =
69
'build-cloud-function-service-account-relationships';
10+
export const STEP_CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIPS =
11+
'build-cloud-function-source-repo-relationships';
12+
13+
export const FunctionStepsSpec = {
14+
FETCH_CLOUD_FUNCTIONS: {
15+
id: 'fetch-cloud-functions',
16+
name: 'Cloud Functions',
17+
},
18+
CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS: {
19+
id: 'build-cloud-function-service-account-relationships',
20+
name: 'Cloud Function Service Account Relationships',
21+
},
22+
CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIP: {
23+
id: 'build-cloud-function-source-repo-relationships',
24+
name: 'Build Cloud Function -> Source Repository Relationships',
25+
},
26+
};
27+
28+
export const FunctionEntitiesSpec = {
29+
CLOUD_FUNCTION: {
30+
resourceName: 'Cloud Function',
31+
_type: 'google_cloud_function',
32+
_class: ['Function'],
33+
},
34+
};
735

8-
export const RELATIONSHIP_TYPE_CLOUD_FUNCTION_USES_IAM_SERVICE_ACCOUNT =
9-
'google_cloud_function_uses_iam_service_account';
36+
export const FunctionsRelationshipsSpec = {
37+
GOOGLE_CLOUD_FUNCTION_USES_IAM_SERVICE_ACCOUNT: {
38+
_class: RelationshipClass.USES,
39+
_type: 'google_cloud_function_uses_iam_service_account',
40+
sourceType: 'google_cloud_function',
41+
targetType: IAM_SERVICE_ACCOUNT_ENTITY_TYPE,
42+
},
43+
GOOGLE_CLOUD_FUNCTION_USES_SOURCE_REPOSITORY: {
44+
_type: 'google_cloud_function_uses_source_repository',
45+
_class: RelationshipClass.USES,
46+
sourceType: 'google_cloud_function',
47+
targetType: 'google_cloud_source_repository',
48+
},
49+
};

src/steps/functions/converters.ts

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export function createCloudFunctionEntity(
3737
status: cloudFunction.status,
3838
active: cloudFunction.status === 'ACTIVE',
3939
serviceAccountEmail: cloudFunction.serviceAccountEmail,
40+
sourceRepoUrl: cloudFunction.sourceRepository?.url,
4041
},
4142
},
4243
});

src/steps/functions/index.ts

+75-27
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import {
22
createDirectRelationship,
3+
Entity,
34
IntegrationStep,
45
RelationshipClass,
56
} from '@jupiterone/integration-sdk-core';
67
import { CloudFunctionsClient } from './client';
78
import { IntegrationConfig, IntegrationStepContext } from '../../types';
89
import { createCloudFunctionEntity } from './converters';
10+
import { STEP_IAM_SERVICE_ACCOUNTS } from '../iam';
911
import {
10-
CLOUD_FUNCTION_ENTITY_TYPE,
11-
STEP_CLOUD_FUNCTIONS,
12-
CLOUD_FUNCTION_ENTITY_CLASS,
13-
RELATIONSHIP_TYPE_CLOUD_FUNCTION_USES_IAM_SERVICE_ACCOUNT,
14-
STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS,
12+
FunctionEntitiesSpec,
13+
FunctionsRelationshipsSpec,
14+
FunctionStepsSpec,
1515
} from './constants';
1616
import {
17-
IAM_SERVICE_ACCOUNT_ENTITY_TYPE,
18-
STEP_IAM_SERVICE_ACCOUNTS,
19-
} from '../iam';
17+
CloudSourceRepositoriesEntitiesSpec,
18+
CloudSourceRepositoriesStepsSpec,
19+
} from '../cloud-source-repositories/constants';
2020

2121
export * from './constants';
2222

@@ -38,7 +38,7 @@ export async function buildCloudFunctionServiceAccountRelationships(
3838

3939
await jobState.iterateEntities(
4040
{
41-
_type: CLOUD_FUNCTION_ENTITY_TYPE,
41+
_type: FunctionEntitiesSpec.CLOUD_FUNCTION._type,
4242
},
4343
async (cloudFunctionEntity) => {
4444
const serviceAccountEmail = cloudFunctionEntity.serviceAccountEmail as
@@ -68,34 +68,82 @@ export async function buildCloudFunctionServiceAccountRelationships(
6868
);
6969
}
7070

71+
export async function buildCloudFunctionSourceRepoRelationships(
72+
context: IntegrationStepContext,
73+
): Promise<void> {
74+
const { jobState } = context;
75+
let sourceRepoEntities: Entity[] = [];
76+
77+
await jobState.iterateEntities(
78+
{
79+
_type: CloudSourceRepositoriesEntitiesSpec.REPOSITORY._type,
80+
},
81+
(sourceRepoEntity) => {
82+
sourceRepoEntities = [...sourceRepoEntities, sourceRepoEntity];
83+
},
84+
);
85+
86+
await jobState.iterateEntities(
87+
{
88+
_type: FunctionEntitiesSpec.CLOUD_FUNCTION._type,
89+
},
90+
async (cloudFunctionEntity) => {
91+
if (!cloudFunctionEntity?.sourceRepoUrl) {
92+
return;
93+
}
94+
95+
const sourceRepoUrl = cloudFunctionEntity?.sourceRepoUrl as string;
96+
97+
const sourceEntity = sourceRepoEntities.find((sourceRepoEntity) =>
98+
sourceRepoUrl.includes(sourceRepoEntity._key),
99+
);
100+
101+
if (sourceEntity) {
102+
await jobState.addRelationship(
103+
createDirectRelationship({
104+
_class: RelationshipClass.USES,
105+
from: cloudFunctionEntity,
106+
to: sourceEntity,
107+
}),
108+
);
109+
}
110+
},
111+
);
112+
}
113+
71114
export const functionsSteps: IntegrationStep<IntegrationConfig>[] = [
72115
{
73-
id: STEP_CLOUD_FUNCTIONS,
74-
name: 'Cloud Functions',
116+
id: FunctionStepsSpec.FETCH_CLOUD_FUNCTIONS.id,
117+
name: FunctionStepsSpec.FETCH_CLOUD_FUNCTIONS.name,
75118
dependsOn: [],
76-
entities: [
77-
{
78-
resourceName: 'Cloud Function',
79-
_type: CLOUD_FUNCTION_ENTITY_TYPE,
80-
_class: CLOUD_FUNCTION_ENTITY_CLASS,
81-
},
82-
],
119+
entities: [FunctionEntitiesSpec.CLOUD_FUNCTION],
83120
relationships: [],
84121
executionHandler: fetchCloudFunctions,
85122
},
86123
{
87-
id: STEP_CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS,
88-
name: 'Cloud Function Service Account Relationships',
89-
dependsOn: [STEP_CLOUD_FUNCTIONS, STEP_IAM_SERVICE_ACCOUNTS],
124+
id: FunctionStepsSpec.CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS.id,
125+
name: FunctionStepsSpec.CLOUD_FUNCTIONS_SERVICE_ACCOUNT_RELATIONSHIPS.name,
126+
dependsOn: [
127+
FunctionStepsSpec.FETCH_CLOUD_FUNCTIONS.id,
128+
STEP_IAM_SERVICE_ACCOUNTS,
129+
],
90130
entities: [],
91131
relationships: [
92-
{
93-
_class: RelationshipClass.USES,
94-
_type: RELATIONSHIP_TYPE_CLOUD_FUNCTION_USES_IAM_SERVICE_ACCOUNT,
95-
sourceType: CLOUD_FUNCTION_ENTITY_TYPE,
96-
targetType: IAM_SERVICE_ACCOUNT_ENTITY_TYPE,
97-
},
132+
FunctionsRelationshipsSpec.GOOGLE_CLOUD_FUNCTION_USES_IAM_SERVICE_ACCOUNT,
98133
],
99134
executionHandler: buildCloudFunctionServiceAccountRelationships,
100135
},
136+
{
137+
id: FunctionStepsSpec.CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIP.id,
138+
name: FunctionStepsSpec.CLOUD_FUNCTIONS_SOURCE_REPO_RELATIONSHIP.name,
139+
dependsOn: [
140+
FunctionStepsSpec.FETCH_CLOUD_FUNCTIONS.id,
141+
CloudSourceRepositoriesStepsSpec.FETCH_REPOSITORIES.id,
142+
],
143+
entities: [],
144+
relationships: [
145+
FunctionsRelationshipsSpec.GOOGLE_CLOUD_FUNCTION_USES_SOURCE_REPOSITORY,
146+
],
147+
executionHandler: buildCloudFunctionSourceRepoRelationships,
148+
},
101149
];

0 commit comments

Comments
 (0)