diff --git a/images/builders/aws.json b/images/builders/aws.json index 53f5a0bb..2a735c3a 100644 --- a/images/builders/aws.json +++ b/images/builders/aws.json @@ -1,32 +1,38 @@ { - "builders": [ + "builders": [ + { + "access_key": "{{ user `aws_access_key` }}", + "ami_name": "{{ user `snapshot_name` }}", + "instance_type": "{{ user `default_size` }}", + "region": "{{ user `region` }}", + "vpc_id": "{{ user `vpc_id` }}", + "security_group_id": "{{user `security_group_id`}}", + "subnet_id": "{{ user `subnet_id` }}", + "secret_key": "{{ user `aws_secret_access_key` }}", + "run_tags": { + "{{user `tag_key`}}": "{{user `tag_value`}}" + }, + "launch_block_device_mappings": [ { - "access_key": "{{ user `aws_access_key` }}", - "ami_name": "{{ user `snapshot_name` }}", - "instance_type": "{{ user `default_size` }}", - "region": "{{ user `region` }}", - "secret_key": "{{ user `aws_secret_access_key` }}", - "launch_block_device_mappings": [ - { - "device_name": "/dev/sda1", - "volume_type": "gp2", - "volume_size": 20, + "device_name": "/dev/sda1", + "volume_type": "gp2", + "volume_size": 20, "encrypted": true, - "delete_on_termination": true - } - ], - "source_ami_filter": { - "filters": { - "virtualization-type": "hvm", - "name": "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*", - "root-device-type": "ebs" - }, - "owners": ["099720109477"], - "most_recent": true - }, - "ssh_username": "ubuntu", - "temporary_key_pair_type": "ed25519", - "type": "amazon-ebs" + "delete_on_termination": true } - ] + ], + "source_ami_filter": { + "filters": { + "virtualization-type": "hvm", + "name": "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*", + "root-device-type": "ebs" + }, + "owners": ["099720109477"], + "most_recent": true + }, + "ssh_username": "ubuntu", + "temporary_key_pair_type": "ed25519", + "type": "amazon-ebs" + } + ] } diff --git a/interact/account-helpers/aws.sh b/interact/account-helpers/aws.sh index 0dd05200..ea0957d7 100755 --- a/interact/account-helpers/aws.sh +++ b/interact/account-helpers/aws.sh @@ -15,21 +15,21 @@ email="" BASEOS="$(uname)" case $BASEOS in 'Linux') - BASEOS='Linux' - ;; + BASEOS='Linux' + ;; 'FreeBSD') - BASEOS='FreeBSD' - alias ls='ls -G' - ;; + BASEOS='FreeBSD' + alias ls='ls -G' + ;; 'WindowsNT') - BASEOS='Windows' - ;; + BASEOS='Windows' + ;; 'Darwin') - BASEOS='Mac' - ;; + BASEOS='Mac' + ;; 'SunOS') - BASEOS='Solaris' - ;; + BASEOS='Solaris' + ;; 'AIX') ;; *) ;; esac @@ -58,78 +58,203 @@ else install_aws_cli fi -function awssetup(){ - -echo -e -n "${Green}Please enter your AWS Access Key ID (required): \n>> ${Color_Off}" -read ACCESS_KEY -while [[ "$ACCESS_KEY" == "" ]]; do - echo -e "${BRed}Please provide a AWS Access KEY ID, your entry contained no input.${Color_Off}" - echo -e -n "${Green}Please enter your token (required): \n>> ${Color_Off}" - read ACCESS_KEY -done - -echo -e -n "${Green}Please enter your AWS Secret Access Key (required): \n>> ${Color_Off}" -read SECRET_KEY -while [[ "$SECRET_KEY" == "" ]]; do - echo -e "${BRed}Please provide a AWS Secret Access Key, your entry contained no input.${Color_Off}" - echo -e -n "${Green}Please enter your token (required): \n>> ${Color_Off}" - read SECRET_KEY -done - -aws configure set aws_access_key_id "$ACCESS_KEY" -aws configure set aws_secret_access_key "$SECRET_KEY" - -default_region="us-west-2" -echo -e -n "${Green}Please enter your default region: (Default '$default_region', press enter) \n>> ${Color_Off}" -read region - if [[ "$region" == "" ]]; then - echo -e "${Blue}Selected default option '$default_region'${Color_Off}" - region="$default_region" - fi - echo -e -n "${Green}Please enter your default size: (Default 't2.medium', press enter) \n>> ${Color_Off}" - read size - if [[ "$size" == "" ]]; then - echo -e "${Blue}Selected default option 't2.medium'${Color_Off}" - size="t2.medium" -fi +function awssetup() { + # Look where is the instance axiom is being installed on + if curl -s http://169.254.169.254/latest/meta-data/instance-id &>/dev/null; then + onCloud=true + # Means that the instance is on AWS and skip the Access Key + # /!\ The instance needs IAM Policies on ec2 to perform installation + : + else + # Doesn't run on AWS and need Access Key + echo -e -n "${Green}Please enter your AWS Access Key ID (required): \n>> ${Color_Off}" + read ACCESS_KEY + while [[ "$ACCESS_KEY" == "" ]]; do + echo -e "${BRed}Please provide a AWS Access KEY ID, your entry contained no input.${Color_Off}" + echo -e -n "${Green}Please enter your token (required): \n>> ${Color_Off}" + read ACCESS_KEY + done + + echo -e -n "${Green}Please enter your AWS Secret Access Key (required): \n>> ${Color_Off}" + read SECRET_KEY + while [[ "$SECRET_KEY" == "" ]]; do + echo -e "${BRed}Please provide a AWS Secret Access Key, your entry contained no input.${Color_Off}" + echo -e -n "${Green}Please enter your token (required): \n>> ${Color_Off}" + read SECRET_KEY + done -aws configure set default.region "$region" + aws configure set aws_access_key_id "$ACCESS_KEY" + aws configure set aws_secret_access_key "$SECRET_KEY" + fi -echo -e "${BGreen}Creating an Axiom Security Group: ${Color_Off}" -aws ec2 delete-security-group --group-name axiom > /dev/null 2>&1 -sc="$(aws ec2 create-security-group --group-name axiom --description "Axiom SG")" -group_id="$(echo "$sc" | jq -r '.GroupId')" -echo -e "${BGreen}Created Security Group: $group_id ${Color_Off}" + default_region="us-west-2" + echo -e -n "${Green}Please enter your default region: (Default '$default_region', press enter) \n>> ${Color_Off}" + read region + if [[ "$region" == "" ]]; then + echo -e "${Blue}Selected default option '$default_region'${Color_Off}" + region="$default_region" + fi + echo -e -n "${Green}Please enter your default size: (Default 't2.medium', press enter) \n>> ${Color_Off}" + read size + if [[ "$size" == "" ]]; then + echo -e "${Blue}Selected default option 't2.medium'${Color_Off}" + size="t2.medium" + fi + # VPC Selection + while true; do + echo -e -n "${Green}Here are the differents VPCs available : \n${Color_Off}" + #Get all the VPC on the account in the region selected and display them + aws ec2 describe-vpcs --query "Vpcs[*].[Tags[?Key=='Name'].Value]" --region $region --output text | awk -F'\t' '{if (NR==1) print "Number \t VPC"} {print NR-1 "\t" $1}' + echo -e -n "${Green}Please enter the vpc number or id you want to use: (Default vpc, press enter) \n>> ${Color_Off}" + read vpc + if [[ $vpc == *"vpc"* ]]; then + vpc_id=$vpc + else + vpc_id=$(aws ec2 describe-vpcs --filters --query "Vpcs[$vpc].VpcId" --region $region --output text) + fi + # If default VPC choosed, retrieve it + if [[ "$vpc" == "" ]]; then + vpc_id=$(aws ec2 describe-vpcs --filters "Name=is-default,Values=true" --region $region --query "Vpcs[0].VpcId" --output text) + echo -e "${Blue}Selected default option 'default vpc'${Color_Off}" + if [[ "$vpc_id" == "None" ]]; then + echo "${BRed}No default vpc available, please choose a vpc.${Color_Off}" + else + is_default=true + break + fi + fi + break + done + # Subnet Selection + while true; do + echo -e -n "${Green}This vpc has those subnets : \n${Color_Off}" + if [[ "$is_default" ]]; then + aws ec2 describe-subnets --filters "Name=vpc-id, Values=$vpc_id" --region $region --query "Subnets[*].[AvailabilityZone]" --output text | awk -F'\t' '{if (NR==1) print "Number \t Availability Zone"} {print NR-1 "\t" $1}' + else + aws ec2 describe-subnets --filters "Name=vpc-id, Values=$vpc_id" --region $region --query "Subnets[*].[Tags[?Key=='Name'].Value]" --output text | awk -F'\t' '{if (NR==1) print "Number \t Subnet"} {print NR-1 "\t" $1}' + fi + echo -e -n "${Green}Please choose the subnet you want to use: (number required) \n>> ${Color_Off}" + read subnet + subnet_id=$(aws ec2 describe-subnets --filters "Name=vpc-id, Values=$vpc_id" --region $region --query "Subnets[$subnet].SubnetId" --output text) + if [[ "$subnet_id" != "None" && $subnet =~ ^[0-9]+$ ]]; then + break + else + echo -e "${BRed}Please provide a subnet, your entry didn't contain a valid input.${Color_Off}" + fi + done + # Tags Selection + while true; do + echo -e -n "${Green}Do you need to add a tag to the resources created ? (y/n) \n>> ${Color_Off}" + read ans + if [[ "$ans" == "n" || "$ans" == "no" || "$ans" == "" ]]; then + echo -e "${Blue}No tags needed \n${Color_Off}" + ami_tags="" + security_group_tags="" + break + elif [[ "$ans" == "y" || "$ans" == "yes" ]]; then + echo -e -n "${Green}Please enter the key string \n>> ${Color_Off}" + read tkey + echo -e -n "${Green}Please enter the value string \n>> ${Color_Off}" + read tvalue + security_group_tags="Key=${tkey},Value=${tvalue}" + break + else + echo -e "${BRed}Please provide a correct answer, your entry didn't contain a valid input. \n${Color_Off}" + fi + done + # Security group source filtering Selection + ip_regex='^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$' + while true; do + echo -e -n "${Green}Choose the source for the inbound rules (default 0.0.0.0/0). Enter None if not needed. \n>> ${Color_Off}" + read security_source + # Validate input + if [[ $security_source =~ $ip_regex ]]; then + IFS='/' read -r ip prefix <<<"$ip_cidr" + IFS='.' read -r -a octets <<<"$ip" + valid_ip=true + for octet in "${octets[@]}"; do + if ((octet < 0 || octet > 255)); then + echo -e "${BRed}Invalid IP address: Octet $octet is out of range \n${Color_Off}" + valid_ip=false + break + fi + done + if ((prefix < 0 || prefix > 32)); then + echo -e "${BRed}Invalid CIDR prefix: $prefix is out of range \n${Color_Off}" + valid_ip=false + fi + if $valid_ip; then + break + fi + # Accept all IPs if nothing entered + elif [[ "$security_source" == "" ]]; then + security_source="0.0.0.0/0" + echo -e "${Blue}Selected default option '0.0.0.0/0'${Color_Off}" + break + # None case + elif [[ "$security_source" == "None" ]]; then + echo -e "${Blue}Selected None option${Color_Off}" + break + else + echo -e "${BRed}Please provide a correct answer, your entry didn't contain a valid input. Expected format: x.x.x.x/x \n${Color_Off}" + fi + done + aws configure set default.region "$region" -######################################################################################################## we should add this to whitelist your IP - TODO -group_rules="$(aws ec2 authorize-security-group-ingress --group-id "$group_id" --protocol tcp --port 2266 --cidr 0.0.0.0/0)" -group_owner_id="$(echo "$group_rules" | jq -r '.SecurityGroupRules[].GroupOwnerId')" -sec_group_id="$(echo "$group_rules" | jq -r '.SecurityGroupRules[].SecurityGroupRuleId')" + echo -e "${BGreen}Creating an Axiom Security Group: ${Color_Off}" -data="$(echo "{\"aws_access_key\":\"$ACCESS_KEY\",\"aws_secret_access_key\":\"$SECRET_KEY\",\"group_owner_id\":\"$group_owner_id\",\"security_group_id\":\"$sec_group_id\",\"region\":\"$region\",\"provider\":\"aws\",\"default_size\":\"$size\"}")" + # Looking if axiom security group already exist + existing_sec_id="$(aws ec2 describe-security-groups --filters Name=vpc-id,Values=$vpc_id Name=group-name,Values=axiom \ + --query 'SecurityGroups[0].GroupId' --output text)" + aws ec2 delete-security-group --group-id $existing_sec_id >/dev/null 2>&1 + if [[ "$security_group_tags" != "" ]]; then + sc="$(aws ec2 create-security-group --group-name axiom --vpc-id $vpc_id --description "Axiom SG" --tag-specifications "ResourceType=security-group,Tags=[{${security_group_tags}}]")" + else + sc="$(aws ec2 create-security-group --group-name axiom --vpc-id $vpc_id --description "Axiom SG")" + fi + group_id="$(echo "$sc" | jq -r '.GroupId')" + echo -e "${BGreen}Created Security Group: $group_id ${Color_Off}" -echo -e "${BGreen}Profile settings below: ${Color_Off}" -echo $data | jq -echo -e "${BWhite}Press enter if you want to save these to a new profile, type 'r' if you wish to start again.${Color_Off}" -read ans + # Create the ssh rule + if [[ "$security_source" != "None" ]]; then + group_rules="$(aws ec2 authorize-security-group-ingress --group-id "$group_id" --protocol tcp --port 2266 --cidr $security_source)" + fi + + # Add the Public IP address of the axiom instance + if [[ "$onCloud" == true ]]; then + TOKEN="$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")" >/dev/null 2>&1 + publicIP="$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null)" + aws ec2 authorize-security-group-ingress --group-id "$group_id" --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 0, "ToPort": 65535, "IpRanges": [{"CidrIp": "'"$publicIP"/32'"}]},{"IpProtocol": "udp", "FromPort": 0, "ToPort": 65535, "IpRanges": [{"CidrIp": "'"$publicIP"/32'"}]},{"IpProtocol": "icmp", "FromPort": -1, "ToPort": -1, "IpRanges": [{"CidrIp": "'"$publicIP"/32'"}]}]' >/dev/null 2>&1 + fi + group_owner_id="$(echo "$group_rules" | jq -r '.SecurityGroupRules[].GroupOwnerId')" >/dev/null 2>&1 + + if [[ "$tkey" == "None" ]]; then + data="$(echo "{\"aws_access_key\":\"$ACCESS_KEY\",\"aws_secret_access_key\":\"$SECRET_KEY\",\"group_owner_id\":\"$group_owner_id\",\"security_group_id\":\"$group_id\",\"region\":\"$region\",\"vpc_id\":\"$vpc_id\",\"subnet_id\":\"$subnet_id\",\"provider\":\"aws\",\"default_size\":\"$size\"}")" + else + data="$(echo "{\"aws_access_key\":\"$ACCESS_KEY\",\"aws_secret_access_key\":\"$SECRET_KEY\",\"group_owner_id\":\"$group_owner_id\",\"security_group_id\":\"$group_id\",\"tag_key\":\"$tkey\",\"tag_value\":\"$tvalue\",\"region\":\"$region\",\"vpc_id\":\"$vpc_id\",\"subnet_id\":\"$subnet_id\",\"provider\":\"aws\",\"default_size\":\"$size\"}")" + fi + echo -e "${BGreen}Profile settings below: ${Color_Off}" + echo $data | jq + echo -e "${BWhite}Press enter if you want to save these to a new profile, type 'r' if you wish to start again.${Color_Off}" + read ans if [[ "$ans" == "r" ]]; then $0 exit -fi + fi -echo -e -n "${BWhite}Please enter your profile name (e.g 'personal', must be all lowercase/no specials)\n>> ${Color_Off}" -read title + echo -e -n "${BWhite}Please enter your profile name (e.g 'personal', must be all lowercase/no specials)\n>> ${Color_Off}" + read title -if [[ "$title" == "" ]]; then + if [[ "$title" == "" ]]; then title="personal" echo -e "${Blue}Named profile 'personal'${Color_Off}" -fi + fi echo $data | jq > "$AXIOM_PATH/accounts/$title.json" -echo -e "${BGreen}Saved profile '$title' successfully!${Color_Off}" -$AXIOM_PATH/interact/axiom-account $title + echo -e "${BGreen}Saved profile '$title' successfully!${Color_Off}" + $AXIOM_PATH/interact/axiom-account $title } diff --git a/providers/aws-functions.sh b/providers/aws-functions.sh index ccdba72d..a2432db1 100644 --- a/providers/aws-functions.sh +++ b/providers/aws-functions.sh @@ -332,17 +332,24 @@ create_instance() { size_slug="$3" region="$4" boot_script="$5" - sshkey="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.sshkey')" - #sshkey_fingerprint="$(ssh-keygen -l -E md5 -f ~/.ssh/$sshkey.pub | awk '{print $2}' | cut -d : -f 2-)" - #keyid=$(doctl compute ssh-key import $sshkey \ - # --public-key-file ~/.ssh/$sshkey.pub \ - # --format ID \ - # --no-header 2>/dev/null) || - #keyid=$(doctl compute ssh-key list | grep "$sshkey_fingerprint" | awk '{ print $1 }') - - aws ec2 run-instances --image-id "$image_id" --count 1 --instance-type "$size" --region "$region" --security-groups axiom --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=$name}]" 2>&1 >> /dev/null - - sleep 260 + sshkey="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.sshkey')" + #sshkey_fingerprint="$(ssh-keygen -l -E md5 -f ~/.ssh/$sshkey.pub | awk '{print $2}' | cut -d : -f 2-)" + #keyid=$(doctl compute ssh-key import $sshkey \ + # --public-key-file ~/.ssh/$sshkey.pub \ + # --format ID \ + # --no-header 2>/dev/null) || + #keyid=$(doctl compute ssh-key list | grep "$sshkey_fingerprint" | awk '{ print $1 }') + subnet_id="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.subnet_id')" + security_group_id="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.security_group_id')" + security_group_tags="Key=$(cat "$AXIOM_PATH/axiom.json" | jq -r '.tag_key'),Value=$(cat "$AXIOM_PATH/axiom.json" | jq -r '.tag_value')" + if [[ "$security_group_tags" != "" ]]; then + tags="[{Key=Name,Value=$name},{${security_group_tags}}]" + else + tags="[{Key=Name,Value=$name}]" + fi + aws ec2 run-instances --image-id "$image_id" --count 1 --instance-type "$size" --region "$region" --subnet-id "$subnet_id" --associate-public-ip-address --security-group-id "$security_group_id" --tag-specifications "ResourceType=instance,Tags=${tags}" 2>&1 >>/dev/null + + sleep 260 } # Function used for splitting $src across $instances and rename the split files.