Search code examples
amazon-web-servicesaws-cliaws-security-group

How to temporarily open and close a port to a certain IP on an AWS security group?


I want to use aws cli tool to temporarily open a port to a certain IP address before a backup process starts and close it after it's finished.

I know how to do this through the console, but I couldn't find how to do this programmatically.

Does anyone know what commands I could run to do that?

I was thinking to write a shell script to do that and launch it before the backup, so I found a Circle CI Orb that does exactly the same. However, when I try to launch it using a shell script I get errors. I'm not so good with the shell commands, so maybe somebody could tell me what I could fix below?

The permissions for AWS are set correctly, so I guess I just need to tweak something in the script below.

# Get the current IP of the AWS instance the script is launched from

LATEST_IP=$(wget -qO- http://checkip.amazonaws.com)

IP="${IP-$LATEST_IP}"

if [[ "${IP}" == "" ]]; then
    echo "Could not find your public IP"
    exit 1
fi

# Get the security group ID

GROUPID=$(aws ec2 describe-security-groups --query 'SecurityGroups[].[Tags[?Key==`<< parameters.tag-key >>`] | [0].Value, GroupId]' --output table | grep << parameters.tag-value >> | awk '{print $4}') [[ -n "${GROUPID}" ]] || (echo "Could not determine Security Group ID" && exit 0);
                                            
# Adding Rule SSH to Your Security Group

echo Allowing << parameters.description >> to access port $PORT from IP
$IP to the security group $GROUPID

aws ec2 authorize-security-group-ingress --group-id $GROUPID --ip-permissions '[{"IpProtocol": "tcp", "FromPort": '<< parameters.port >>', "ToPort": '<< parameters.port >>', "IpRanges": [{"CidrIp": "'$LATEST_IP/<< parameters.mask >>'", "Description": "'<< parameters.description >>'"}]}]' 

# Closing the port
echo "Removing << parameters.description >> access from IP $IP to the security group $GROUPID"


# Delete IP rules matching port

aws ec2 revoke-security-group-ingress --group-id $GROUPID --ip-permissions '[{"IpProtocol": "tcp", "FromPort": '<< parameters.port >>', "ToPort": '<< parameters.port >>', "IpRanges": [{"CidrIp":"'$LATEST_IP/<< parameters.mask >>'", "Description": "'<< parameters.description >>'"}]}]'


Solution

  • I modified the script so that it works. But I don't see much use for it in its current form. It just adds a rule to a SG, and then it removes it immediately after.

    I replaced GROUPID=$(aws ec2 des ... with just a value of SG ID to use.

    #!/bin/bash 
    # Get the current IP of the AWS instance the script is launched from
    
    set -ex
    
    LATEST_IP=$(wget -qO- http://checkip.amazonaws.com)
    
    IP="${IP-$LATEST_IP}"
    
    if [[ "${IP}" == "" ]]; then
        echo "Could not find your public IP"
        exit 1
    fi
    
    echo ${IP}
    
    # Get the security group ID
    
    GROUPID="sg-0483809ca6b8e91d0" # change to your own SG
    PORT_FROM=80
    PORT_TO=80
    MASK_IP="32"
    DESCRIPTION="Some-description"
    AWS_PROFILE="default" # AWS credentials profile to use
    
    # Adding Rule SSH to Your Security Group
    
    echo Allowing ${GROUPID} to access port $PORT from IP ${IP} to the security group $GROUPID
    
    aws ec2 authorize-security-group-ingress \
        --group-id $GROUPID \
        --ip-permissions '[{"IpProtocol": "tcp", "FromPort": '${PORT_FROM}', "ToPort": '${PORT_TO}', "IpRanges": [{"CidrIp": "'$LATEST_IP/${MASK_IP}'", "Description": "'${DESCRIPTION}'"}]}]' \
        --profile ${AWS_PROFILE} 
    
    # Closing the port
    echo "Removing ${DESCRIPTION} access from IP $IP to the security group $GROUPID"
    
    
    # Delete IP rules matching port
    
    aws ec2 revoke-security-group-ingress \
        --group-id $GROUPID \
        --ip-permissions '[{"IpProtocol": "tcp", "FromPort": '${PORT_FROM}', "ToPort": '${PORT_TO}', "IpRanges": [{"CidrIp":"'$LATEST_IP/${MASK_IP}'", "Description": "'${DESCRIPTION}'"}]}]' \
        --profile ${AWS_PROFILE}
    

    Example output:

    ++ wget -qO- http://checkip.amazonaws.com
    + LATEST_IP=<real-ip-value>
    + IP=<real-ip-value>
    + [[ <real-ip-value> == '' ]]
    + echo <real-ip-value>
    <real-ip-value>
    + GROUPID=sg-0483809ca6b8e91d0
    + PORT_FROM=80
    + PORT_TO=80
    + MASK_IP=32
    + DESCRIPTION=Some-description
    + AWS_PROFILE=la
    + echo Allowing sg-0483809ca6b8e91d0 to access port from IP <real-ip-value> to the security group sg-0483809ca6b8e91d0
    Allowing sg-0483809ca6b8e91d0 to access port from IP <real-ip-value> to the security group sg-0483809ca6b8e91d0
    + aws ec2 authorize-security-group-ingress --group-id sg-0483809ca6b8e91d0 --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "IpRanges": [{"CidrIp": "<real-ip-value>/32", "Description": "Some-description"}]}]' --profile la
    + echo 'Removing Some-description access from IP <real-ip-value> to the security group sg-0483809ca6b8e91d0'
    Removing Some-description access from IP <real-ip-value> to the security group sg-0483809ca6b8e91d0
    + aws ec2 revoke-security-group-ingress --group-id sg-0483809ca6b8e91d0 --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "IpRanges": [{"CidrIp":"<real-ip-value>/32", "Description": "Some-description"}]}]' --profile la