Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gordonbondon/585e558990c7ce9d30627a57b7a377d5 to your computer and use it in GitHub Desktop.
Save gordonbondon/585e558990c7ce9d30627a57b7a377d5 to your computer and use it in GitHub Desktop.
Run Argo-CD with GitHub App private key authentication

Currently argo-cd does not natively support authenticating with GitHub via GitHub App private keys.

This steps will allow you to achieve this, with AWS SSM as seret storage for a private key:

  1. Configure argo-cm repo credentials to point password to private key location, and username to app id location:
repository.credentials: |
  - url: https://github.com/<yourorgnamehere>
    passwordSecret:
      name: argocd-secret
      key: gitHubAppPrivateKeySSMPath # this key contains ssm path to github private key in AWS SSM
    usernameSecret:
      name: argocd-secret
      key: gitHubAppIdSSMPath # this key contains ssm path to app id in AWS SSM
  1. Create a custom image from argoproj/argocd using provided Dockerfile, that will replace git-ask-pass.sh with custom implementation from here. Use as this new image as repo server image.
  2. Now every time repo server tries to clone a repo, it will call the new git-ask-pass.sh script set via GIT_ASKPASS, which will use the private key to grub temporary (10 minutes) jwt token to access them.
FROM argoproj/argocd
COPY git-ask-pass.sh /usr/local/bin/git-ask-pass.sh
USER root
WORKDIR /build
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ruby \
build-essential && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
gem install --no-user-install --no-document bundler
COPY Gemfile /build/
RUN bundle config --delete frozen && \
bundle config set system 'true' && \
bundle install -j4 --retry 3
USER 999
WORKDIR /home/argocd
source 'https://rubygems.org'
gem 'aws-sdk-ssm', '= 1.83.0'
gem 'octokit', '= 4.18.0'
gem 'jwt', '= 2.2.1'
#!/usr/bin/env ruby
require 'aws-sdk-ssm'
require 'jwt'
require 'octokit'
require 'openssl'
# overriding original https://github.com/argoproj/argo-cd/blob/master/hack/git-ask-pass.sh script to get credentials from GitHub app
# original:
# case "$1" in
# Username*) echo "${GIT_USERNAME}" ;;
# Password*) echo "${GIT_PASSWORD}" ;;
# esac
if File.fnmatch("Username*", ARGV[0])
puts "x-access-token"
end
if File.fnmatch("Password*", ARGV[0])
# TODO: unhardocode this
org = "<yourorgnamehere>"
key_ssm = ENV['GIT_PASSWORD']
id_ssm = ENV['GIT_USERNAME']
# TODO: unhardcode this
ssm = Aws::SSM::Client.new(region: "us-east-1")
key = ssm.get_parameter(name: key_ssm, with_decryption: true).parameter.value
id = ssm.get_parameter(name: id_ssm, with_decryption: true).parameter.value
private_key = OpenSSL::PKey::RSA.new(key)
payload = {
iat: Time.now.to_i,
exp: (Time.now + 10*60).to_i,
iss: id
}
jwt = JWT.encode(payload, private_key, 'RS256')
github = Octokit::Client.new(bearer_token: jwt)
preview_header = Octokit::Preview::PREVIEW_TYPES[:integrations]
installations = github.find_installations(accept: preview_header)
raise "GitHub app does not have access to #{org}" unless installations.any? {|i| i['account']['login'] == org }
installation = installations.find { |i| i['account']['login'] == org }
# TODO: get token only for required repos, not all available
token = github.create_installation_access_token(installation['id'], accept: preview_header)
puts token['token']
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment