Skip to content

Instantly share code, notes, and snippets.

@sryabkov
Last active March 15, 2023 15:30
Show Gist options
  • Save sryabkov/39f20f263c5edfa650522c6a2e9484b6 to your computer and use it in GitHub Desktop.
Save sryabkov/39f20f263c5edfa650522c6a2e9484b6 to your computer and use it in GitHub Desktop.
Passing SSH private key to atlantis

Custom Atlantis image

Reasons

Custom image for atlantis was needed:

  • to add missing components
    • terragrunt
    • Google Cloud SDK
    • taking care of the SSH key for the user atlantis uses to clone GitHub repos (the key is NOT embedded into the image)

Environment

  • GCP
  • Atlantis is running in a GKE cluster
  • Atlantis deployed using the stable Atlantis Helm chart
  • The Helm chart is deployed by Terraform code (can be done differently)

Key implementation details

  • The following values are passed to the atlantis Helm chart (through a values file)

    environment:
      GOOGLE_APPLICATION_CREDENTIALS: "/etc/credentials/service-account.json"
      GITHUB_USER_SSH_KEY: "/etc/github-user-ssh-key/service-account.json"
    

    service-account.json is an unfortunate name for the file that contains a private SSH key, but we are "creatively using" the functionality that was originally designed for passing GCP service account credentials to atlantis and service-account.json is expected by atlantis Kubernetes manifests created by the chart.

  • The values bwlow are passed to the atlantis Helm chart as parameters on the command line. In our case, this has been done with Terraform, but it doesn't have to be.

    set {
      # used for mounting credential files (when using google provider).
      name  = "serviceAccountSecrets.credentials"
      value = "${base64encode(file(local.svc_acct_key_file_name))}"
    }
    
    set {
      # used for mounting github user ssh key
      # a bit of a hack because we are hijacking the functionality for
      # handling service account keys
      name = "serviceAccountSecrets.github-user-ssh-key"
      value = "${base64encode(file(local.github_user_ssh_key_file_name))}"
    

    }

  • We are placing a custom /usr/local/bin/docker-entrypoint.sh on the custom Atlantis image. It copies the GitHub SSH key to the atlantis home directory and then calls the original entrypoint.

#!/bin/dumb-init /bin/sh
set -e
# the script is being executed by the root user
ATLANTIS_HOME=/home/atlantis
# GITHUB_USER_SSH_KEY is set through the atlantis helm chart
# In the atlantis-helm-chart-non-secret-values.yaml file, we have
#
# environment:
# GITHUB_USER_SSH_KEY: "/etc/github-user-ssh-key/service-account.json"
#
# The private SSH key is passed to the atlantis helm chart from 70-atlantis.tf,
# the Terraform file that has the "helm_release.atlantis" definition
#
# set {
# name = "serviceAccountSecrets.github-user-ssh-key"
# value = "${base64encode(file(local.github_user_ssh_key_file_name))}"
# }
#
if [ -n "$GITHUB_USER_SSH_KEY" ] \
&& [ -f "$GITHUB_USER_SSH_KEY" ]; then
if [ ! -d "$ATLANTIS_HOME/.ssh" ]; then
mkdir "$ATLANTIS_HOME/.ssh"
fi
if [ ! -f "$ATLANTIS_HOME/.ssh/id_rsa" ]; then
cp "$GITHUB_USER_SSH_KEY" "$ATLANTIS_HOME/.ssh/id_rsa"
chmod 600 "$ATLANTIS_HOME/.ssh/id_rsa"
ssh-keyscan github.com >> "$ATLANTIS_HOME/.ssh/known_hosts"
chown atlantis:atlantis "$ATLANTIS_HOME/.ssh/id_rsa"
chown atlantis:atlantis "$ATLANTIS_HOME/.ssh/known_hosts"
fi
fi
#!/bin/dumb-init /bin/sh
set -e
create_github_user_ssh_key.sh
set -- docker-entrypoint-original.sh "$@"
exec "$@"
FROM runatlantis/atlantis:v0.6.0
ARG TERRAGRUNT_VER=v0.18.2
ARG TERRAGRUNT_DOWNLOAD_SITE="https://github.com/gruntwork-io/terragrunt/releases/download"
ARG TERRAGRUNT_DOWNLOAD_URL="${TERRAGRUNT_DOWNLOAD_SITE}/${TERRAGRUNT_VER}/terragrunt_linux_amd64"
RUN curl -sL "${TERRAGRUNT_DOWNLOAD_URL}" -o /usr/local/bin/terragrunt \
&& chmod +x /usr/local/bin/terragrunt
# https://github.com/GoogleCloudPlatform/cloud-sdk-docker/blob/master/alpine/Dockerfile
ARG CLOUD_SDK_VERSION=239.0.0
ENV CLOUD_SDK_VERSION=$CLOUD_SDK_VERSION
ARG GOOGLE_SDK_DOWNLOAD_FILE="google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz"
ENV PATH /google-cloud-sdk/bin:$PATH
RUN apk --no-cache add \
curl \
python \
py-crcmod \
bash \
libc6-compat \
openssh-client \
git \
gnupg \
&& curl -O "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/${GOOGLE_SDK_DOWNLOAD_FILE}" \
&& tar xzf "${GOOGLE_SDK_DOWNLOAD_FILE}" \
&& rm "${GOOGLE_SDK_DOWNLOAD_FILE}" \
&& ln -s /lib /lib64 \
&& gcloud config set core/disable_usage_reporting true \
&& gcloud config set component_manager/disable_update_check true \
&& gcloud config set metrics/environment github_docker_image \
&& gcloud --version
ADD create_github_user_ssh_key.sh /usr/local/bin/
# rename original entry point
RUN mv /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint-original.sh
# the new docker-entrypoint.sh will do some work and then call the original entry point
ADD docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
@Lerentis
Copy link

Lerentis commented Oct 5, 2022

Thanks for the idea. helped me with another issue i had with extending the base atlantis functionality 😃

the shebang in docker-entrypoint.sh and create_github_user_ssh_key.sh changed in the more recent upstream images to #!/usr/bin/dumb-init /bin/sh (source: upstream) if somebody else stumbles upon this in the future

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