324 lines
9.2 KiB
Bash
324 lines
9.2 KiB
Bash
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
|
|
MIME-Version: 1.0
|
|
|
|
--==BOUNDARY==
|
|
Content-Type: text/x-shellscript; charset="us-ascii"
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Run Order: 1
|
|
# Run Frequency: only once, on first boot
|
|
|
|
# Tasks:
|
|
# - Install Dependencies
|
|
# - Make users and directories
|
|
# - Install download, unzip, and setup vault bin
|
|
|
|
# Note: dollar-sign curly braces are template values from Terraform.
|
|
# Non curly brace ones are normal bash variables...
|
|
|
|
sudo apt update -y && sudo apt install gpg wget -y
|
|
|
|
# Make the user
|
|
useradd --system --shell /sbin/nologin vault
|
|
|
|
# Make the directories
|
|
mkdir -p /opt/vault
|
|
mkdir -p /opt/vault/bin
|
|
mkdir -p /opt/vault/config
|
|
mkdir -p /opt/vault/tls
|
|
|
|
# Give corret permissions
|
|
chmod 755 /opt/vault
|
|
chmod 755 /opt/vault/bin
|
|
|
|
# Change ownership to vault user
|
|
chown -R vault:vault /opt/vault
|
|
|
|
# === Install Vault via apt ===
|
|
# Get the keyring
|
|
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
|
|
|
# Verify the keyring
|
|
gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint
|
|
|
|
# Check the exit status of the last command
|
|
if [ $? -eq 0 ]; then
|
|
# If the exit status is 0 (which means the previous command was successful), add the repo
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
|
|
|
|
# Install the vault
|
|
sudo apt update && sudo apt install vault -y
|
|
else
|
|
# If the exit status is not 0 (which means the previous command failed), print an error message and exit
|
|
echo "Keyring verification failed. Exiting."
|
|
exit 1
|
|
fi
|
|
|
|
# === Install AWS CLI ===
|
|
# Either x86_64 or aarm64
|
|
Architecture=$(uname -m)
|
|
|
|
printf '%s\n' "Installing / Updating AWS-Cli" "-----------------" "$Architecture"
|
|
|
|
echo "downloading..."
|
|
curl "https://awscli.amazonaws.com/awscli-exe-linux-$Architecture.zip" -o "awscliv2.zip"
|
|
sleep 1
|
|
|
|
# create public gpg key
|
|
cat <<EOF > aws-cli-public.gpg
|
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
mQINBF2Cr7UBEADJZHcgusOJl7ENSyumXh85z0TRV0xJorM2B/JL0kHOyigQluUG
|
|
ZMLhENaG0bYatdrKP+3H91lvK050pXwnO/R7fB/FSTouki4ciIx5OuLlnJZIxSzx
|
|
PqGl0mkxImLNbGWoi6Lto0LYxqHN2iQtzlwTVmq9733zd3XfcXrZ3+LblHAgEt5G
|
|
TfNxEKJ8soPLyWmwDH6HWCnjZ/aIQRBTIQ05uVeEoYxSh6wOai7ss/KveoSNBbYz
|
|
gbdzoqI2Y8cgH2nbfgp3DSasaLZEdCSsIsK1u05CinE7k2qZ7KgKAUIcT/cR/grk
|
|
C6VwsnDU0OUCideXcQ8WeHutqvgZH1JgKDbznoIzeQHJD238GEu+eKhRHcz8/jeG
|
|
94zkcgJOz3KbZGYMiTh277Fvj9zzvZsbMBCedV1BTg3TqgvdX4bdkhf5cH+7NtWO
|
|
lrFj6UwAsGukBTAOxC0l/dnSmZhJ7Z1KmEWilro/gOrjtOxqRQutlIqG22TaqoPG
|
|
fYVN+en3Zwbt97kcgZDwqbuykNt64oZWc4XKCa3mprEGC3IbJTBFqglXmZ7l9ywG
|
|
EEUJYOlb2XrSuPWml39beWdKM8kzr1OjnlOm6+lpTRCBfo0wa9F8YZRhHPAkwKkX
|
|
XDeOGpWRj4ohOx0d2GWkyV5xyN14p2tQOCdOODmz80yUTgRpPVQUtOEhXQARAQAB
|
|
tCFBV1MgQ0xJIFRlYW0gPGF3cy1jbGlAYW1hem9uLmNvbT6JAlQEEwEIAD4CGwMF
|
|
CwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQT7Xbd/1cEYuAURraimMQrMRnJHXAUC
|
|
ZMKcEgUJCSEf3QAKCRCmMQrMRnJHXCilD/4vior9J5tB+icri5WbDudS3ak/ve4q
|
|
XS6ZLm5S8l+CBxy5aLQUlyFhuaaEHDC11fG78OduxatzeHENASYVo3mmKNwrCBza
|
|
NJaeaWKLGQT0MKwBSP5aa3dva8P/4oUP9GsQn0uWoXwNDWfrMbNI8gn+jC/3MigW
|
|
vD3fu6zCOWWLITNv2SJoQlwILmb/uGfha68o4iTBOvcftVRuao6DyqF+CrHX/0j0
|
|
klEDQFMY9M4tsYT7X8NWfI8Vmc89nzpvL9fwda44WwpKIw1FBZP8S0sgDx2xDsxv
|
|
L8kM2GtOiH0cHqFO+V7xtTKZyloliDbJKhu80Kc+YC/TmozD8oeGU2rEFXfLegwS
|
|
zT9N+jB38+dqaP9pRDsi45iGqyA8yavVBabpL0IQ9jU6eIV+kmcjIjcun/Uo8SjJ
|
|
0xQAsm41rxPaKV6vJUn10wVNuhSkKk8mzNOlSZwu7Hua6rdcCaGeB8uJ44AP3QzW
|
|
BNnrjtoN6AlN0D2wFmfE/YL/rHPxU1XwPntubYB/t3rXFL7ENQOOQH0KVXgRCley
|
|
sHMglg46c+nQLRzVTshjDjmtzvh9rcV9RKRoPetEggzCoD89veDA9jPR2Kw6RYkS
|
|
XzYm2fEv16/HRNYt7hJzneFqRIjHW5qAgSs/bcaRWpAU/QQzzJPVKCQNr4y0weyg
|
|
B8HCtGjfod0p1A==
|
|
=gdMc
|
|
-----END PGP PUBLIC KEY BLOCK-----
|
|
EOF
|
|
|
|
gpg --import aws-cli-public.gpg
|
|
|
|
curl -o awscliv2.sig https://awscli.amazonaws.com/awscli-exe-linux-$Architecture.zip.sig
|
|
|
|
gpg --verify awscliv2.sig awscliv2.zip
|
|
|
|
# -u for overwrite / update
|
|
unzip -u awscliv2.zip
|
|
|
|
sudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update
|
|
|
|
aws --version
|
|
|
|
# give ownership to the vault user
|
|
chown vault:vault /opt/vault/bin/vault
|
|
|
|
# create a symlink
|
|
ln -s /opt/vault/bin/vault /usr/local/bin/vault
|
|
|
|
# allow vault permissions to use mlock and prevent memory from swapping to disk
|
|
setcap cap_ipc_lock=+ep /opt/vault/bin/vault
|
|
|
|
# cleanup files
|
|
rm awscliv2.zip
|
|
rm aws-cli-public.gpg
|
|
rm awscliv2.sig
|
|
|
|
--==BOUNDARY==
|
|
Content-Type: text/x-shellscript; charset="us-ascii"
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Run Order: 2
|
|
# Run Frequency: only once, on first boot
|
|
|
|
# Tasks:
|
|
# - Fetch needed data
|
|
# - Create Self-Signed Certificate and Key
|
|
|
|
INSTANCE_IP_ADDR=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)
|
|
INSTANCE_DNS_NAME=$(curl http://169.254.169.254/latest/meta-data/local-hostname)
|
|
|
|
# Used for encryption between the load balancer and vault instances.
|
|
# Th other alternatives are either creating an entire, private CA and hoping AWS
|
|
# eventually adds the ability to add trusted CAs to load balancers...
|
|
# ...or paying $400/month base for the ACM private CA.
|
|
openssl req -x509 -sha256 -nodes \
|
|
-newkey rsa:4096 -days 3650 \
|
|
-keyout /opt/vault/tls/vault.key -out /opt/vault/tls/vault.crt \
|
|
-subj "/CN=$INSTANCE_DNS_NAME" \
|
|
-extensions san \
|
|
-config <(cat /etc/pki/tls/openssl.cnf <(echo -e "\n[san]\nsubjectAltName=DNS:$INSTANCE_DNS_NAME,IP:$INSTANCE_IP_ADDR"))
|
|
|
|
chown vault:vault /opt/vault/tls/vault.key
|
|
chown vault:vault /opt/vault/tls/vault.crt
|
|
|
|
chmod 640 /opt/vault/tls/vault.key
|
|
chmod 644 /opt/vault/tls/vault.crt
|
|
|
|
# Trust the certificate
|
|
cp /opt/vault/tls/vault.crt /etc/pki/tls/certs/vault.crt
|
|
|
|
--==BOUNDARY==
|
|
Content-Type: text/x-shellscript; charset="us-ascii"
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Run Order: 3
|
|
# Run Frequency: only once, on first boot
|
|
|
|
# Tasks:
|
|
# - Make the vault config file
|
|
# - Make the systemd service file
|
|
|
|
# The vault config file
|
|
cat > /opt/vault/config/server.hcl <<- EOF
|
|
cluster_name = "${VAULT_CLUSTER_NAME}"
|
|
max_lease_ttl = "192h"
|
|
default_lease_ttl = "192h"
|
|
ui = "true"
|
|
|
|
# Where can the Vault API be reached? At DNS for the load balancer, or the CNAME created.
|
|
# Note: this maps to the environment variable VAULT_API_ADDR not VAULT_ADDR
|
|
api_addr = "https://${VAULT_DNS}"
|
|
|
|
# For forwarding between vault servers. Set to own ip.
|
|
cluster_addr = "https://INSTANCE_IP_ADDR:8201"
|
|
|
|
# Auto unseal the vault
|
|
seal "awskms" {
|
|
region = "${VAULT_CLUSTER_REGION}"
|
|
kms_key_id = "${VAULT_KMS_KEY_ID}"
|
|
}
|
|
|
|
# Listener for loopback
|
|
listener "tcp" {
|
|
address = "127.0.0.1:8199"
|
|
tls_disable = "true"
|
|
}
|
|
|
|
# Listener for private network
|
|
listener "tcp" {
|
|
address = "INSTANCE_IP_ADDR:8200"
|
|
cluster_address = "INSTANCE_IP_ADDR:8201"
|
|
|
|
tls_disable = "false"
|
|
tls_cert_file = "/opt/vault/tls/vault.crt"
|
|
tls_key_file = "/opt/vault/tls/vault.key"
|
|
}
|
|
|
|
storage "dynamodb" {
|
|
ha_enabled = "true"
|
|
region = "${VAULT_CLUSTER_REGION}"
|
|
table = "${VAULT_DYNAMODB_TABLE}"
|
|
}
|
|
EOF
|
|
|
|
chown vault:vault /opt/vault/config/server.hcl
|
|
|
|
# The systemd service file
|
|
cat > /etc/systemd/system/vault.service <<- EOF
|
|
[Unit]
|
|
Description=Vault Server on AWS
|
|
Requires=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=vault
|
|
Group=vault
|
|
ProtectSystem=full
|
|
ProtectHome=read-only
|
|
PrivateTmp=yes
|
|
PrivateDevices=yes
|
|
SecureBits=keep-caps
|
|
AmbientCapabilities=CAP_IPC_LOCK
|
|
Capabilities=CAP_IPC_LOCK+ep
|
|
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
|
|
NoNewPrivileges=yes
|
|
ExecStart=/opt/vault/bin/vault server -config=/opt/vault/config/ -log-level=info
|
|
ExecReload=/bin/kill --signal HUP \$MAINPID
|
|
KillMode=process
|
|
KillSignal=SIGINT
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
TimeoutStopSec=30
|
|
StartLimitInterval=60
|
|
StartLimitBurst=3
|
|
LimitNOFILE=65536
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
--==BOUNDARY==
|
|
Content-Type: text/x-shellscript; charset="us-ascii"
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Run Order: 4
|
|
# Run Frequency: only once, on first boot
|
|
|
|
# Tasks:
|
|
# - Replace values in configuration files with instance metadata
|
|
# - Start vault
|
|
|
|
INSTANCE_IP_ADDR=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)
|
|
sed -i -e "s/INSTANCE_IP_ADDR/$INSTANCE_IP_ADDR/g" /opt/vault/config/server.hcl
|
|
|
|
systemctl daemon-reload
|
|
systemctl enable vault
|
|
systemctl restart vault
|
|
|
|
--==BOUNDARY==
|
|
Content-Type: text/x-shellscript; charset="us-ascii"
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Run Order: 5
|
|
# Run Frequency: only once, on first boot
|
|
|
|
# Tasks:
|
|
# - Initialize Vault
|
|
# - Create credentials file
|
|
# - Encrypt the file via KMS
|
|
# - Send the file to S3
|
|
# - Delete the local file
|
|
# - Erase bash history
|
|
|
|
# Workaround to make sure the vault service is fully initialized.
|
|
sleep 20
|
|
|
|
export VAULT_ADDR="http://127.0.0.1:8199"
|
|
export AWS_DEFAULT_REGION="${VAULT_CLUSTER_REGION}"
|
|
export VAULT_INITIALIZED=$(vault operator init -status) # avoid non-zero exit status
|
|
|
|
function initialize_vault {
|
|
# initialize and pipe to file
|
|
vault operator init > vault_credentials.txt
|
|
|
|
# encrypt it with the KMS key
|
|
aws kms encrypt --key-id ${VAULT_KMS_KEY_ID} --plaintext fileb://vault_credentials.txt --output text --query CiphertextBlob | base64 --decode > vault_creds_encrypted
|
|
|
|
# send the encrypted file to the s3 bucket
|
|
aws s3 cp vault_creds_encrypted s3://${VAULT_S3_BUCKET_NAME}/
|
|
|
|
# cleanup
|
|
rm vault_credentials.txt
|
|
rm vault_creds_encrypted
|
|
history -c
|
|
history -w
|
|
}
|
|
|
|
if [ "$VAULT_INITIALIZED" = "Vault is initialized" ]; then
|
|
echo "Vault is already initialized."
|
|
else
|
|
echo "Initializing vault..."
|
|
initialize_vault
|
|
fi
|
|
|
|
--==BOUNDARY==-- |