DEV Community

Cover image for Securing Customer Support with AWS Services and Slack Integration
Nada Ahmed
Nada Ahmed

Posted on

Securing Customer Support with AWS Services and Slack Integration

In this post, I’ll guide you through the creation of a secure customer support system leveraging various AWS services, integrated with Slack for streamlined communication. This architecture effectively manages support tickets while ensuring data security and efficient workflow.

Project Overview

The system facilitates customer ticket creation and management through a robust backend, utilizing the following components:

  1. Ticket Creation: Customers initiate support requests via a user-friendly interface, which sends the data to AWS API Gateway.
  2. Data Storage: Upon receiving the request, API Gateway triggers a Lambda function that processes the ticket information and stores it in DynamoDB.
  3. Notifications: An SNS (Simple Notification Service) notification is dispatched to alert support agents of the new ticket, ensuring they can respond promptly.
  4. Ticket Retrieval: Support agents can retrieve tickets by sending a request to another API Gateway endpoint. This request invokes a Lambda function that fetches ticket details from DynamoDB using the ticket ID.
  5. Customer Messaging: To communicate with customers, another Lambda function is invoked, sending messages through Slack's API.
  6. Ticket Closure: When the status of a ticket changes to "closed," a Lambda function triggers to transfer the ticket data from DynamoDB to S3 and to an archival DynamoDB table.

Step-by-Step Implementation

1. Create DynamoDB for Ticket Storage

a. Set Up a New Table
  1. In the AWS Management Console, navigate to DynamoDB and select “Create table.”
  2. Configure:
    • Table Name: SupportTickets
    • Primary Key: TicketID (String)
  3. Capacity: Keep default settings for initial testing.
  4. Save the table.
b. Add Attributes

Consider adding these fields:

  • CustomerName (String)
  • IssueDescription (String)
  • Status (String) - Default: "Open"

1.1 Create an Archival DynamoDB Table

Repeat the above steps to create another table:

  • Table Name: ArchivedTickets
  • Primary Key: TicketID (String)

Note: Enable DynamoDB Streams on both tables. This feature provides a real-time data stream of item-level changes in a DynamoDB table. This feature is beneficial for tracking changes to your customer support tickets

Image description

Image description

Image description

Image description

Image description

Image description

2. Configure Amazon SNS for Notifications

a. Create a New Topic

  1. Go to SNS in the AWS Console.
  2. Select “Create topic” and name it SupportTicketNotifications.

b. Subscribe Agents

  1. Open SupportTicketNotifications.
  2. Create a subscription for each agent using Email/SMS and input their details.

Image description

Image description

Image description

Image description

Image description

Image description

Image description

Image description

Image description

3. Create AWS Lambda Functions

This function handles incoming ticket creation requests. It processes the ticket information, stores it in DynamoDB, and sends a notification through SNS to inform relevant parties of the new ticket.

a. Function Setup

  1. Navigate to Lambda in the AWS Console.
  2. Create New Function: Click "Create function."
  3. Configuration:
    • Name: CreateTicket
    • Runtime: Python (or Node.js)
    • Permissions: Create a new role with Lambda permissions.
  4. Save: Click “Create.”

Image description

Image description

Image description

Image description

b. Code the CreateTicket Function

  • Replace the default code with this:
import json
import boto3
from uuid import uuid4

dynamodb = boto3.resource('dynamodb')
sns = boto3.client('sns')
table = dynamodb.Table('SupportTickets')

def lambda_handler(event, context):
    body = json.loads(event['body'])
    ticket_id = str(uuid4())
    response = table.put_item(
        Item={
            'TicketID': ticket_id,
            'CustomerName': body['customerName'],
            'IssueDescription': body['issueDescription'],
            'Status': 'Open'
        }
    )
    message = f"New ticket created: {ticket_id} - {body['customerName']}"
    sns.publish(TopicArn='arn:aws:sns:eu-north-1:533267368463:SupportTicketNotifications', Message=message)
    return {
        'statusCode': 201,
        'body': json.dumps({'TicketID': ticket_id})
    }
Enter fullscreen mode Exit fullscreen mode

Note
Make sure to select and attach the required policy to the Lambda execution role to ensure it has the necessary permissions for your function's operations.

Image description

Image description

3.1 Create Another AWS Lambda Functions for retrieve

 messages
Enter fullscreen mode Exit fullscreen mode
  • Create a new function called GetTicket by following the same steps used to set up the Lambda function for creating a ticket.

This function retrieves ticket details based on the ticket ID provided by the support agent. It queries the DynamoDB table to fetch and return the ticket information.

Image description

c. Code the GetTicket Function

import json
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('SupportTickets')

def lambda_handler(event, context):
    ticket_id = event['pathParameters']['ticketId']
    response = table.get_item(Key={'TicketID': ticket_id})
    item = response.get('Item')

    if item:
        return {
            'statusCode': 200,
            'body': json.dumps(item)
        }
    else:
        return {
            'statusCode': 404,
            'body': json.dumps({'error': 'Ticket not found'})
        }

Enter fullscreen mode Exit fullscreen mode

Note
Make sure to select and attach the required policy to the Lambda execution role to ensure it has the necessary permissions for your function's operations.

Image description

4. Slack Integration for Real-Time Messaging

Step 1: Set Up Incoming Webhook in Slack

  1. Visit Slack API and sign in.
  2. Create a new app and enable Incoming Webhooks.
  3. Generate a Webhook URL to use within Lambda for message sending.

Image description
Image description
Image description
Image description

Step 2 Create Another Lambda function for sendmessage

This function sends real-time messages to the designated Slack channel, facilitating communication with customers. It ensures that updates or responses related to the ticket are communicated promptly.

c. Code the sendmessage function Function

import json
import requests
import os

def lambda_handler(event, context):
    # Extract the message from the API Gateway event body
    try:
        message = json.loads(event['body']).get('text', 'Default message to Slack')
    except json.JSONDecodeError:
        message = 'Default message to Slack'

    # Define Slack webhook URL from environment variable
    slack_webhook_url = os.environ['SLACK_WEBHOOK_URL']

    # Prepare the payload to send to Slack
    slack_payload = {
        'text': message
    }

    # Send the message to Slack
    response = requests.post(slack_webhook_url, json=slack_payload)

    # Check for success or error in the Slack response
    if response.status_code == 200:
        return {
            'statusCode': 200,
            'body': json.dumps('Message sent to Slack successfully!')
        }
    else:
        return {
            'statusCode': 500,
            'body': json.dumps(f'Failed to send message to Slack: {response.text}')
        }
Enter fullscreen mode Exit fullscreen mode

Note
Ensure that you use environment variables to securely store this information. You can utilize Secrets Manager for added security. Additionally, install the Requests library locally and create a ZIP file for deployment.

Image description

5. Set Up API Gateway

a. Create API

  1. Open API Gateway in the AWS Console.
  2. New API: Select "Create API."
  3. Type: Choose "HTTP API."
  4. API Name: CustomerSupportAPI
  5. Save: Click “Create.”

Image description

Image description

Image description

b. Define Endpoints

  1. Create Ticket Endpoint:
    • Path: /createticket
    • Method: POST
    • Integration: Connect to a Lambda function for createticket
  2. Retrieve Ticket Endpoint:
    • Path: /tickets/{ticketId}
    • Method: GET
    • Integration: Connect to another Lambda function for retrieving details.
    • Send Message Endpoint:
    • Path: /sendmessage
    • Method: post
    • Integration: Connect to another Lambda function for sending messages.

Image description

Image description

Image description

Image description

6. Set Up Amazon S3 for Document Storage

a. Create S3 Bucket

  1. Open S3 in AWS Console.
  2. New Bucket: Click “Create bucket.”
  3. Name: support-documents
  4. Region: Same as other resources
  5. Save: Click “Create.”

b. Set Permissions

  • Adjust S3 bucket policy to allow Lambda function access.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::533267368463:role/service-role/ArchiveClosedTickets-role-qbc73yay"
},
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::support-ticket-archive/*"
}
]
}

Image description

Image description

7 Create the final lambda function for ArchiveClosedTickets

This function is triggered when a ticket status changes to closed. It archives the ticket by moving it from the DynamoDB table to an S3 bucket and updating the archived tickets table.

Image description

code for this lambda

import json
import boto3
import datetime
import logging

# Set up logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
archive_table = dynamodb.Table('ArchivedTickets')
archive_bucket = 'support-ticket-archive'
tickets_table = dynamodb.Table('SupportTickets')

def lambda_handler(event, context):
    for record in event['Records']:
        if record['eventName'] == 'MODIFY':
            new_image = record['dynamodb']['NewImage']
            old_image = record['dynamodb']['OldImage']

            if new_image['Status']['S'] == 'closed' and old_image['Status']['S'] != 'closed':
                ticket_id = new_image['TicketID']['S']

                # Log ticket ID
                logger.info(f'Processing ticket: {ticket_id}')

                # Create JSON object for the archived ticket
                ticket_data = {
                    'TicketID': ticket_id,
                    'CustomerName': new_image.get('CustomerName', {}).get('S', 'Unknown'),
                    'IssueDescription': new_image.get('IssueDescription', {}).get('S', 'No description'),
                    'Status': new_image['Status']['S'],
                    'Comments': new_image.get('Comments', {}).get('S', ''),
                }

                # Define file path in S3
                file_name = f"{ticket_id}.json"

                # Upload JSON to S3
                s3.put_object(
                    Bucket=archive_bucket,
                    Key=file_name,
                    Body=json.dumps(ticket_data)
                )

                # Get S3 URL
                s3_url = f"s3://{archive_bucket}/{file_name}"

                # Save archive metadata to DynamoDB
                archive_table.put_item(
                    Item={
                        'TicketID': ticket_id,
                        'DateArchived': datetime.datetime.utcnow().isoformat(),
                        'S3URL': s3_url
                    }
                )

                # Log before deletion
                logger.info(f'Deleting ticket from SupportTickets: {ticket_id}')

                # Delete the original ticket from DynamoDB
                response = tickets_table.delete_item(
                    Key={
                        'TicketID': ticket_id
                    }
                )

                # Log the response from the delete operation
                logger.info(f'Delete response: {response}')

    return {'status': 'success'}
Enter fullscreen mode Exit fullscreen mode

Test All Components

Test createticket lambda function

-Create test event

Image description

Test the GetTicket Lambda Function

  • Create a test event to validate the code functionality. Image description Image description ###Test archiveticket lambda

Image description

test api from postman

Image description

Image description

Image description

Image description

Image description

Conclusion

In conclusion, the Secure Customer Support System leveraging AWS services and Slack provides a robust framework for managing customer inquiries and enhancing communication. By integrating API Gateway, Lambda functions, DynamoDB, SNS, and S3, we have created a scalable and efficient solution that ensures real-time responses and secure handling of customer data. The system's architecture allows for easy ticket creation, retrieval, and closure while facilitating seamless interactions with customers via Slack. This project not only streamlines support operations but also highlights the potential of cloud technologies in delivering high-quality customer service. As businesses increasingly seek to enhance their customer support capabilities, adopting such innovative solutions will be crucial in meeting customer expectations and driving satisfaction.

Top comments (0)