Cloudflared --login and Ansible

All, I’ve been using Argo Tunnel (cloudflared) for quite a while now in production. I’m attempting to migrate our deployments to Ansible, but have run into one difficulty. There are some fragments on galaxy.ansible.com for installing cloudflared for the purpose of DoH. This is really handy, but doesn’t require --login. :frowning:

Does anyone have an Ansible role they could share for installing cloudflared and doing the --login portion? I’d much prefer the daemon download the certs itself rather than developers pushing files around.

Obviously, I’m pretty new to Ansible, but this seems to be a pretty difficult task as it’s whole purpose is automated install.

[FEAT REQ]: if --login could accept username and password on the CLI, then I could use a variable that’s properly secured and that would also solve the problem.

I haven’t used Ansible but asked one of our devs with the Cloudflare API key and Origin CA key, the certificate can be generated like this… 10 minutes of trying to format a script in this editor later… uh… here’s a link:

Not sure if it helps or not, but there ya go. :slight_smile:

1 Like

Awesome!! Thanks so much.

Here it is in case the G-Drive link fades:

#!/bin/bash

## example parameters, adjust as needed
ORIGIN_CA_KEY="${CLOUDFLARE_ORIGIN_CA_KEY}"
CF_API_KEY="${CLOUDFLARE_AUTH_KEY}"
CF_EMAIL="${CLOUDFLARE_AUTH_EMAIL}"
TUNNEL_ZONE_ID="${CLOUDFLARE_ZONE_ID}"
TUNNEL_HOSTNAMES=""
case $STAGE in
  development)
    TUNNEL_HOSTNAMES='["db-dev.exmaple.com"]'
    ;;
  production)
    TUNNEL_HOSTNAMES='["db.exmaple.com"]'
    ;;
  *)
    exit 1
    ;;
esac

## now for the actual script:
set -e

## tmp dir
tmpbase=/tmp/${0##*/}
find ${tmpbase}* -type f -exec shred -uvxz {} ';' || true
rm -rf ${tmpbase}*
TMPDIR="`mktemp -d ${tmpbase}-XXXXXX`"

curl -s https://api.cloudflare.com/client/v4/user/service_keys/origintunnel \
  -H "x-auth-key: $CF_API_KEY" \
  -H "x-auth-email: $CF_EMAIL" \
  | jq -r .result.service_key \
  > $TMPDIR/tunnel_service_key.txt

# generate private key
openssl ecparam -name prime256v1 -out $TMPDIR/tunnel_private_key_params.txt
openssl req -batch -new \
        -newkey ec:$TMPDIR/tunnel_private_key_params.txt \
        -nodes -out ${TMPDIR}/csr.txt \
        -keyout ${TMPDIR}/tunnel_private_key.txt \
        -subj "/C=US/CN=CloudFlare"

# make cert.pem, containing
# 1. Private key (in PKCS #8 format)
openssl pkcs8 -topk8 \
        -in ${TMPDIR}/tunnel_private_key.txt \
        -nocrypt -out ${TMPDIR}/cert.pem

# 2. public key from originCA
curl -s -XPOST https://api.cloudflare.com/client/v4/certificates \
  -H "Content-Type: application/json" \
  -H "X-Auth-User-Service-Key: $ORIGIN_CA_KEY" \
  -d "$(jq -n --arg csr "$(cat ${TMPDIR}/csr.txt)" --argjson hostnames "$TUNNEL_HOSTNAMES" '{hostnames:$hostnames,requested_validity:5475,request_type:"origin-ecc",csr:$csr}')" \
  | jq -r .result.certificate \
  >> ${TMPDIR}/cert.pem

# 3. Argo Tunnel token
echo "-----BEGIN ARGO TUNNEL TOKEN-----" >> cert.pem
echo -n "$(echo $TUNNEL_ZONE_ID; cat ${TMPDIR}/tunnel_service_key.txt)" | \
        base64 | fold -w 64 >> cert.pem
echo "-----END ARGO TUNNEL TOKEN-----" >> cert.pem

if [ "x$DEBUG" == "x" ]; then
  find ${tmpbase}* -type f -exec shred -uvxz {} ';' || true
fi

Thanks again for the quick response, this is exactly what I needed

2 Likes

I’ve created an ansible role which bundles this script for automatic deployment: