Skip to main content

AWS (EC2) Security Groups

Knocknoc can easily connect to AWS using common utilities and IAM credentials, and update the allowed IP dynamically. The agent ships with a script built in for this already, which requires credentials placed where the agent can read them. 

Backend for AWS Security Group

image.png

In the example above, there is a backend called "AWSSecurityGroup." You are required to select an agent, being the host where the script is installed, equipped with necessary credentials. Finally, there is the command required to initiate the backend. Please note that the provided sample script may need to be customised to suit your needs.

ACL for AWS Security Group

Then the admin creates an ACL:

image.png

The ACL Name as the security group is an argument passed to the script, and then updated with the IP of the Knocknoc user when they login.

Here is copy of the script. As you can see, the credentials file needs to be written out, and it can of course be tailored to your needs.

#!/bin/bash

# Check for AWS CLI
if ! command -v aws &> /dev/null; then
    echo "Error: AWS CLI is not installed."
    exit 1
fi

# Check arguments
if [ "$#" -lt 3 ]; then
    echo "Usage: $0 <ACTION> <IP_ADDRESS> <SECURITY_GROUP_ID>"
    exit 1
fi

IP_ADDRESS=$3
ACTION=$1
SECURITY_GROUP_ID=$2

# standard aws credential file
# please ensure your IAM cred has least privileges

CREDENTIAL_FILE=/opt/knocknoc-agent/etc/aws-sg.creds

# Load credentials if provided
if [ ! -z "$CREDENTIAL_FILE" ]; then
    if [ ! -f "$CREDENTIAL_FILE" ]; then
        echo "Error: Credential file does not exist."
        exit 1
    fi
    export AWS_ACCESS_KEY_ID=$(grep 'aws_access_key_id' $CREDENTIAL_FILE | cut -d '=' -f 2 | tr -d '[:space:]')
    export AWS_SECRET_ACCESS_KEY=$(grep 'aws_secret_access_key' $CREDENTIAL_FILE | cut -d '=' -f 2 | tr -d '[:space:]')
    export AWS_DEFAULT_REGION=$(grep 'region' $CREDENTIAL_FILE | cut -d '=' -f 2 | tr -d '[:space:]')
fi

case $ACTION in
    "add")
        # Check if the IP is already allowed
        CURRENT_IPS=$(aws ec2 describe-security-groups --group-ids $SECURITY_GROUP_ID --query 'SecurityGroups[0].IpPermissions[?ToPort==`22` && FromPort==`22`].IpRanges[].CidrIp' --output text)
        if echo "$CURRENT_IPS" | grep -q "$IP_ADDRESS"; then
            echo "IP $IP_ADDRESS is already allowed. Skipping addition." 
        else
            aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr $IP_ADDRESS/32 
        fi
        ;;
    "del")
        aws ec2 revoke-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr $IP_ADDRESS/32 
        ;;
    "flush")
        # Get current IPs and remove them one by one
        CURRENT_IPS=$(aws ec2 describe-security-groups --group-ids $SECURITY_GROUP_ID --query 'SecurityGroups[0].IpPermissions[?ToPort==`22` && FromPort==`22`].IpRanges[].CidrIp' --output text)
        for ip in $CURRENT_IPS; do
            aws ec2 revoke-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr $ip 
        done
        ;;
    *)
        echo "Invalid action. Valid actions are 'add', 'del', and 'flush'." 
        exit 1
        ;;
esac

An example IAM policy to create a user for an EC2 security group might be as follows:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SGPermissions",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeSecurityGroups",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:RevokeSecurityGroupIngress",
                "ec2:AuthorizeSecurityGroupEgress",
                "ec2:RevokeSecurityGroupEgress"
            ],
            "Resource": "arn:aws:ec2:ap-southeast-2:691650234881:security-group/sg-0eea61b7e43fcd9a5"
        }
    ]
}

There are of course many ways you could take these examples and adapt them to your needs. You could also create real problems if you aren't careful with the syntax of scripts and IAM policies etc, so please be mindful of the principals of least privilege to get this job done.