You have two AWS accounts:
Your goal is:
"CodePipeline in tools-account should run a Lambda function inside dev-account, wait for the Lambda to finish, and then either continue or stop the pipeline."
Since the Lambda is in another AWS account, CodePipeline cannot directly control it automatically. AWS solves this using:
The important part is:
The Lambda must explicitly tell CodePipeline whether the job succeeded or failed.
Without that callback, the pipeline does not properly know the final result.
Inside the dev-account, you create a Lambda function.
Example:
import boto3
codepipeline = boto3.client('codepipeline')
def lambda_handler(event, context):
job_id = event['CodePipeline.job']['id']
try:
print("Running validation")
# your deployment validation logic here
codepipeline.put_job_success_result(
jobId=job_id
)
except Exception as e:
codepipeline.put_job_failure_result(
jobId=job_id,
failureDetails={
'type': 'JobFailed',
'message': str(e)
}
)
raise
This Lambda can do things like:
put_job_success_result() Is ImportantThis is the key idea.
CodePipeline is not sitting inside the dev-account watching the Lambda directly.
Instead:
That callback is:
codepipeline.put_job_success_result()
or
codepipeline.put_job_failure_result()
Without this callback:
Now create an IAM Role inside the dev-account.
This role says:
"I trust the tools-account pipeline."
This is called a trust policy.
Example:
DevAccountCodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: DevAccount-CodePipeline-InvokeRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::<TOOLS_ACCOUNT_ID>:root
Action: sts:AssumeRole
This allows tools-account to temporarily become this role.
Now attach permissions to that role:
Policies:
- PolicyName: InvokeLambdaPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource:
- arn:aws:lambda:us-east-1:<DEV_ACCOUNT_ID>:function:MyFunction
This says:
"This role can invoke the Lambda."
The Lambda also needs permission to send success/failure results back to CodePipeline.
Example:
- Effect: Allow
Action:
- codepipeline:PutJobSuccessResult
- codepipeline:PutJobFailureResult
Resource: "*"
Without this:
Now in the tools-account, the pipeline execution role needs permission to assume the dev-account role.
Example:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- arn:aws:iam::<DEV_ACCOUNT_ID>:role/DevAccount-CodePipeline-InvokeRole
This is AWS security working both ways.
The dev-account must trust the tools-account, and the tools-account must also be allowed to assume the role.
Inside the pipeline stage:
- Name: InvokeValidationLambda
Actions:
- Name: RunValidation
ActionTypeId:
Category: Invoke
Owner: AWS
Provider: Lambda
Version: '1'
Configuration:
FunctionName: MyFunction
RoleArn: arn:aws:iam::<DEV_ACCOUNT_ID>:role/DevAccount-CodePipeline-InvokeRole
The important part is:
RoleArn:
This tells AWS:
"Before invoking Lambda, temporarily become this role in the dev-account."
When pipeline reaches this stage:
Example:
codepipeline.put_job_success_result(
jobId=job_id
)
Pipeline stage becomes successful.
Deployment continues.
Example:
codepipeline.put_job_failure_result(
jobId=job_id,
failureDetails={
'type': 'JobFailed',
'message': 'Validation failed'
}
)
Pipeline immediately stops.
Deployment terminates.