Managing and controlling resources is crucial in the cloud computing environment. Amazon Web Services (AWS) offers various services, including Amazon Elastic Compute Cloud (EC2), which provides scalable computing capacity in the cloud. Alongside AWS services, communication and collaboration tools like Slack have become integral to modern workflows. This article explores how to seamlessly integrate AWS Lambda functions with Slack to enable users to invoke actions such as rebooting, stopping, and starting EC2 instances directly from Slack channels. Using Lambda functions in combination with AWS services and Slack’s messaging platform streamlines operational tasks and enhances team collaboration and productivity.
Setting Up Lambda Function and Slack Integration
We utilize a Python Lambda function to facilitate communication between Slack and AWS Lambda. This Lambda function acts as a bridge, interpreting commands received from Slack, processing them, and executing corresponding actions on EC2 instances.
The Lambda function is configured to listen for incoming requests from Slack. When a request is received, it verifies the authenticity of the request using a signing key to prevent unauthorized access. Once validated, the function parses the Slack payload, extracts the user’s command, and executes the requested action on the specified EC2 instance.
Additionally, the Lambda function includes logic to prevent rapid consecutive executions of the same action within a short timeframe (less than 5 minutes). This prevents accidental or malicious triggering of actions and helps maintain system stability.
Implementation Steps:
- Log in to your AWS Management Console, search for AWS Lambda, and create a Function.
-
Provide the Basic Information for the Lambda Function, then click Create Function.
-
Function Name: instance_state_automation
-
Runtime: Python 3.12
-
- On the Code Source, paste the code below and click Deploy.
import json import os import boto3 import base64 import urllib.request SLACK_HOOK = os.environ["SLACK_HOOK"] PORTAL_INSTANCE_ID = os.environ["INSTANCE_ID"] def lambda_handler(event, context): try: # Parse event data slack_payload = event['body'] payload = parse_slack_payload(slack_payload) user_name = payload["user_name"] command_text = payload['text'].lower().strip() # Send initial processing message to Slack initial_response = f"{user_name} is invoking the command '{command_text}'. Please wait..." send_message_to_slack(initial_response) # Perform the EC2 action manage_ec2_instance_response = manage_ec2_instance(command_text, user_name) # Send the outcome of the EC2 action to Slack send_message_to_slack(manage_ec2_instance_response) # Return a simple HTTP response for successful processing return { 'statusCode': 200, "body": json.dumps({"text": "Request processed successfully."}) } except Exception as e: error_message = f"An error occurred: {str(e)}" send_message_to_slack(error_message) return { 'statusCode': 400, "body": json.dumps({"text": "An error occurred processing your request."}) } def parse_slack_payload(data): decoded_data_raw = base64.b64decode(data).decode('utf-8').split('&') decoded_data_formatted = {item.split('=')[0]: urllib.parse.unquote_plus(item.split('=')[1]) for item in decoded_data_raw} return decoded_data_formatted def manage_ec2_instance(action, user_name): ec2_client = boto3.client("ec2") try: if action == 'start': ec2_client.start_instances(InstanceIds=[PORTAL_INSTANCE_ID]) return f"{user_name}: EC2 instance has been started successfully." elif action == 'stop': ec2_client.stop_instances(InstanceIds=[PORTAL_INSTANCE_ID]) return f"{user_name}: EC2 instance has been stopped successfully." elif action == 'reboot': ec2_client.reboot_instances(InstanceIds=[PORTAL_INSTANCE_ID]) return f"{user_name}: EC2 instance has been rebooted successfully." else: return f"Invalid command by {user_name}. Please use the command with 'start', 'stop', or 'reboot'." except Exception as e: return f"{user_name} failed to {action} the EC2 Instance: {str(e)}" def send_message_to_slack(message): data = json.dumps({"text": message}).encode('utf-8') # Data needs to be bytes req = urllib.request.Request(SLACK_HOOK, data=data, headers={'Content-Type': 'application/json'}) with urllib.request.urlopen(req) as response: response_body = response.read().decode('utf-8') print("Message sent to Slack:", response_body)
Now, we will configure the Lambda Function’s environment variable, function URL, and the permission needed to enable it to work.
4. Click the Configurations beside the Monitoring.
5. Select the Environment Variables and the following:
-
-
SLACK_CHANNEL
= [your slack channel] -
SLACK_HOOK
= [your slack hook] -
SIGNING_KEY
= [your slack signing key] -
INSTANCE_ID
= [your instance ID]
-
6. Let’s add permission to allow the Lambda Function to start, stop, and reboot the EC2 instance. Firsts, select Permission then click the execution role name and paste the following JSON Permission. Save it.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "ec2:RebootInstances", "ec2:DescribeInstances", "ec2:StartInstances", "ec2:StopInstances", "ec2:DescribeInstanceStatus" ], "Resource": "*" } ] }
7. Create a Function URL, select NONE for the Auth Type, then for the invoke mode, choose buffered and save it.
Integration with Slack
The Lambda function is integrated with Slack using webhook URLs provided by Slack’s Incoming Webhooks feature. These URLs serve as endpoints to which the Lambda function sends messages containing updates on the status of EC2 actions.
Upon executing an action, such as starting, stopping, or rebooting an EC2 instance, the Lambda function sends a notification message back to the originating Slack channel. This real-time feedback keeps users informed of the outcome of their actions and fosters transparency within the team.
To integrate it, just follow the steps below:
- Go to your Slack Command API, and under Features, select Slash Commands. Click the Create New Command button and add the command that you want. Note that the command must start with
/
. - Next, add the Function URL we have just created on the Lambda Function.
- Then, add a short description and the usage hint, which are the list of parameters that can be passed, e.g. stop|start|reboot.
That’s it. You can now try to invoke the slash command in your Slack channel. To ensure that the command is really working, you can check your Event History in AWS CloudTrail.
Final Remarks
By combining the power of AWS Lambda, EC2, and Slack, organizations can streamline their cloud infrastructure management workflows and empower users to control resources directly from their preferred communication platform. The Lambda function presented in this article is a scalable and flexible solution for orchestrating EC2 instances, enhancing operational efficiency, and promoting collaboration among team members.
As cloud computing continues to evolve, integrating cloud services with popular collaboration tools like Slack will become increasingly important for driving productivity and innovation in modern enterprises.