Octelium documentation · Latest
Using Octelium in GitHub Actions
Your User, especially WORKLOAD User used by non-human entities such as GitHub Action workflows, can access HTTP-based Services (e.g. HTTP/gRPC APIs, Kubernetes clusters) through the clientless BeyondCorp mode via OAuth2 client credentials (read more here) and directly issued access tokens used in bearer authentication (read more here). However, in many cases, you might want to access non-HTTP Services, such as databases, from within your GitHub Action workflows. Octelium enables you to connect to your Cluster and access any arbitrary Service from within your workflows via the official octelium/github-action GitHub Action.
By default, the Action authenticates to your Cluster in a "secretless" way using GitHub's own OIDC issued identity token assertions (read more here), which means that no secret at all needs to be stored in your repository. To do so, we first need to create an oidcIdentityToken IdentityProvider as follows:
Now your User can set an identifier for the github-actions IdentityProvider as follows (read more about User identities here):
Your GitHub Action needs to add the permission id-token: write to generate an OIDC identity token. Your workflow should now look as follows:
Note that the audience input has to match the audience field of the github-actions IdentityProvider, and that the Action does not return until the tunnel is actually up, which means that the steps that come after it can immediately access the Cluster Services.
You do not need to identify which IdentityProvider the Action authenticates against, even if your Cluster has more than one, since the Cluster itself infers the IdentityProvider that matches the assertion.
The Action deliberately rejects input combinations that would otherwise silently do nothing. In other words, the audience input cannot be combined with the auth-token input since an authentication token does not use an assertion at all, and it also cannot be combined with an explicit assertion input whose value already carries its own options (e.g. github-actions:audience=https://example.com).
Authentication Tokens
You can also authenticate using an authentication token Credential (read more about issuing authentication tokens here) which is typically stored as a GitHub repository secret. Here is an example:
The authentication token is only passed to the octelium client via an environment variable and it is never passed as a command-line argument. Note, however, that GitHub does not provide repository secrets to workflows that are triggered by a pull_request event from forked repositories, which is one more reason to prefer the secretless assertion-based authentication described above.
Scopes
You can restrict what the Session created by the workflow is actually able to access via the scopes input, which works in a similar spirit to OAuth2 scopes (read more here). Here is an example that limits the workflow to the postgres Service of the db Namespace as well as every Service belonging to the ci Namespace:
Publishing Services
Once connected, your workflow can access any Service assigned to the User by its hostname (read more here). In some cases, however, your tooling can only speak to localhost. For such cases, you can map a Service to a port of the GitHub Action runner via the publish input (read more here). Here is an example:
Your workflow can now access the postgres.db and redis.ns1 Services at localhost:5432 and localhost:6379 respectively.
Serving Services
A GitHub Action runner can also remotely serve Services back to the Cluster via the serve input (read more about remotely serving Services here), which can be useful, for example, to expose a preview environment that is built inside the workflow. Here is an example:
Pinning the Client Version
By default the Action installs the latest octelium client release. You can pin a specific version for reproducible workflows as follows:
The Action downloads the release archive directly from the Octelium GitHub releases, verifies it against the release SHA256SUMS and refuses to install it upon a checksum mismatch.
You can also install the other Octelium binaries, which is useful for workflows that manage the Cluster itself via octeliumctl (read more here), as follows:
Additional Arguments
Most of the commonly used octelium connect flags already have their own dedicated inputs which you should always prefer. For anything else, the extra-args input takes one argument per line in the --flag=value form as follows:
Note that the extra-args input is meant to be a forward-compatibility escape hatch and it is therefore not able to override the options that the Action itself manages. In other words, the --detach, --domain, --auth-token, --assertion and --homedir flags are rejected, since detaching the client would leave behind a tunnel that the Action can no longer manage and the authentication flags would place a Credential in the command-line arguments of the process.
Disconnecting
The connection remains available for the rest of the job. You can explicitly tear it down and log the Session out via the logout command instead of leaving the Session to expire on its own (read more about Sessions here) as follows:
Note that the if: always() condition makes sure that the step still runs even if an earlier step of the job has failed, and that the logout step has to run in the same job as the step that connected to the Cluster. The step stops the client, waits for it to shut down gracefully and then revokes the Session. If the connection itself never comes up, then the Action automatically terminates the client before failing the step, which means that a runner is never left with a tunnel that is no longer managed.
The Action's inputs were reorganized in v2. If you are upgrading from v1, then the args input, whose value used to be split on whitespace, is now the newline-separated extra-args input, and most of its common use cases now have dedicated inputs such as serve, publish and scopes. The wait input, which simply slept for a number of seconds, is now the timeout input which sets how long the Action waits for the tunnel to actually come up. You can read about every supported input of the Action here.