Last active
December 1, 2022 01:09
-
-
Save jdillon222/ca38a3d1b07a84c685fbc4a9dd3210e5 to your computer and use it in GitHub Desktop.
DSL Lambda creation for Netsuite CSV downloads.
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 | |
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 | |
<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