2i2c-org / binderhub-service

https://2i2c.org/binderhub-service/
BSD 3-Clause "New" or "Revised" License
8 stars 3 forks source link

Add chart config to mount and consume a GCP service account's credentials #123

Closed consideRatio closed 4 months ago

consideRatio commented 4 months ago

mybinder.org has its federated binderhubs log event data to a single google logging destination, and does so via this extraConfig.

For credentials to get setup for that:

  1. the mybinder chart provides config to accept a GCP service account key via eventsArchiver.serviceAccountKey
  2. the mybinder chart renders a k8s Secret template
  3. the mybinder deployment config binderhub.extraVolumes and binderhub.extraVolumeMounts is used to mount the k8s Secret created by the mybinder chart on the binderhub deployment's pod
  4. the mybinder deployment config binderhub.extraEnv.GOOGLE_APPLICATION_CREDENTIALS is used to make the credentials detected by the google-cloud-logging library

I think it makes sense of binderhub-service embraces this complexity by accepting a extraCredentials.googleServiceAccountKey configuration, and if received, adds a key/value (Secret's and ConfigMap's keys become filenames when mounted, and the values becomes the file content) to the existing k8s Secret template. That k8s Secret is already declared as a volume and mounted to /etc/binderhub/mounted-secret/, so what remains is to just conditionally declares a GOOGLE_APPLICATION_CREDENTIALS environment variable to reference the file with credentials.

Practically this is the plan

  1. Add extraCredentials.googleServiceAccountKey config (values.yaml entry, values.schema.yaml entry, tools/templates/lint-and-validate-values.yaml entry)
  2. Conditionally render its value in an existing k8s Secret under a new key
  3. Conditionally declare an environment variable GOOGLE_APPLICATION_CREDENTIALS to point to the mounted file
Development tips ## Development tips To test and develop changes to template files, you can make use of commands below - the `tools/` folders commands are available in z2jh / binderhub as well, so this practice can be useful to know about for contributions to those projects as well. ```bash # generates a .json version of the values.schema.yaml which is respected by the helm CLI # (the YAML version is just to make work with the schema file, which must be .json, easier) tools/generate-json-schema.py # this script validates the chart's default values against the schema but also the # example config values in tools/templates/lint-and-validate-values.yaml tools/validate-against-schema.py # test render the chart and inspect how a specific template was rendered helm template binderhub-service --show-only templates/deployment.yaml # test render the chart again, but focusing on whats rendered after # `env:` string in the deployment resource, updating every second. # This is useful when modifying the template file to verify changes quickly watch -n1 'helm template binderhub-service --show-only templates/deployment.yaml | grep -A20 "env:"' ```
consideRatio commented 4 months ago

I now see this as something that could be done in three separate ways:

  1. extraVolume + extraVolumeMounts + extraEnv
    • Requires #122
    • Benefits from #131
  2. extraFiles + extraEnv
    • Requires #130
    • Benefit from #131
  3. Dedicated credential functionality, like extraCredentials.googleServiceAccountKey config

I forgot to consider option 2 when refining this work, hmmm... I disliked the complexity of 1 for the user which then also needs to create a k8s Secret themselves and went thinking about 3, but with 2 we can still avoid the need for users to create a k8s Secret and allow for any kind of credentials to be easily injected.

Comparing option 2 and 3 from a usage perspective:

# how one would use option 2
binderhub-service:
  extraFiles:
    gcp-sa-key.json:
      mountPath: /mnt/gcp-sa-key.json
      stringData: |
        <...>
  extraEnv:
    - name: GOOGLE_APPLICATION_CREDENTIALS
      value: /mnt/gcp-sa-key.json

# how one would use option 3
binderhub-service:
  extraCredentials:
    googleServiceAccountKey: |
      <...>

Dang it, because this chart doesn't have extraEnv support a dictionary (yet?), use of extraEnv is a bit troublesome because lists will replace each other when configured in multiple locations...

consideRatio commented 4 months ago

I hesitated on the way to get this done, and spent time refining #130 and #131, I'll go with adding the config extraCredentials.googleServiceAccountKey.