Firebase Auth authorized domains
I’m using Firebase Authentication in a project to authenticate users of various OAuth2 identity systems. Firebase Authentication requires a set of Authorized Domains.
The (web) app that interacts with Firebase Authentication is deployed to Cloud Run. The Authorized Domains list must include the app’s Cloud Run service URL.
Cloud Run service URLs vary by Project (ID). They are a combination of the service name, a hash (?) of the Project (ID) and .a.run.app
.
Using `gcloud ... --format` with arbitrary returned data
If you use jq
, you’ll know that, its documentation uses examples that you can try locally or using the excellent jqplay
:
printf "[1,2,3]" | jq .[1:]
[
2,
3
]
And here
If you use Google Cloud Platform (GCP) CLI, gcloud
, this powerful tool includes JSON output formatting of results (--format=json
) and YAML (--format=yaml
) etc. and includes a set of so-called projections that you can use to format the returned data.
There is a comparable slice
projection that you may use with gcloud
and the documentation even includes an example:
Golang Structured Logging w/ Google Cloud Logging (2)
UPDATE There’s an issue with my naive implementation of
RenderValuesHook
as described in this post. I summarized the problem in this issue where I’ve outlined (hopefully) a more robust solution.
Recently, I described how to configure Golang logging so that user-defined key-values applied to the logs are parsed when ingested by Google Cloud Logging.
Here’s an example of what we’re trying to achieve. This is an example Cloud Logging log entry that incorporates user-defined labels (see dog:freddie
and foo:bar
) and a readily-querable jsonPayload
:
Sigstore
I’ve been on a digression (gcp-oidc-token-proxy
) this week. Yesterday I began exploring Podman and wrote briefly about running gcp-oidc-token-proxy
on my localhost using it.
This morning while walking with my dog, I listened to Google’s Dan Lorenc explain Sigstore (blog](https://blog.sigstore.dev/)) on The Kubelist Podcast1
The plan today is to try to sign the gcp-oidc-token-proxy
container images in GitHub Container Registry.
NOTE I decided against trying the hardware key approach. I have a Google Titan key and only Yubikeys are well-tested by
go-piv
Podman
I’ve read about Podman and been intrigued by it but never taken the time to install it and play around. This morning, walking with my dog, I listened to the almost-always-interesting Kubernetes Podcast and two of the principals behind Podman were on the show to discuss it.
I decided to install it and use it in this week’s project.
Here’s a working Podman deployment for gcp-oidc-token-proxy
ACCOUNT="..."
ENDPOINT="..."
# Can't match container name i.e. prometheus
POD="foo"
SECRET="${ACCOUNT}"
podman secret create ${SECRET} ${PWD}/${ACCOUNT}.json
# Pod publishes pod-port:container-port
podman pod create \
--name=${POD} \
--publish=9091:9090 \
--publish=7776:7777
PROMETHEUS=$(mktemp)
# Important
chmod go+r ${PROMETHEUS}
sed \
--expression="s|some-service-xxxxxxxxxx-xx.a.run.app|${ENDPOINT}|g" \
${PWD}/prometheus.yml > ${PROMETHEUS}
# Prometheus
# Requires --tty
# Can't include --publish but exposes 9090
podman run \
--detach --rm --tty \
--pod=${POD} \
--name=prometheus \
--volume=${PROMETHEUS}:/etc/prometheus/prometheus.yml \
docker.io/prom/prometheus:v2.30.2 \
--config.file=/etc/prometheus/prometheus.yml \
--web.enable-lifecycle
# GCP OIDC Token Proxy
# Can't include --publish but exposes 7777
podman run \
--detach --rm \
--pod=${POD} \
--name=gcp-oidc-token-proxy \
--secret=${SECRET} \
--env=GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/${SECRET} \
ghcr.io/dazwilkin/gcp-oidc-token-proxy:ec8fa9d9ab1b7fa47448ff32e34daa0c3d211a8d \
--port=7777
The prometheus
container includes a volume
mount.
Scraping metrics exposed by Google Cloud Run services that require authentication
I’ve written a solution (gcp-oidc-token-proxy
) that can be used in conjunction with Prometheus OAuth2 to authenticate requests so that Prometheus can scrape metrics exposed by e.g. Cloud Run services that require authentication. The solution resulted from my question on Stack overflow.
Problem #1: Endpoint requires authentication
Given a Cloud Run service URL for which:
ENDPOINT="my-server-blahblah-wl.a.run.app"
# Returns 200 when authentication w/ an ID token
TOKEN="$(gcloud auth print-identity-token)"
curl \
--silent \
--request GET \
--header "Authorization: Bearer ${TOKEN}" \
--write-out "%{response_code}" \
--output /dev/null \
https://${ENDPOINT}/metrics
# Returns 403 otherwise
curl \
--silent \
--request GET \
--write-out "%{response_code}" \
--output /dev/null \
https://${ENDPOINT}/metrics
Problem #2: Prometheus OAuth2 configuration is constrained
Golang Structured Logging w/ Google Cloud Logging
I’ve multiple components in an app and these are deployed across multiple Google Cloud Platform (GCP) services: Kubernetes Engine, Cloud Functions, Cloud Run, etc. Almost everything is written in Golang and I started the project using go-logr
.
logr
is in two parts: a Logger
that you use to write log entries; a LogSink
(adaptor) that consumes log entries and outputs them to a specific log implementation.
Initially, I defaulted to using stdr
which is a LogSink
for Go’s standard logging implementation. Something similar to the module’s example:
GitHub help with dependency management
This is very useful:
I am building an application that comprises multiple repos. I continue to procrastinate on whether using multiple repos vs. a monorepo was a good idea but, an issue that I have (had) is the need to ensure that the repos’ contents are using current|latest modules. GitHub can help.
Most of the application is written in Golang with a smattering of Rust and some JavaScript.
`gcloud beta run services replace`
TL;DR I’m working on a project that includes multiple Cloud Run services. I’ve been putting my
gcloud
head on to deploy these services thinking that it’s curious there’s no way to write the specs as YAML configs. Today, I learned that there is:gcloud beta run services replace
.
What prompted the discovery was some frustration trying to deploy a JSON-valued environment variable to Cloud Run:
local FIREBASE_CONFIG="{
apiKey: ${FIREBASE_API_KEY},
authDomain: ${FIREBASE_AUTH_DOMAIN},
projectId: ${FIREBASE_PROJECT},
storageBucket: ${FIREBASE_STORAGE_BUCKET},
messagingSenderId: ${FIREBASE_MESSAGING_SENDER},
appId: ${FIREBASE_APP}}"
gcloud run deploy ${SRV_NAME} \
--image=${IMAGE} \
--command="/server" \
--args="--endpoint=:${PORT}" \
--set-env-vars=FIREBASE_CONFIG="${FIREBASE_CONFIG}" \
--max-instances=1 \
--memory=256Mi \
--ingress=all \
--platform=managed \
--port=${PORT} \
--allow-unauthenticated \
--region=${REGION} \
--project=${PROJECT}
gcloud
balks at this.
Infrastructure as Code
Problem
I’m building an application that comprises:
- Kubernetes¹
- Kubernetes Operator
- Cloud Firestore
- Cloud Functions
- Cloud Run
- Cloud Endpoints
- Stripe
- Firebase Authentication
¹ - I’m using Google Kubernetes Engine (GKE) but may include other managed Kubernetes offerings (e.g. Digital Ocean, Linode, Oracle). GKE clusters are manageable by
gcloud
but other platforms require other CLI tools. All are accessible from bash but are these supported by e.g. Terraform (see below)?
Many of the components are packaged as container images and, because I’m using GitHub to host the project’s repos (I’ll leave the monorepo discussion for another post), I’ve become inculcated and use GitHub Container Registry (GHCR) as the container repo.