Skip to content

Instantly share code, notes, and snippets.

@jdillon222
Last active December 1, 2022 01:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdillon222/ca38a3d1b07a84c685fbc4a9dd3210e5 to your computer and use it in GitHub Desktop.
Save jdillon222/ca38a3d1b07a84c685fbc4a9dd3210e5 to your computer and use it in GitHub Desktop.
DSL Lambda creation for Netsuite CSV downloads.
#!/bin/bash
helper(){
: '<helper>
- Prints argument input options per arg call
or upon incorrect argument input
<helper>'
cat <<-EOF
netsuiteLambda.sh:
-----------
REQUIREMENTS:
--------------------------------------------------------------------------
./netsuiteLambda.sh --inventoryBaseUrl <inventory_server>
--s3_bucket <s3-bucket-name>
--username <user_name>
--password <pass_word>
--subfolder <s3-internal-folder>
--subnets <subnet1,subnet2,subnet3..> (no space btwn ,)
--vpc <vpc-name>
--email <email_group_address>
--------------------------------------------------------------------------
OPTIONAL:
--------------------------------------------------------------------------
./netsuiteLambda.sh --help
--------------------------------------------------------------------------
--help: Shows usage examples, and explanation of arguments
EOF
exit
}
exit_test(){
: '<exit_test>
- Checks exit status of last process ($1)
- If success: echo $2
- If error: echo $3
- If $4 == `exit`: exit program upon error
<exit_test>'
if [[ $1 == 0 ]]; then
echo "$2"
else
echo "$3"
[[ ${4} == "EXIT" ]] && exit
fi
}
get_args(){
: '<get_args>
- Gathers argument inputs and creates necessary variables
Necessary Arguments:
-------------------
- inventory_url
- s3_bucket
- password
- username
- vpc
- subnets
- email
<get_args>'
inventoryBaseUrl=''
outputBucketName=''
password=''
subfolder=''
username=''
vpc=''
subnets=''
email=''
epoch=$(date +"%s")
topicArn='' #will be added to by sub-routine
s3_arn='' #will be added to by sub-routine
counter=0
for arg in "$@";do
arrval="${@:$((counter+2)):1}"
case "$arg" in
--inventory_url)
inventoryBaseUrl+="${arrval}";;
--s3_bucket)
outputBucketName+="${arrval}";;
--password)
password+="${arrval}";;
--username)
username+="${arrval}";;
--subfolder)
subfolder+="${arrval}";;
--vpc)
vpc+="${arrval}";;
--subnets)
subnets+="${arrval}";;
--email)
email+="${arrval}";;
--help)
helper;;
esac
(( counter++ ))
done
#All args != `--help` are required
for i in "${inventoryBaseUrl}" "${outputBucketName}" "${password}" "${username}" "${subfolder}" "${vpc}" "${subnets}" "${email}";do
[[ "${i}" == "" ]] && echo "helper"
done
#populate IAM role name to be used
role_name="inventory_netsuite_lambda_s3_role"
#utilizing policy name
policy_name="inventory_netsuite_lambda_s3_policy"
: 'COMMENT
echo "inventoryBaseUrl = ${inventoryBaseUrl}"
echo "outputBucketName = ${outputBucketName}"
echo "password = ${password}"
echo "username = ${username}"
echo "subfolder = ${subfolder}"
echo "vpc = ${vpc}"
echo "subnets = ${subnets}"
echo "email = ${email}"
#COMMENT'
}
get_args "$@"
create_SNS(){
: '<create_SNS>
- Function will create SNS topic `inventory_netsuite_lambda_notification`
- Function will add email group dictated by `email` argument
<create_SNS>'
topic=$(aws sns create-topic --name inventory_netsuite_lambda_notification)
topicArn+=$(echo $topic | sed 's/{.*: "\(.*\)".*/\1/')
aws sns subscribe --topic-arn ${topicArn} \
--protocol email \
--notification-endpoint ${email}
#exit test the SNS creation, do not terminate program if SNS not created successfully
exit_test $? "SNS notification created successfully" "!!!SNS notification creation failure. Please create manually."
}
create_SNS
create_S3(){
: '<create_S3>
- Creates an S3 bucket to house Netsuite CSV dumps (if one does not exist)
- Bucket serves as a trigger for the Lambda function
<create_S3>'
mk_bucket(){
aws s3api create-bucket --bucket ${outputBucketName} \
--region us-west-2 \
--create-bucket-configuration LocationConstraint=us-west-2
exit_test $? "Successfully created S3 bucket" "!!!Failed to create bucket" "EXIT"
}
#test to see whether or not the bucket already exists
aws s3 ls s3://${outputBucketName} > /dev/null 2>&1
if [[ $? != 0 ]]; then
aws s3 mb s3://${outputBucketName}
exit_test $? "Successfully created S3 bucket" "!!!Failed to create bucket" "EXIT"
#create test folder structure within bucket
touch testFile
aws s3 mv testFile s3://${outputBucketName}/${subfolder}/testFile
else
echo "Using S3 bucket ${outputBucketName}"
fi
#arn of the s3 bucket, to be used as Lambda target later
s3_arn+="arn:aws:s3:::${outputBucketName}"
echo ${s3_arn}
}
create_S3
#Permissions data for IAM role:
policy=$(cat <<- EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "inventoryLambda0",
"Effect": "Allow",
"Action": [
"s3:PutBucketAcl",
"s3:ListBucket"
],
"Resource": "${s3_arn}"
},
{
"Sid": "inventoryLambda1",
"Effect": "Allow",
"Action": "s3:PutObjectAcl",
"Resource": "${s3_arn}/*"
},
{
"Sid": "inventoryLambda2",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:HeadBucket"
],
"Resource": "*"
},
{
"Sid": "inventoryLambda3",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"${s3_arn}",
"${s3_arn}/*"
]
},
{
"Sid": "inventoryLambda4",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "${topicArn}"
},
{
"Sid": "inventoryLambda5",
"Effect": "Allow",
"Action": [
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface"
],
"Resource": "*"
},
{
"Sid": "inventoryLambda6",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
)
#Policy file for creating the role:
role=$(cat <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
)
create_IAM(){
: '<create_IAM>
- Function will create IAM role `inventory_netsuite_lambda_s3_role`,
utilizing a created policy `inventory_netsuite_lambda_s3_policy`
(if the IAM role and policy don`t already exist)
<create_IAM>'
echo "${policy}" > snapPolicy.json
echo "${role}" > snapRole.json
for file in snapPolicy.json snapRole.json; do
chmod a+r ${file}
done
#test to see whether or not role is already created
aws iam get-role --role-name ${role_name} > /dev/null 2>&1
if [[ $? == 0 ]]; then
delim=''
for ((i=0;i<64;i++));do
delim+='#'
done
echo -e "\n${delim} \n IAM role ${role_name} already exists"
echo " Please confirm that role has proper Lambda and S3 permissions"
echo -e " Role will be applied to Lambda function\n${delim}\n"
else
#create role:
aws iam create-role --role-name ${role_name} --assume-role-policy-document file://snapRole.json
exit_test $? "IAM role creation succeeded" "!!!IAM role creation failed; exiting" "EXIT"
#attach new policy to role:
aws iam put-role-policy --role-name ${role_name} --policy-name ${policy_name} --policy-document file://snapPolicy.json
echo "Waiting 30 seconds for new role to be made available within AWS"
for ((i=0;i<31;i++));do
echo $((i-30))
sleep 1
done
exit_test $? "Policy attachment succeeded" "!!!Policy attachment failed; exiting" "EXIT"
fi
rm snapPolicy.json
rm snapRole.json
}
create_IAM
create_SG(){
: '<create_SG>
- Creates a VPC security group, handling traffice on port 53
across TCP and UDP (for CIDR block 10.240.0/16)
<create_SG>'
sg_name='lambda-netsuite-inventory-group'
#test to see whether or not security group exists, will exit w/ status 1 if group exists
sg_data=$(aws ec2 describe-security-groups --filters Name=group-name,Values=${sg_name})
sg_data=$(echo ${sg_data} | sed 's/ //g')
if [[ ${sg_data} == '{"SecurityGroups":[]}' ]]; then
#create the new security group if the json parameter is empty
sg=$(aws ec2 create-security-group --description "Netsuite csv access" --group-name ${sg_name} --vpc-id ${vpc})
exit_test $? "Successfully created Security Group ${sg_name}" "!!!Failed to create Security Group" "EXIT"
sg=$(echo ${sg} | sed 's/ //'g)
sg_id=$(echo ${sg} | sed 's/{.*:"\(.*\)".*/\1/')
#add TCP and UDP parameters (specific to Netsuite requirements) to the SG
aws ec2 authorize-security-group-ingress --group-id ${sg_id} --protocol tcp --port 53 --cidr "10.240.0.0/16"
aws ec2 authorize-security-group-ingress --group-id ${sg_id} --protocol udp --port 53 --cidr "10.240.0.0/16"
#add name tag to security group
aws ec2 create-tags --resources ${sg_id} --tags Key="Name",Value="${sg_name}"
else
#if security group exists,
echo "security group exists"
sg_id=$(echo ${sg_data} | sed -e 's/{.*"GroupId":"\(.*[0-9a-z]*\)",.*/\1/' -e 's/".*//')
fi
}
create_SG
create_lambda(){
: '<create_lambda>
- Creates a Lambda function, targetting the S3 bucket
identified by the `outputBucketName` variable
<create_lambda>'
role_arn=$(aws iam get-role --role-name ${role_name} | grep "Arn" | awk '{print $2}' | sed 's/,//' | sed 's/"//g')
lambda_name="inventory-netsuite-s3-lambda-function"
env_string="Variables={inventoryBaseUrl=${inventoryBaseUrl},outputBucketName=${outputBucketName},"
env_string+="password=${password},topicArn=${topicArn},username=${username}}"
lambda_mk(){
#subproc to create lambda function
aws lambda create-function \
--function-name ${lambda_name} \
--runtime nodejs8.10 \
--role ${role_arn} \
--zip-file fileb://Archive.zip \
--handler index.handler \
--environment ${env_string} \
--timeout 150 \
--memory-size 256 \
--vpc-config SubnetIds=${subnets},SecurityGroupIds=${sg_id}
}
lambda_s3_perm(){
#subproc to add s3 permissions to Lambda function
aws lambda add-permission \
--function-name ${lambda_name} \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn ${s3_arn} \
--statement-id 1
}
#test current existence of Lambda function
aws lambda get-function --function-name ${lambda_name} > /dev/null 2>&1
if [[ $? != 0 ]]; then
lambda_mk
lambda_arn=$(aws lambda get-function --function-name ${lambda_name} | grep "FunctionArn" | awk '{print $2}' | sed 's/,//' | sed 's/"//g')
#Trigger policy for Lambda S3 targetting
s3_trigger=$(cat << EOF
{
"LambdaFunctionConfigurations": [
{
"Id": "lambda-s3-event-configuration",
"LambdaFunctionArn": "${lambda_arn}",
"Events": [ "s3:ObjectCreated:Put" ],
"Filter": {
"Key": {
"FilterRules": [
{
"Name": "suffix",
"Value": ".csv"
},
{
"Name": "prefix",
"Value": "${subfolder}/netsuite"
}
]
}
}
}
]
}
EOF
)
#add S3 bucket as a target to the Lambda function
lambda_s3_perm
echo ${s3_trigger} > s3.json
chmod 755 s3.json
aws s3api put-bucket-notification-configuration --bucket ${outputBucketName} --notification-configuration file://s3.json
rm s3.json
else
echo "${lambda_name} already exists!! Exiting"
fi
}
create_lambda
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment