Amazon Code Pipeline Status notification to Microsoft Teams

Hello Techies,

I recently worked on one project where I was using AWS on codepipeline. In our project, we need to provide Code Pipeline status back to the application team immediately. So that team can take quick action on that and speed up deployment/delivery. Based on this requirement, we have decided to implement Microsoft Team Notification where your AWS Code Pipeline state will be sent to the Microsoft Teams channel. This article will help you to implement AWS CodePipleline notification with Microsoft Teams Webhook Channel.

Ref – How to configure incoming webhook on Microsoft Team channel

Sample CodePipeline Webhook Notification

How does it work?

The main role played by Cloudwatch Events Rule. It is checking the Code Pipeline Execution State Change and When the pipeline state is FAILED/SUCCEEDED it sends the event to SNS and Amazon SNS triggers the lambda function with a message to the Microsoft Teams channel.

Prerequisites

  • AWS-CLI to deploy AWS Cloud Formation Stack
  • Incoming Webhook URL for your Microsoft Teams Channel
  • Working AWS Code Pipeline
  • At least basic experience with AWS Cloud Formation
  • Basic syntax knowledge of Python

Cloud Formation Code

AWSTemplateFormatVersion: '2010-09-09'
Description: Caz Creek IAM Roles - 1.6.0
Parameters:
  TeamsURL:
    Description: "Incoming Microsoft Teams Webhook URL"
    Type: String
    Default: "<MS TEAM WEB HOOK URL>"
    # ToDo Add your Incoming Webhood URL
  CodePipelineName:
    Description: "Codepipeline Name"
    Type: String
    Default: "<CODE PIPELINE NAME>"
    #TODO Add your parameter

Resources:
  NotificationLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.index_handler
      Code:
        ZipFile: |
          import urllib3
          import json
          import os
          http = urllib3.PoolManager()
          def index_handler(event, context):
              url = os.environ['TEAMS_URL']
              event_message = event['Records'][0]['Sns']['Message']
              message_dict  = json.loads(event_message)
              pipeline_name = message_dict["detail"]["pipeline"]
              pipeline_status = message_dict["detail"]["state"]
              print(pipeline_name)

              msg = {
                  "text": f"Pipeline: {pipeline_name} has: {pipeline_status}"
              }

              encoded_msg = json.dumps(msg).encode('utf-8')
              resp = http.request('POST',url, body=encoded_msg)
              print({
                  "message": pipeline_name,
                  "status_code": resp.status,
                "response": resp.data
              })
      MemorySize: 128
      Environment:
        Variables:
          TEAMS_URL: !Ref TeamsURL
      Runtime: 'python3.7'
      Timeout: 30
      Role: !GetAtt NotificationLambdaFunctioneRole.Arn

  NotificationLambdaFunctioneRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'lambda.amazonaws.com'
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: 'customresource'
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - 'sns:*'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: '*'
  EventRule:
    DependsOn: NotificationLambdaFunction
    Type: AWS::Events::Rule
    Properties:
      Description: "EventRule"
      EventPattern:
        source:
          - "aws.codepipeline"
        detail-type:
          - "CodePipeline Pipeline Execution State Change"
        detail:
          state:
            - "FAILED"
            - "SUCCEEDED"
          pipeline:
            - !Ref CodePipelineName
        resources:
          - !Sub 'arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${CodePipelineName}'
      State: "ENABLED"
      Targets:
        -
          Arn:
            Ref: "SNSTopic"
          Id: "NotificationTeams"
  PermissionLambda:
    DependsOn: NotificationLambdaFunction
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName:
        Ref: "NotificationLambdaFunction"
      Action: "lambda:InvokeFunction"
      Principal: "sns.amazonaws.com"
      SourceArn: !Ref SNSTopic

  SNSTopic:
    DependsOn: NotificationLambdaFunction
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: String
      Subscription:
        - Protocol: lambda
          Endpoint: !GetAtt NotificationLambdaFunction.Arn

  SnsTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    DependsOn: SNSTopic
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: SnsTopicPolicy
            Effect: Allow
            Principal:
              AWS: "*"
            Action:
              - "SNS:GetTopicAttributes"
              - "SNS:SetTopicAttributes"
              - "SNS:AddPermission"
              - "SNS:RemovePermission"
              - "SNS:DeleteTopic"
              - "SNS:Subscribe"
              - "SNS:ListSubscriptionsByTopic"
              - "SNS:Publish"
              - "SNS:Receive"
            Resource:
              Ref: SNSTopic
          - Sid: SnsTopicPolicyEvent
            Effect: Allow
            Principal:
              Service: "events.amazonaws.com"
            Action:
              - "SNS:Publish"
            Resource:
              Ref: SNSTopic
      Topics:
        - Ref: SNSTopic

In this Cloud Formation template, we have two parameters which need to be updated as per your configuration. One is Incoming Webhook URL from you Microsoft Teams Channel and second AWS Code Pipeline Name. Make sure to update both.

AWS Cloud Formation Deployment

Deploy your AWS Cloud Formation template from your local machine using AWS CLI command, however you can deploy it directly from AWS Cloud Formation page.

aws cloudformation package 
--template-file codepipeline-ms-team-notification.yaml 
--s3-bucket <MY-PACKAGE-CFN-BUCKET> 
--output-template-file your-notification-output.yaml

aws cloudformation deploy
--template-file codepipeline-ms-team-notification.yaml
--stack-name team-notification-cloudformation-stack
--capabilities CAPABILITY_NAMED_IAM

Thanks for reading!

Leave a Comment