|
| 1 | +# Bitbucket - Web Identity Federation |
| 2 | + |
| 3 | +In this guide, you'll learn how to deploy from Bitbucket Pipelines using OpenFaaS's IAM support and Web Identity Federation. |
| 4 | + |
| 5 | +You'll need to create YAML files for an Issuer, a Policy and a Role. These need to be applied through kubectl, Helm or a GitOps tool. |
| 6 | + |
| 7 | +Your build will need to be adapted in order to receive an *id_token* from Bitbucket, which will be exchanged for an OpenFaaS access token. |
| 8 | + |
| 9 | +## Pre-requisites |
| 10 | + |
| 11 | +### OIDC identity provider |
| 12 | + |
| 13 | +You need to retrieve your workspace's OIDC identity provider URL and audience from Bitbucket: |
| 14 | + |
| 15 | +1. Navigate to your repository in Bitbucket Cloud. |
| 16 | +2. Select **Repository settings** on the left navigation sidebar. |
| 17 | +3. Select **OpenID Connect** under **Pipelines** on the left sidebar. |
| 18 | +4. Copy the **Identity provider URL** and **Audience** values. |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +You'll need both values when configuring the `JwtIssuer` resource below. |
| 23 | + |
| 24 | +See also: [Integrate Pipelines with resource servers using OIDC](https://support.atlassian.com/bitbucket-cloud/docs/integrate-pipelines-with-resource-servers-using-oidc/) |
| 25 | + |
| 26 | +### faas-cli pro license |
| 27 | + |
| 28 | +The `faas-cli pro` plugin requires a valid CLI license. The plugin looks for the license in the `OPENFAAS_CLI_LICENSE` environment variable. |
| 29 | + |
| 30 | +Add `OPENFAAS_CLI_LICENSE` as a repository variable under **Repository settings > Pipelines > Repository variables**, or as a workspace variable under **Workspace settings > Pipelines > Workspace variables**. Mark it as **Secured** so its value is masked in build logs. Workspace and repository variables are automatically available as environment variables in all pipeline steps. |
| 31 | + |
| 32 | +See: [Variables and secrets](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/) |
| 33 | + |
| 34 | +> If you don't have a CLI license yet, contact your account representative at OpenFaaS to receive one. |
| 35 | +
|
| 36 | +## Define an Issuer for Bitbucket |
| 37 | + |
| 38 | +First define a new JwtIssuer resource, setting the `iss` field to the Identity provider URL retrieved from your workspace's OIDC settings. Set the `aud` field to the URL of your OpenFaaS gateway. |
| 39 | + |
| 40 | +```yaml |
| 41 | +apiVersion: iam.openfaas.com/v1 |
| 42 | +kind: JwtIssuer |
| 43 | +metadata: |
| 44 | + name: bitbucket.com |
| 45 | + namespace: openfaas |
| 46 | +spec: |
| 47 | + iss: https://api.bitbucket.org/2.0/workspaces/WORKSPACE/pipelines-config/identity/oidc |
| 48 | + aud: |
| 49 | + - https://gw.example.com |
| 50 | + tokenExpiry: 30m |
| 51 | +``` |
| 52 | +
|
| 53 | +Replace `WORKSPACE` with the name of your Bitbucket workspace. |
| 54 | + |
| 55 | +The `tokenExpiry` field controls how long the OpenFaaS access token is valid. A short expiry such as `30m` is recommended to reduce the window in which a leaked token could be used, but it can be increased for longer-running CI jobs. |
| 56 | + |
| 57 | +The `aud` field must match the custom audience configured in your Bitbucket pipeline. By adding the gateway URL as a [custom audience](#custom-audience) in the pipeline step, it is included in the token's `aud` claim so that OpenFaaS can validate the token. |
| 58 | + |
| 59 | +If you have repositories across multiple workspaces that need to access OpenFaaS, you will need to create a separate issuer for each workspace. |
| 60 | + |
| 61 | +## Create a Policy |
| 62 | + |
| 63 | +Next, define a Policy with the privileges required to perform the desired actions. The following examples show two common use cases: |
| 64 | + |
| 65 | +- A deployment role for any function within the `etl` namespace |
| 66 | +- An invocation-only role for a single function in the `etl` namespace |
| 67 | + |
| 68 | +The `etl-deployer` policy allows listing and deploying functions in the `etl` namespace. It grants permission to list namespaces, list functions, and create or update any function within `etl`: |
| 69 | + |
| 70 | +```yaml |
| 71 | +apiVersion: iam.openfaas.com/v1 |
| 72 | +kind: Policy |
| 73 | +metadata: |
| 74 | + name: etl-deployer |
| 75 | + namespace: openfaas |
| 76 | +spec: |
| 77 | + statement: |
| 78 | + - sid: 1-rw-etl |
| 79 | + action: |
| 80 | + - Function:List |
| 81 | + - Function:Create |
| 82 | + - Function:Update |
| 83 | + - Namespace:List |
| 84 | + effect: Allow |
| 85 | + resource: ["etl:*"] |
| 86 | +``` |
| 87 | + |
| 88 | +For a pipeline that only needs to call a function, the `etl-invoker` policy restricts access to invoking a single function by name: |
| 89 | + |
| 90 | +```yaml |
| 91 | +apiVersion: iam.openfaas.com/v1 |
| 92 | +kind: Policy |
| 93 | +metadata: |
| 94 | + name: etl-invoker |
| 95 | + namespace: openfaas |
| 96 | +spec: |
| 97 | + statement: |
| 98 | + - sid: 1-invoke-etl |
| 99 | + action: |
| 100 | + - Function:Invoke |
| 101 | + effect: Allow |
| 102 | + resource: ["etl:my-function"] |
| 103 | +``` |
| 104 | + |
| 105 | +## Bind a Policy to a Role |
| 106 | + |
| 107 | +Next, you need to bind the Policy to a Role. |
| 108 | + |
| 109 | +The Role uses conditions to match claims from the Bitbucket OIDC token. Here is an overview of the claims available within a Bitbucket Pipelines `id_token`: |
| 110 | + |
| 111 | +```json |
| 112 | +{ |
| 113 | + "sub": "{repositoryUuid}:{stepUuid}", |
| 114 | + "stepUuid": "{xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}", |
| 115 | + "iss": "https://api.bitbucket.org/2.0/workspaces/WORKSPACE/pipelines-config/identity/oidc", |
| 116 | + "branchName": "xxxxxxxxx", |
| 117 | + "workspaceUuid": "{xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}", |
| 118 | + "pipelineRunUuid": "{xxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx}", |
| 119 | + "aud": [ |
| 120 | + "ari:cloud:bitbucket::workspace/WORKSPACE", |
| 121 | + "https://gw.example.com" |
| 122 | + ], |
| 123 | + "repositoryUuid": "{xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}", |
| 124 | + "exp": "xxxxxxxxxx", |
| 125 | + "iat": "xxxxxxxxxx", |
| 126 | + "pipelineUuid": "{xxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx}" |
| 127 | +} |
| 128 | +``` |
| 129 | + |
| 130 | +You can view the example payload for your repository on the **OpenID Connect** page under **Repository settings > Pipelines** in Bitbucket Cloud. |
| 131 | + |
| 132 | +When a [custom audience](#custom-audience) is configured in the pipeline, it will appear alongside the default workspace audience in the `aud` array. |
| 133 | + |
| 134 | +```yaml |
| 135 | +apiVersion: iam.openfaas.com/v1 |
| 136 | +kind: Role |
| 137 | +metadata: |
| 138 | + name: etl-ci-deployer |
| 139 | + namespace: openfaas |
| 140 | +spec: |
| 141 | + policy: |
| 142 | + - etl-deployer |
| 143 | + condition: |
| 144 | + StringEqual: |
| 145 | + jwt:iss: ["https://api.bitbucket.org/2.0/workspaces/WORKSPACE/pipelines-config/identity/oidc"] |
| 146 | + jwt:repositoryUuid: ["{REPO_UUID}"] |
| 147 | + jwt:branchName: ["main"] |
| 148 | +``` |
| 149 | + |
| 150 | +The example above restricts deployments to a specific repository and the `main` branch. You could restrict this further by matching additional claims such as `workspaceUuid` or `pipelineUuid`. |
| 151 | + |
| 152 | +Finally, you need to apply all of the above objects. |
| 153 | + |
| 154 | +## Create a Bitbucket Pipeline |
| 155 | + |
| 156 | +To access the OpenFaaS gateway from a Bitbucket Pipeline you should adapt your pipeline to: |
| 157 | + |
| 158 | +- Obtain the id_token via the `BITBUCKET_STEP_OIDC_TOKEN` environment variable. |
| 159 | +- Authenticate to OpenFaaS with the id_token using the faas-cli pro plugin. |
| 160 | + |
| 161 | +### Custom audience |
| 162 | + |
| 163 | +By default, the Bitbucket OIDC token only includes the workspace audience (e.g. `ari:cloud:bitbucket::workspace/WORKSPACE_UUID`). We recommend adding the OpenFaaS gateway URL as a custom audience. This is done by adding an `oidc` block with an `audiences` list to your pipeline step. The custom audience is appended to the default workspace audience in the token's `aud` claim. |
| 164 | + |
| 165 | +```yaml |
| 166 | +oidc: |
| 167 | + audiences: |
| 168 | + - https://gw.example.com |
| 169 | +``` |
| 170 | + |
| 171 | +When setting a custom audience in the pipeline, the `aud` field in the `JwtIssuer` resource must be set to the same gateway URL so that OpenFaaS can validate the token. |
| 172 | + |
| 173 | +You can set custom audiences at the step level or globally using `options`. See the [Bitbucket documentation](https://support.atlassian.com/bitbucket-cloud/docs/integrate-pipelines-with-resource-servers-using-oidc/) for more details. |
| 174 | + |
| 175 | +### Example pipeline |
| 176 | + |
| 177 | +This is an example `bitbucket-pipelines.yml` file: |
| 178 | + |
| 179 | +```yaml |
| 180 | +image: atlassian/default-image:3 |
| 181 | +
|
| 182 | +pipelines: |
| 183 | + default: |
| 184 | + - step: |
| 185 | + name: Deploy to OpenFaaS |
| 186 | + services: |
| 187 | + - docker |
| 188 | + oidc: |
| 189 | + audiences: |
| 190 | + - https://gw.example.com |
| 191 | + script: |
| 192 | + - export OPENFAAS_URL="https://gw.example.com" |
| 193 | +
|
| 194 | + - mkdir -p $HOME/bin |
| 195 | + - export PATH=$PATH:$HOME/bin |
| 196 | + - curl -sLS https://cli.openfaas.com | sh |
| 197 | +
|
| 198 | + - faas-cli plugin get pro |
| 199 | +
|
| 200 | + - faas-cli pro auth --token=$BITBUCKET_STEP_OIDC_TOKEN |
| 201 | +
|
| 202 | + - faas-cli list -n etl |
| 203 | + - faas-cli ns |
| 204 | + - faas-cli store deploy -n etl printer --name p1 |
| 205 | +``` |
| 206 | + |
| 207 | +The `oidc.audiences` field adds the OpenFaaS gateway URL as a custom audience to the OIDC token. Bitbucket makes the token available through the `BITBUCKET_STEP_OIDC_TOKEN` environment variable when `oidc` is configured on the step. |
| 208 | + |
| 209 | +The faas-cli pro plugin exchanges the Bitbucket OIDC token for an OpenFaaS access token and saves it. After that, faas-cli can be used to interact with the gateway. |
0 commit comments