Skip to content

Instantly share code, notes, and snippets.

@GauntletWizard
Last active September 4, 2023 02:44
Show Gist options
  • Save GauntletWizard/9ee6e55b5e23c9a8cadd0d1a34cacbd2 to your computer and use it in GitHub Desktop.
Save GauntletWizard/9ee6e55b5e23c9a8cadd0d1a34cacbd2 to your computer and use it in GitHub Desktop.
aws tricks

Must Dos:

  • Use terraform, or other declarative infrastructure
  • Use Organizations for billing. Set up an Org account, with an Infra account for build artifacts/login, and development, staging, and prod accounts with appropriate permissions.
  • Developers should all have admin permissions in dev, and only necessary permissions in staging and prod. Staging should be exactly like prod except that customers aren't using it. Dev should be as close as possible, with any changes being backed out and repeated in staging before they make it to staging.

Useful tools:

Stretch Goals:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
# see https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-FS-1-2-2019-08
alb.ingress.kubernetes.io/target-type: ip
# Fix for some ALB defaults that make sense for instances but not k8s pods: Pods are already ready when added to group, and need to shut down fast.
alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=10,slow_start.duration_seconds=30
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
# This is the configuration of a HTTP redirect
# Why this rule is not created in the HTTPS listener, but only HTTP, I don't know. Magic in the ALB ingress controller, I guess.
alb.ingress.kubernetes.io/actions.rule-http: |
{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "Path":"/#{path}", "Query": "#{query}", "StatusCode": "HTTP_301"}}
spec:
rules:
# This is the rule that connects with actions.rule-http
- http:
paths:
- path: /*
backend:
serviceName: rule-http
servicePort: use-annotation
# Credentials as env vars:
eval $(grep -A 2 "\[oghp\]" ~/.aws/credentials |tail -n +2 | awk '{ print "export " toupper($1) "=" $3 }')
# Credentials CSV to AWS Creds file.
CSVFILE="/Users/ted/Downloads/credentials.csv"
PROFILE=hp
CREDSFILE=~/.aws/credentials
csv() {
set +o pipefail
local FIELD="${1}"
tail -n 1 "${CSVFILE}" |cut -d "," -f "${FIELD}"
}
echo "[${PROFILE}]" >> $CREDSFILE
echo "aws_access_key_id =" $(csv 3) >> $CREDSFILE
echo "aws_secret_access_key =" $(csv 4) >> $CREDSFILE
# Generate an aws access-key secret:
IAMUSER=jenkins
KEY="$(aws iam create-access-key --user-name "${IAMUSER}")"
KEYID="$(echo "${KEY}" |jq -r .AccessKey.AccessKeyId)"
KEYSECRET="$(echo "${KEY}" |jq -r .AccessKey.SecretAccessKey)"
kubectl create secret generic "aws-${IAMUSER}" --from-literal "AWS_ACCESS_KEY_ID=${KEYID}" --from-literal "AWS_SECRET_ACCESS_KEY=${KEYSECRET}"
# Reads a MFA token, stores in MFATOKEN
mfa-token() {
if [[ -n "${ZSH_VERSION}" ]] ; then
read -s "MFATOKEN?MFA Token? "
else
read -sp "MFA Token? " MFATOKEN
echo
fi
}
# AWS MFA Function
mfa-aws() {
local MFAPROFILE="${MFAPROFILE:-login}"
local TEMPPROFILE="${TEMPPROFILE:-default}"
echo "Authenticating profile ${TEMPPROFILE}..."
mfa-token
local mfatoken="${MFATOKEN}"
# Name of MFA device is just our username, munged.
local MFADEVICE
MFADEVICE=$(aws sts get-caller-identity --profile "${MFAPROFILE}" |jq -r .Arn | sed s/user/mfa/)
# Use the token to get a short-lived session token.
local shorttoken
if ! shorttoken=$(aws sts get-session-token --profile "${MFAPROFILE}" --serial-number "${MFADEVICE}" --token "${mfatoken}")
then
echo "MFA Login Failed. Try again with a new token"
return 1
fi
aws configure set "profile.${TEMPPROFILE}.aws_access_key_id" "$(echo "$shorttoken" | jq -r .Credentials.AccessKeyId)"
aws configure set "profile.${TEMPPROFILE}.aws_secret_access_key" "$(echo "$shorttoken" | jq -r .Credentials.SecretAccessKey)"
aws configure set "profile.${TEMPPROFILE}.aws_session_token" "$(echo "$shorttoken" | jq -r .Credentials.SessionToken)"
echo "Session expires at $(echo "$shorttoken" |jq -r .Credentials.Expiration)"
local id
id="$(aws sts get-caller-identity --profile "${TEMPPROFILE}")"
echo $id
# Set up AWS ECR Docker Login. This hardcodes the region, which is good enough for now.
# This command is for AWSCLI v2, which is the default for brew on osx. On linux machines you may be lagging; on windows please update.
# aws ecr get-login-password --profile "${TEMPPROFILE}" --region us-east-1 | docker login --username AWS --password-stdin "$(echo $id | jq -r .Account).dkr.ecr.us-east-1.amazonaws.com"
}
# Use with an AWS Config like:
# [profile dev]
# role_arn = arn:aws:iam::768009573690:role/swch_admin
# source_profile = swch
# https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html
# The above does not work if an MFA token is required to assume roles, however, and "chained" session tokens are limited to a short maximum.
mfa-aws-profile() {
local roleprofile="$1"
local MFAPROFILE
if ! MFAPROFILE=${MFAPROFILE:-$(aws configure get "profile.${roleprofile}.source_profile")}
then
echo "Either ${roleprofile}.source_profile must be set (in ~/.aws/config) or MFAPROFILE must be set"
return
fi
local role_arn
role_arn="$(aws configure get "profile.${roleprofile}.role_arn")"
local mfatoken
read -sp "MFA Token? " mfatoken
# On ZSH, replace the above with:
# read -s "?MFA Token? " mfatoken
echo
# Name of MFA device is just our username, munged. Using "Default" identity.
local mfadevice
mfadevice=$(aws sts get-caller-identity --profile "${MFAPROFILE}" |jq -r .Arn | sed s/user/mfa/)
# Use the token to get a session token.
local shorttoken
shorttoken=$(aws sts assume-role --profile "${MFAPROFILE}" --role-arn="${role_arn}" --role-session-name="${USER}@${HOSTNAME}" --serial-number "${mfadevice}" --token "${mfatoken}" --duration 21600)
aws configure set profile.${roleprofile}.aws_access_key_id $(echo $shorttoken | jq -r .Credentials.AccessKeyId)
aws configure set profile.${roleprofile}.aws_secret_access_key $(echo $shorttoken | jq -r .Credentials.SecretAccessKey)
aws configure set profile.${roleprofile}.aws_session_token $(echo $shorttoken | jq -r .Credentials.SessionToken)
aws sts get-caller-identity --profile ${roleprofile}
}

Reformat key so that it can be used by openssl/libressl:

ssh-keygen -p -m PEM

get the key data. Note that real base64 must be used, because JQ's @base64d only handles utf-8 data.

aws ec2 get-password-data --instance-id i-08b9b66e9d6c6f18a --region us-west-2 |jq -r '.PasswordData' | base64 -D | openssl rsautl -decrypt -inkey ~/.ssh/id_rsa | pbcopy

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