Skip to content

Instantly share code, notes, and snippets.

@amontalban
Last active September 7, 2020 04:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save amontalban/cb5744f8fe9e5ba966fece68dd2b16cb to your computer and use it in GitHub Desktop.
Save amontalban/cb5744f8fe9e5ba966fece68dd2b16cb to your computer and use it in GitHub Desktop.
Attach an ENI (Elastic Network Interface) to an instance
#!/usr/bin/env bash
# This script assigns Elastic Network Interface (ENI) passed as argument to current instance.
# The goal of this script is to attach an ENI to a single instance running in an ASG for example.
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/root/bin
PROG_NAME=$(basename $0)
AWSCLI=$(which aws)
JQ=$(which jq)
CURL=$(which curl)
TR=$(which tr)
DHCLIENT=$(which dhclient)
IFCONFIG=$(which ifconfig)
GREP=$(which grep)
CUT=$(which cut)
AWK=$(which awk)
SED=$(which sed)
NIC="eth1"
ENI_ID=$1
usage() {
cat<<EOF
NAME
${PROG_NAME} -- Assign an Elastic Network Interface to this instance
SYNOPSIS
${PROG_NAME} eni-id
EXIT STATUS
The ${PROG_NAME} utility exits 0 on success, and > 0 if an error occurs.
EOF
exit 0
}
parse_cmdline() {
if [ $# -eq 0 ]; then
usage
else
while [ $# -gt 0 ]; do
case "$1" in
-*)
usage
;;
*)
break
;;
esac
shift
done
fi
}
get_eni_info () {
local ENI_ID=$1
${AWSCLI} ec2 describe-network-interfaces --filters Name=network-interface-id,Values=${ENI_ID}
}
attach_eni () {
local ENI_ID=$1
local INSTANCE_ID=$2
${AWSCLI} ec2 attach-network-interface --network-interface-id ${ENI_ID} --instance-id ${INSTANCE_ID} --device-index 1
}
dettach_eni () {
local ENI_ATTACHMENT_ID=$1
${AWSCLI} ec2 detach-network-interface --attachment-id ${ENI_ATTACHMENT_ID} --force
}
main() {
ENI_INFO=$(get_eni_info ${ENI_ID})
ENI_IP=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .PrivateIpAddresses[] .PrivateIpAddress' | ${SED} 's/"//g')
ENI_STATUS=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Status' | ${TR} '[A-Z]' '[a-z]' | ${SED} 's/"//g')
INSTANCE_ID=$(${CURL} -s http://169.254.169.254/latest/meta-data/instance-id )
echo "Configuring ENI ${ENI_ID}"
if [ "${ENI_STATUS}" == "available" ]; then
echo "ENI ${ENI_ID} is available, attaching it to ${INSTANCE_ID}"
while [ "${ENI_STATUS}" == "available" ]; do
# Attach ENI to current instance
attach_eni ${ENI_ID} ${INSTANCE_ID}
ENI_INFO=$(get_eni_info ${ENI_ID})
ENI_STATUS=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Status' | ${TR} '[A-Z]' '[a-z]' | ${SED} 's/"//g')
sleep 1
done
echo "ENI ${ENI_ID} attached to ${INSTANCE_ID}"
echo "Configuring ${NIC} with IP ${ENI_IP}"
# Configure network interface
${IFCONFIG} ${NIC} up
${DHCLIENT} ${NIC}
else
ENI_INSTANCE_ID=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Attachment .InstanceId' | ${SED} 's/"//g')
if [ "${INSTANCE_ID}" == "${ENI_INSTANCE_ID}" ]; then
# Check if the IP is configured properly
NIC_IP=$(${IFCONFIG} ${NIC} | ${GREP} 'inet addr:' | ${CUT} -d: -f2 | ${AWK} '{ print $1}')
if ! [ "${NIC_IP}" == "${ENI_IP}" ]; then
echo "Configuring NIC ${NIC}..."
# Configure network interface
${IFCONFIG} ${NIC} up
${DHCLIENT} ${NIC}
fi
else
echo "ENI ${ENI_ID} is attached to ${ENI_INSTANCE_ID}, dettaching..."
while [ "${ENI_STATUS}" == "in-use" ]; do
# Dettach ENI
ENI_ATTACHMENT_ID=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Attachment .AttachmentId' | ${SED} 's/"//g')
dettach_eni ${ENI_ATTACHMENT_ID}
ENI_INFO=$(get_eni_info ${ENI_ID})
ENI_STATUS=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Status' | ${TR} '[A-Z]' '[a-z]' | ${SED} 's/"//g')
sleep 1
done
echo "ENI ${ENI_ID} is available, attaching it to ${INSTANCE_ID}"
while [ "${ENI_STATUS}" == "available" ]; do
# Attach ENI to current instance
attach_eni ${ENI_ID} ${INSTANCE_ID}
ENI_INFO=$(get_eni_info ${ENI_ID})
ENI_STATUS=$(echo ${ENI_INFO} | ${JQ} '.NetworkInterfaces[] .Status' | ${TR} '[A-Z]' '[a-z]' | ${SED} 's/"//g')
sleep 1
done
echo "ENI ${ENI_ID} attached to ${INSTANCE_ID}"
echo "Configuring ${NIC} with IP ${ENI_IP}"
# Configure network interface
${IFCONFIG} ${NIC} up
${DHCLIENT} ${NIC}
fi
fi
}
parse_cmdline $@
main
exit 0
@amontalban
Copy link
Author

Required IAM policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1346888659253",
            "Action": [
                "ec2:AttachNetworkInterface",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceStatus",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DetachNetworkInterface",
                "ec2:DescribeNetworkInterfaceAttribute"
            ],
            "Effect": "Allow",
            "Resource": [
                "*"
            ]
        }
    ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment