UNPKG

@cloud-copilot/iam-lens

Version:

Visibility in IAM in and across AWS accounts

81 lines 3.93 kB
import {} from '@cloud-copilot/job'; import { IamCollectClient } from '../collect/client.js'; import {} from '../utils/s3Abac.js'; import { PullBasedJobRunner } from '../workers/JobRunner.js'; import { convertToDenialDetails, toLightRequestAnalysis } from './requestAnalysis.js'; import {} from './whoCan.js'; import { executeWhoCan } from './WhoCanWorker.js'; /** * Creates a main-thread simulation runner that pulls tagged work items from * the processor's FIFO scheduler and routes results back by requestId. * * The requestId is threaded through the job's properties so it is available * in onComplete without needing the workerId. * * @param dequeueWork - Function to dequeue the next tagged work item. * @param onSimulationResult - Callback for simulation results. * @param onCheckDenyDetails - Callback to check whether to collect deny details. * @param onDenyDetail - Callback for deny detail delivery. * @param collectClient - The IAM collect client for fetching policy data. * @param s3AbacOverride - Optional override for S3 ABAC when checking S3 Bucket access. * @param collectGrantDetails - Whether to collect grant details for allowed simulations. * @param concurrency - The number of concurrent simulations to run on the main thread. Defaults to 50. * @returns a PullBasedJobRunner that processes tagged whoCan work items. */ export function createMainThreadStreamingWorkQueue(dequeueWork, onSimulationResult, onCheckDenyDetails, onDenyDetail, collectClient, s3AbacOverride, collectGrantDetails, concurrency = 50) { return new PullBasedJobRunner(concurrency, async () => { return dequeueWork(); }, (taggedItem) => { const { requestId, ...workItem } = taggedItem; return { properties: { requestId, collectDenyDetails: workItem.collectDenyDetails }, execute: async (context) => { return executeWhoCan(workItem, collectClient, { s3AbacOverride, collectDenyDetails: workItem.collectDenyDetails, collectGrantDetails, strictContextKeys: workItem.strictContextKeys }); } }; }, async (result) => { const { requestId, collectDenyDetails } = result.properties; if (result.status === 'fulfilled') { const executionResult = result.value; if (executionResult.type === 'allowed') { onSimulationResult(requestId, { status: 'fulfilled', value: executionResult.allowed, properties: {} }); } else { // Denied — handle deny details BEFORE reporting the simulation result, // because onSimulationResult may trigger request completion checks. const hasDetails = executionResult.type === 'denied_single' || executionResult.type === 'denied_wildcard'; if (collectDenyDetails && hasDetails) { const lightAnalysis = toLightRequestAnalysis(executionResult); const shouldInclude = onCheckDenyDetails(requestId, lightAnalysis); if (shouldInclude) { onDenyDetail(requestId, convertToDenialDetails(executionResult)); } } // Now report the denied simulation result (may trigger completion check) onSimulationResult(requestId, { status: 'fulfilled', value: undefined, properties: {} }); } } else { // Error case onSimulationResult(requestId, { status: 'rejected', reason: result.reason, properties: {} }); } }); } //# sourceMappingURL=WhoCanMainThreadWorker.js.map