Last active
May 27, 2024 07:51
-
-
Save jsianes/034a4e15a8be422c6814 to your computer and use it in GitHub Desktop.
Script to assign Public IP from Elastic IP pool for instances hosted in AWS. 'ec2-utils' and AWS CLI packages required. Instance role or access keys need to allow at least next EC2 actions: describe-addresses, associate-address and disassociate-address. Shell script is designed to be integrated with instance start-up
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# chkconfig: 2345 99 10 | |
# description: Set Public IP from ElasticIP pool during instance startup | |
# processname: ipassign | |
# Provides: ipassign | |
# Required-Start: | |
# Required-Stop: | |
# Default-Start: 2 3 4 5 | |
# Default-Stop: | |
# Short-Description: Set Public IP from ElasticIP pool during instance startup | |
# | |
# | |
# Developed by: Javier Sianes - [email protected] | |
# | |
OUTPUT="text" | |
REGION="eu-west-1" | |
IPLOGFILE="/var/log/ipassign.log" | |
export PATH=/usr/share/pear:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin | |
timestamp() { | |
TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%S.000Z"` | |
} | |
usage() { | |
echo "$0 {start|stop|status}" | |
exit 255 | |
} | |
write_log() { | |
timestamp | |
echo "${TIMESTAMP} - ${LOG}" >> ${IPLOGFILE} | |
} | |
valid_ip() { | |
RX='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])' | |
if [[ ${EC2PUBLICIP} =~ ^${RX}\.${RX}\.${RX}\.${RX}$ ]] | |
then | |
VALIDIP=1 | |
else | |
VALIDIP=0 | |
fi | |
} | |
check_ec2metadata() { | |
ec2-metadata >/dev/null 2>&1 | |
if [ $? -eq 0 ] | |
then | |
# Amazon Linux ec2-metadata command found | |
EC2INSTANCE=`ec2-metadata -i | awk '{ print $NF; }'` | |
EC2PUBLICIP=`ec2-metadata -v | awk '{ print $NF; }'` | |
else | |
# Checking ec2metadata command | |
ec2metadata >/dev/null 2>&1 | |
if [ $? -eq 0 ] | |
then | |
# ec2metadata command found | |
EC2INSTANCE=`ec2metadata --instance-id` | |
EC2PUBLICIP=`ec2metadata --public-ipv4` | |
else | |
# No ec2metadata/ec2-metadata command found. Trying to obtain using curl requests directly | |
IP_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null | grep "200 OK" | wc -l` | |
IS_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null | grep "200 OK" | wc -l` | |
(( INFO=${IP_AVAILABLE}+${IS_AVAILABLE} )) | |
if [ ${INFO} -eq 2 ] | |
then | |
EC2INSTANCE=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null` | |
EC2PUBLICIP=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null` | |
else | |
# ec2metadata/ec2-metadata command not found and unable to obtain metadata info using curl | |
LOG="ERROR: Unable to obtain metadata information using ec2metadata/ec2-metadata command or curl requests"; write_log | |
exit 127 | |
fi | |
fi | |
fi | |
} | |
check_awscli() { | |
aws ec2 describe-addresses >/dev/null 2>&1 | |
if [ $? -ne 0 ] | |
then | |
# Incorrect instance role or invalid AWS CLI configuration | |
LOG="ERROR: AWS CLI command not available. Check instance role or AWS CLI installation/configuration"; write_log | |
exit 128 | |
fi | |
} | |
start() { | |
check_ec2metadata | |
# Check Public IP | |
valid_ip | |
if [ ${VALIDIP} -eq 0 ] | |
then | |
# No Public IP available. So, AWS CLI unavailable | |
LOG="ERROR: There is no Public IP address attached to ${EC2INSTANCE} instance. Unable to use AWS CLI."; write_log | |
exit 3 | |
fi | |
# Check if AWS CLI is available | |
check_awscli | |
# Check if instance has a public IP from Elastic pool assigned | |
PUBLICIPASSIGNED=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | wc -l` | |
if [ ${PUBLICIPASSIGNED} -gt 0 ] | |
then | |
# Instance has (at least) one Pulic IP associated from Elastic pool | |
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | head -1 | awk '{ print $NF; }'` | |
LOG="Instance ${EC2INSTANCE} has (at least) one Public IP address from Elastic pool in ${REGION} region (${IP})"; write_log | |
exit 4 | |
else | |
# Get IP address from Elastic pool | |
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep -v 'i-' | head -1 | awk '{ print $NF; }'` | |
if [ "${IP}" = "" ] | |
then | |
# Public IP on Elastic pool unavailable | |
LOG="ERROR: Free Public IP inside Elastic pool in ${REGION} region unavailable"; write_log | |
exit 5 | |
else | |
# Attach Public IP from Elastic pool | |
BOOL=0 | |
aws ec2 associate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${IP} >/dev/null 2>&1 | |
EXITCODE=$? | |
if [ ${EXITCODE} -eq 0 ] | |
then | |
LOG="${IP} Public IP from Elastic pool assigned to ${EC2INSTANCE} instance"; write_log | |
else | |
LOG="ERROR: (${EXITCODE}) Unable to attach ${IP} Public IP from Elastic pool to ${EC2INSTANCE} instance"; write_log | |
BOOL=1 | |
fi | |
if [ ${BOOL} -eq 0 ] | |
then | |
# Detaching default Public IP | |
aws ec2 disassociate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${EC2PUBLICIP} >/dev/null 2>&1 | |
EXITCODE=$? | |
if [ ${EXITCODE} -eq 0 ] || [ ${EXITCODE} -eq 255 ] | |
then | |
LOG="Default public IP ${EC2PUBLICIP} outside Elastic pool detached from ${EC2INSTANCE} instance"; write_log | |
else | |
LOG="ERROR: (${EXITCODE}) Unable to detach default public IP ${EC2PUBLICIP} from ${EC2INSTANCE} instance"; write_log | |
BOOL=2 | |
fi | |
fi | |
exit ${BOOL} | |
fi | |
fi | |
} | |
stop() { | |
exit 6 | |
} | |
status() { | |
check_ec2metadata | |
valid_ip | |
if [ ${VALIDIP} -eq 0 ] | |
then | |
echo "No Public IP address attached to ${EC2INSTANCE} instance." | |
exit 1 | |
fi | |
check_awscli | |
IPPRESENTINPOOL=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep "${EC2INSTANCE}" | grep ${EC2PUBLICIP} | wc -l` | |
if [ ${IPPRESENTINPOOL} -eq 1 ] | |
then | |
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region belongs to ElasticIP pool" | |
exit 0 | |
else | |
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region is a generic public IP NOT present in ElasticIP pool" | |
exit 2 | |
fi | |
} | |
case "$1" in | |
start) | |
start | |
;; | |
stop) | |
stop | |
;; | |
status) | |
status | |
;; | |
*) | |
usage | |
;; | |
esac |
Resolved:
-
Added this below line 118
Get Allocation id from Elastic pool
AID=
aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep -v 'i-' | head -1 | awk '{ print $2; }'
-
Modified line 128 to:
aws ec2 associate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --allocation-id ${AID} >/dev/null 2>&1
Hi,
We tried to run this as launch script while launching the EC2 instance but it didn't work. But it works when we run this on shell and it successfully assigns Elastic IP to the instance.
Thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I'm getting the following error: ERROR: (255) Unable to attach {IP omitted} Public IP from Elastic pool to i-{ID omitted} instance
If I run the following manually:
aws ec2 associate-address --instance-id i-{ID omitted} --public-ip {IP omitted}
I see:
An error occurred (InvalidParameterCombination) when calling the AssociateAddress operation: You must specify an allocation id when mapping an address to a VPC instance.