DevSecOps with AWS – ChatOps with AWS and AWS Developer Tools – Part 2
Tags: aws, devops, ai, devsecops
Published: 2023-06-13 05:07:15

**_Level 300_**

**Table of Contents**  

- [How AWS Chatbot works](#how-aws-chatbot-works)
- [Hands On](#hands-on)
  - [Requirements](#requirements)
    - [AWS Chatbot requirements](#aws-chatbot-requirements)
  - [AWS Services](#aws-services)
  - [Solution Overview](#solution-overview)
    - [Step by Step](#step-by-step)

According to the first part of this series, in this blog post you can learn more about chatops and how AWS Chatbot could help you and make your operations more efficient and modern.

Imagine that you wish to approve with voice commands from your favorite tool the manual action required for promoting from one environment another.

> You can combine Microsoft teams, Microsoft Speech Tech and AWS Chatbots.

# How AWS Chatbot works

AWS Chatbot uses Amazon Simple Notification Service (Amazon SNS) topics to send event and alarm notifications from AWS services to your chat channels. Once an SNS topic is associated with a configured chat client, events and alarms from various services are processed and notifications are delivered to the specified chat channels and webhooks. For Microsoft Teams and Slack, after an administrator approves AWS Chatbot support for the workspace or tenant, anyone in the workspace or team can add AWS Chatbot to their chat channels. For Amazon Chime, users with AWS Identity and Access Management (IAM) permissions to use Amazon Chime can add AWS Chatbot to their webhooks. You use the AWS Chatbot console to configure chat clients to receive notifications from SNS topics. 
AWS Chatbot supports a number of AWS services, including Amazon CloudWatch, AWS Billing and Cost Management, and AWS Security Hub

# Hands On
## Requirements

- cdk >= 2.73.0
- AWS CLI >= 2.7.0
- Python >= 3.10.4
- Pytest >= 7.1.3
- cdk-nag >=2.18.44
- checkov >= 2.1.229
- Windows 10 or 11 with Microsoft Online Speech Tech 
- Microsoft Teams Channel 
- AWS Chat 

### AWS Chatbot requirements
To use AWS Chatbot, you need the following:
•	An AWS account to associate with Amazon Chime, Microsoft Teams, or Slack chat clients during AWS Chatbot setup. 
•	Administrative privileges for your Amazon Chime chat room, Microsoft Teams tenant, or Slack workspace. You can be the Slack workspace owner or have the ability to work with workspace owners to get approval for installing AWS Chatbot.
•	Familiarity with AWS Identity and Access Management (IAM) and IAM roles and policies. For more information about IAM, see What is IAM? in the IAM User Guide.
•	Experience with the AWS services supported by AWS Chatbot, including experience configuring those services to subscribe to Amazon Simple Notification Service (Amazon SNS) topics to send notifications. For information about supported services, see [Using AWS Chatbot with Other AWS Services](https://docs.aws.amazon.com/chatbot/latest/adminguide/related-services.html).

## AWS Services

- [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/): is an open-source software development framework to define your cloud application resources using familiar programming languages.
- [AWS Identity and Access Management (IAM)](https://aws.amazon.com/iam/?nc2=h_ql_prod_se_iam): Securely manage identities and access to AWS services and resources.
- [AWS IAM Identity Center (Successor to AWS Single Sign-On)](https://aws.amazon.com/iam/identity-center/): helps you securely create or connect your workforce identities and manage their access centrally across AWS accounts and applications.
- [AWS CodeCommit](https://aws.amazon.com/codecommit/): secure, highly scalable, managed source control service that hosts private Git repositories.
- [AWS CodeBuild](https://aws.amazon.com/codebuild/): fully managed continuous integration service that compiles source code, runs tests, and produces software packages that are ready to deploy.
- [AWS CodePipeline](https://aws.amazon.com/codepipeline/): fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates.
- [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/): lets you create, manage, and control cryptographic keys across your applications and more than 100 AWS services.
- [AWS CloudFormation](https://aws.amazon.com/cloudformation/): Speed up cloud provisioning with infrastructure as code as code
- [AWS Lambda](https://aws.amazon.com/lambda/?nc2=h_ql_prod_cp_lbd): A serverless compute service that lets you run code without provisioning or managing servers, build workload-based cluster scaling logic, maintain event integrations, or manage runtimes.
- [AWS Chatbot](https://aws.amazon.com/chatbot/): Monitor, operate, and troubleshoot your AWS resources with interactive ChatOps
- [AWS Resource Explorer](https://aws.amazon.com/resourceexplorer/):  is a managed capability that simplifies the search and discovery of your AWS resources across AWS Regions.



## Solution Overview

![ChatOps and AWS chatbot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1im2wz30v1ihduqa40n.jpg)
Figure 1- Solution Overview


The Figure 1 depicts the general architecture for this demonstration: 

1. The pipeline starts or change.
2. The pipeline events are captured and trigger a lambda service
3. Lambda service loads the secret webhook url from secrets manager and send the notification card to Microsoft teams Channel. 
4. There is an alternative for sending notifications easy and simple, using Codestar notifications or SNS with email subscription.
5. Finally the manual steps as approve transition is invoked from chat using AWS Chatbot Service.

### Step by Step

Prepare your Microsoft Teams. 

First, you need a channel and AWS app installed as follow:

![Microsoft Teams Config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sg9tab1eormx0euwxfkz.png)
Figure 2. Microsoft Teams and AWS App.

Second, Review the permissions and add to a team. Now you must select a channel and finish the process.

![Microsoft Teams Config 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/584mtq9hnij3w64shl1p.png)
Figure 3. Microsoft Teams and AWS Chatbot Setup

Almost ready, now is time to setup AWS chatbot in AWS Account, for this case the DevSecOps account. 

Fourth, enable AWS Resource Explorer.
Follow quick setup instructions. In this case the aggregator index region will be Ohio, however, you can choose other region.

![AWS Resource Explorer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i63n98mhidxzecwvibr1.png)
Figure 4. Enable AWS Resource Explorer.

> Finally, setup AWS Chatbot
	
Fifth, copy and paste the Microsoft Teams channel url. 

![Microsoft Teams channel url](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2mjfrpx9c2r5jca44ej.png)
Figure 5. Microsoft Teams channel url.

Sixth, go to AWS Chatbot console and select Microsoft Team Option in menu has depicts the following image.


![AWS Chatbot Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/db9g8yfxti9rpw0ux828.png)
Figure 6. AWS Chatbot Console for microsoft Teams

You must approve the required permissions. 

![Teams Requiered Permission](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7y2m9oo9zch6oodswsi.png)

Copy the Team ID and tenant ID.


![Tenant Id](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tuwcm2jobgjcz4cdj3a.png)
Figure 7. Tenant ID and Team ID.


Seventh, deploy the pipeline code with updates, in this update a SNS Topic is introduce for chatbot notifications, also the stacks create a role for chatbot users, and Teams Configuration for AWS Chatbot.

{% embed https://github.com/velez94/cdkv2_pipeline_multienvironment %}

The following code shows the IAM role for AWS Chatbot, also, in the project properties (`project_configs/environment_options/environment_options.yaml`) the new option `chat_ops: "enable"` was introduced: 

```python
from aws_cdk import (
    aws_iam as iam,
    CfnOutput,
)

from constructs import Construct


class IAMAWSChatbot(Construct):

    def __init__(self, scope: Construct, construct_id: str,
                 project_name: str = None,
                 emails: list = None,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        chat_role = iam.Role(self, f"AWSChatbotRole-{project_name}", assumed_by=iam.ServicePrincipal(service="chatbot"),
                             role_name=f"AWSChatbotRole-{project_name}",
                             description=f"AWS Chatbot Role for {project_name}",
                             managed_policies=[
                                 iam.ManagedPolicy.from_aws_managed_policy_name("ReadOnlyAccess"),
                                 iam.ManagedPolicy.from_aws_managed_policy_name("AWSResourceExplorerReadOnlyAccess"),
                                 iam.ManagedPolicy.from_aws_managed_policy_name("AWSSupportAccess"),
                                 iam.ManagedPolicy.from_aws_managed_policy_name("AWSCodePipelineApproverAccess"),
                             ]
                             )
        chat_denny = iam.PolicyStatement(effect=iam.Effect.DENY, actions=["iam:*",
                                                                          "s3:GetBucketPolicy",
                                                                          "ssm:*",
                                                                          "sts:*",
                                                                          "kms:*",
                                                                          "cognito-idp:GetSigningCertificate",
                                                                          "ec2:GetPasswordData",
                                                                          "ecr:GetAuthorizationToken",
                                                                          "gamelift:RequestUploadCredentials",
                                                                          "gamelift:GetInstanceAccess",
                                                                          "lightsail:DownloadDefaultKeyPair",
                                                                          "lightsail:GetInstanceAccessDetails",
                                                                          "lightsail:GetKeyPair",
                                                                          "lightsail:GetKeyPairs",
                                                                          "redshift:GetClusterCredentials",
                                                                          "storagegateway:DescribeChapCredentials"],
                                         resources=["*"]
                                         )

        chat_cw = iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                      actions=["cloudwatch:Describe*",
                                               "cloudwatch:Get*",
                                               "cloudwatch:List*"],
                                      resources=["*"]
                                      )
        policy = iam.Policy(self, f"AWSChatbotCWPolicy-{project_name}",
                            policy_name=f"AWSChatbotCWPolicy-{project_name}",
                            statements=[chat_cw, chat_denny]
                            )
        chat_role.attach_inline_policy(policy)

        CfnOutput(self, "AWSChatBotRoleARN", description="AWSChatBotRoleARN", value=chat_role.role_arn)

```

The other construct create a SNS topic, and Microsoft Teams Channel Configuration.

[The key parameters are](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_chatbot/CfnMicrosoftTeamsChannelConfiguration.html): 

- **iam_role_arn (str)** – The ARN of the IAM role that defines the permissions for AWS Chatbot . This is a user-defined role that AWS Chatbot will assume. This is not the service-linked role. For more information, see IAM Policies for AWS Chatbot .

- **team_id (str)** – The ID of the Microsoft Team authorized with AWS Chatbot . To get the team ID, you must perform the initial authorization flow with Microsoft Teams in the AWS Chatbot console. Then you can copy and paste the team ID from the console. For more details, see steps 1-4 in Get started with Microsoft Teams in the AWS Chatbot Administrator Guide .

- **teams_channel_id (str)** – The ID of the Microsoft Teams channel. To get the channel ID, open Microsoft Teams, right click on the channel name in the left pane, then choose Copy. An example of the channel ID syntax is: `19%3ab6ef35dc342d56ba5654e6fc6d25a071%40thread.tacv2` .

- **teams_tenant_id (str)** – The ID of the Microsoft Teams tenant. To get the tenant ID, you must perform the initial authorization flow with Microsoft Teams in the AWS Chatbot console. Then you can copy and paste the tenant ID from the console. For more details, see steps 1-4 in Get started with Microsoft Teams in the AWS Chatbot Administrator Guide .

> Pay attention to the guardrails, is recommended set the ARN policies for limit actions. Channel guardrail policies provide detailed control over what actions your channel members can take. These guardrail policies are applied at runtime to both channel IAM roles and user roles. What channel members are allowed to do is the intersection of role permissions and guardrail policies.


- **guardrail_policies (Optional[Sequence[str]])** – The list of IAM policy ARNs that are applied as channel guardrails. The AWS managed ‘AdministratorAccess’ policy is applied as a default if this is not set.

- **logging_level (Optional[str])** – Specifies the logging level for this configuration. This property affects the log entries pushed to Amazon CloudWatch Logs. Logging levels include ERROR , INFO , or NONE .

- **sns_topic_arns (Optional[Sequence[str]])** – The ARNs of the SNS topics that deliver notifications to AWS Chatbot .

The following is the Construct code:
```python
from aws_cdk import (
    aws_chatbot as chatbot,
    aws_sns as sns,
    CfnOutput, Aws
)

from constructs import Construct
from .iam_chatbot import IAMAWSChatbot


class MicrosoftTeamsChannelConfiguration(Construct):

    def __init__(self, scope: Construct, construct_id: str,

                 props: dict = None,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Create Iam Role
        chat_iam = IAMAWSChatbot(self, "IAMRole", project_name=props["project_name"])

        # Create sns topic
        self.sns_topíc = sns.Topic(self, props["project_name"], display_name=f"ChatOps{props['project_name']}",
                              topic_name=f"ChatOps{props['project_name']}")
        self.arn_teams = f"arn:aws:chatbot::{Aws.ACCOUNT_ID}:chat-configuration/microsoft-teams-channel/MicrosoftTeamsChannel-{props['project_name']}"
        # Define properties
        self.teams_conf = chatbot.CfnMicrosoftTeamsChannelConfiguration(self,
                                                                        f"MicrosoftTeamsChannel-{props['project_name']}",
                                                                        configuration_name=f"MicrosoftTeamsChannel-{props['project_name']}",
                                                                        iam_role_arn=chat_iam.chat_role.role_arn,
                                                                        # "teamId",
                                                                        team_id=props["team_id"],
                                                                        # "teamsChannelId"
                                                                        teams_channel_id=props["teams_channel_id"],
                                                                        # "teamsTenantId"
                                                                        teams_tenant_id=props["teams_tenant_id"],

                                                                        # the properties below are optional
                                                                        guardrail_policies=[
                                                                            "arn:aws:iam::aws:policy/AWSCodePipeline_FullAccess",
                                                                            "arn:aws:iam::aws:policy/ReadOnlyAccess"
                                                                        ],
                                                                        logging_level="ERROR",
                                                                        sns_topic_arns=[self.sns_topíc.topic_arn],
                                                                        user_role_required=False
                                                                        )

        CfnOutput(self, "OutputTeams", value=self.teams_conf.attr_arn)

```

Eight, verify the configurations into AWS Chatbot console.


![AWS Chatbot Conf](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tly1zdu03btihgogdh3g.png)
Figure 8. AWS Chatbot Microsoft settings.

Finally, the code have some changes for lambda function for helping to call to aws bot and run commands. You can see them in lambda code. 

The notifications look as the Figure 9 depicts.

![Microsoft Teams Custom notifications](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zcsztfejn6t9eitj0mpo.png)
Figure 9. Microsoft Teams Custom notifications. 

You can pass **Approved** or **Rejected** for result with custom message as the Figure 10 depicts. 


![ChatOps Final](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzzcq3mlopi9jelbdkct.png)
Figure 10. Final Result.



 

Thanks for reading and sharing! :blush: :computer: