@@ -137,10 +137,12 @@ export default class PolicyPackPlugin extends Plugin {
137
137
}
138
138
139
139
private async executeRule ( {
140
+ data,
140
141
rules,
141
142
policyPack,
142
143
storageEngine,
143
144
} : {
145
+ data : any ,
144
146
rules : Rule [ ]
145
147
policyPack : string
146
148
storageEngine : StorageEngine
@@ -159,18 +161,17 @@ export default class PolicyPackPlugin extends Plugin {
159
161
160
162
findings . push (
161
163
...( await this . executeRule ( {
164
+ data,
162
165
rules : subRules ,
163
166
policyPack,
164
167
storageEngine,
165
168
} ) )
166
169
)
167
170
} else {
168
- const { data } = rule . gql
169
- ? await storageEngine . query ( rule . gql )
170
- : { data : undefined }
171
+ const ruleData = rule . gql ? data : undefined
171
172
const results = ( await this . policyPacksPlugins [
172
173
policyPack
173
- ] ?. engine ?. processRule ( rule , data ) ) as RuleFinding [ ]
174
+ ] ?. engine ?. processRule ( rule , ruleData ) ) as RuleFinding [ ]
174
175
175
176
findings . push ( ...results )
176
177
}
@@ -274,13 +275,69 @@ export default class PolicyPackPlugin extends Plugin {
274
275
}
275
276
}
276
277
278
+ private getLinkedData ( { providerData } : { providerData : ProviderData } ) : any {
279
+ const linkedData = { }
280
+ const allEntities = providerData ?. entities || [ ]
281
+ const allConnections = providerData ?. connections || { }
282
+ const entitiesById : { [ key : string ] : any } = { }
283
+
284
+ for ( const entity of allEntities ) {
285
+ // AddawsEc2Input! => queryawsEc2
286
+ const mutationName = / (?< = \[ ) ( .* ?) (? = \] ) /
287
+ . exec ( entity . mutation as any ) [ 0 ]
288
+ . replace ( 'Add' , 'query' )
289
+ . replace ( 'Input!' , '' )
290
+
291
+ linkedData [ mutationName ] = entity . data
292
+
293
+ for ( const entityData of entity . data ) {
294
+ entitiesById [ entityData . id ] = entityData
295
+ // eslint-disable-next-line no-underscore-dangle
296
+ entityData . __typename = mutationName . replace ( 'query' , '' ) // or entity.name?
297
+ }
298
+ }
299
+
300
+ // connect data on a second pass
301
+ for ( const entityId of Object . keys ( allConnections ) ) {
302
+ const entityConnections = allConnections [ entityId ]
303
+ const entity = entitiesById [ entityId ]
304
+ if ( ! entity ) {
305
+ // eslint-disable-next-line no-continue
306
+ continue
307
+ }
308
+ for ( const conn of entityConnections ) {
309
+ const targetEntity = entitiesById [ conn . id ]
310
+ if ( ! targetEntity ) {
311
+ // eslint-disable-next-line no-continue
312
+ continue
313
+ }
314
+ if ( conn . relation === 'child' ) {
315
+ if ( ! entity [ conn . field ] ) {
316
+ entity [ conn . field ] = [ ]
317
+ }
318
+ entity [ conn . field ] . push ( targetEntity )
319
+ // inverse relation
320
+ // const inverseConnField = this.schemasMap[entity.__typename] || 'account' // @TODO: account doesn't have a name
321
+ // if (!targetEntity[inverseConnField]) {
322
+ // targetEntity[inverseConnField] = []
323
+ // }
324
+ // targetEntity[inverseConnField].push(entity)
325
+ } // else parent relation.. is not used atm
326
+ }
327
+ }
328
+
329
+ return linkedData
330
+ }
331
+
277
332
async execute ( {
278
333
storageRunning,
279
334
storageEngine,
335
+ providerData,
280
336
processConnectionsBetweenEntities,
281
337
} : {
282
338
storageRunning : boolean
283
339
storageEngine : StorageEngine
340
+ providerData : ProviderData
284
341
processConnectionsBetweenEntities : ( props : {
285
342
provider ?: string
286
343
providerData : ProviderData
@@ -314,7 +371,10 @@ export default class PolicyPackPlugin extends Plugin {
314
371
mergeSchemas ( currentSchema , findingsSchema ) ,
315
372
] )
316
373
374
+ const linkedData = this . getLinkedData ( { providerData } )
375
+
317
376
const findings = await this . executeRule ( {
377
+ data : linkedData ,
318
378
rules,
319
379
policyPack,
320
380
storageEngine,
0 commit comments