packages/aws-cdk-lib/aws-codepipeline-actions/lib/inspector/scan-action-base.ts (70 lines of code) (raw):
import { Construct } from 'constructs';
import * as codepipeline from '../../../aws-codepipeline';
import * as iam from '../../../aws-iam';
import * as cdk from '../../../core';
import { Action } from '../action';
/**
* The CodePipeline variables emitted by the InspectorScan Action.
*/
export interface InspectorScanVariables {
/**
* The highest severity output from the scan.
*
* Valid values are medium | high | critical.
*/
readonly highestScannedSeverity: string;
}
/**
* Base construction properties of the `InspectorScanActionBase`.
*/
export interface InspectorScanActionBaseProps extends codepipeline.CommonAwsActionProps {
/**
* The number of critical severity vulnerabilities found in your source
* beyond which CodePipeline should fail the action.
*
* @default - no threshold
*/
readonly criticalThreshold?: number;
/**
* The number of high severity vulnerabilities found in your source
* beyond which CodePipeline should fail the action.
*
* @default - no threshold
*/
readonly highThreshold?: number;
/**
* The number of medium severity vulnerabilities found in your source
* beyond which CodePipeline should fail the action.
*
* @default - no threshold
*/
readonly mediumThreshold?: number;
/**
* The number of low severity vulnerabilities found in your source
* beyond which CodePipeline should fail the action.
*
* @default - no threshold
*/
readonly lowThreshold?: number;
/**
* Vulnerability details of your source in the form of a Software Bill of Materials (SBOM) file.
*/
readonly output: codepipeline.Artifact;
}
/**
* CodePipeline invoke action that uses AWS InspectorScan.
*/
export abstract class InspectorScanActionBase extends Action {
protected readonly props: InspectorScanActionBaseProps;
constructor(props: InspectorScanActionBaseProps) {
super({
...props,
category: codepipeline.ActionCategory.INVOKE,
provider: 'InspectorScan',
artifactBounds: { minInputs: 0, maxInputs: 1, minOutputs: 1, maxOutputs: 1 },
outputs: [props.output],
});
this.props = props;
}
/** The variables emitted by this action. */
public get variables(): InspectorScanVariables {
return {
highestScannedSeverity: this.variableExpression('HighestScannedSeverity'),
};
}
protected abstract renderActionConfiguration(): Record<string, any>;
protected bound(scope: Construct, stage: codepipeline.IStage, options: codepipeline.ActionBindOptions):
codepipeline.ActionConfig {
// see: https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-InspectorScan.html#edit-role-InspectorScan
options.role.addToPrincipalPolicy(new iam.PolicyStatement({
resources: ['*'],
actions: [
'inspector-scan:ScanSbom',
],
}));
const logGroupArn = cdk.Stack.of(scope).formatArn({
service: 'logs',
resource: 'log-group',
resourceName: `/aws/codepipeline/${stage.pipeline.pipelineName}`,
arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME,
});
const logGroupArnWithWildcard = `${logGroupArn}:*`;
options.role.addToPrincipalPolicy(new iam.PolicyStatement({
resources: [logGroupArn, logGroupArnWithWildcard],
actions: [
'logs:CreateLogGroup',
'logs:CreateLogStream',
'logs:PutLogEvents',
],
}));
// allow the Role access to the Bucket for outputs
if ((this.actionProperties.outputs ?? []).length > 0) {
options.bucket.grantWrite(options.role);
}
return {
configuration: {
...this.renderActionConfiguration(),
CriticalThreshold: this.props.criticalThreshold,
HighThreshold: this.props.highThreshold,
MediumThreshold: this.props.mediumThreshold,
LowThreshold: this.props.lowThreshold,
},
};
}
}