Important - Introduction of access controls on API proxy module

What is changing?

Bitbucket is going to perform access control checks when proxying requests via an API proxy module. Requests that previously passed through the API proxy may now be rejected with a 403. It is important to note that access controls are an extra check on top of permissions.

When the proxy module executes URL matching it may lookup Bitbucket objects (i.e. workspaces, teams, users, issues, pull requests, commits). The API proxy module has always checked that the calling user has permission to “read” the Bitbucket object (or it will be rejected) before forwarding the request.

The new behaviour is that API proxy module will check that the calling user meets the access controls during any lookup as well. The request will be rejected with a 403 if the calling user does not meet access controls.

Why this change?

The API proxy module was enforcing permissions when looking up objects. That is, the calling user must have read access to the Bitbucket object being looked up in the URL.

Bitbucket didn’t enforce the access controls on top of these permission checks. For example, it would be possible for a user with read access to a repository to call an API proxy module for that repository even though the calling IP did not match one of the allowed IP addresses.

This change will now enforce access controls on API proxy modules making the access control checks more consistent across Bitbucket.

What are Access Controls?

Access controls are a premium feature of Bitbucket that exists on top of permissions. There two current access controls:

  1. IP Whitelisting: Restrict access to Bitbucket to specific IP addresses.
  2. 2FA enforcement: Require a user to have 2FA enabled.

What do I need to do?

You need to check through all our API proxy modules are work out if you need to opt-out of the access controls checks. This is really only makes sense if the module is looking up a target_user or workspace. Lets do some examples:

  • /api/repositories/{workspace}/{repository}/example/resource: This resource probably doesn’t need any change. The repository lookup means we are checking access controls against the repository. This is consistent with Bitbucket where access controls are always checked when accessing a repository. If you lookup issue, commit, pullrequest or repository in your URL then the running access controls makes sense.
  • /api/execute/{job_id}/run: There are no lookups for repository, target_user, workspace, issue, commit and pullrequest. This means that the API proxy module won’t do any access controls checks. You have a few options at this point:
    • No nothing. You don’t want to check access controls.
    • Trigger access controls by doing a lookup on some object in the URL. Probably target_user or workspace.
    • Some resources my be assuming the current user implicitly. In this case you can add a checkAccessControlsTarget in your resource or method. See “Resources that target the request user” below.
  • /api/users/{target_user}/other/{thing_id}/projects: This URL only has workspace or target_user. The thing_id can be ignored because its just a pass-through. The API proxy module will enforce access controls on the target_user. Bitbucket only checks access controls for workspace or target_user objects when performing “admin” actions (e.g. changing permissions). If the resource is considered to execute an “admin” action then checking access controls probably what you want. Otherwise, access controls should not be enforced and you should opt-out (see below).

How to Opt-Out?

Simples. Add a "checkAccessControls": false property to your method. For example:

"proxy": {
    "/api/repo/{workspace}/{repository}": {
      "methods": {
        "get": {
          "checkAccessControls": false,
          "destination": "/connect/proxy/{target_user.uuid}/{repository.uuid}",
          "conditions": [
            {
              "condition": "has_permission",
              "params": {
                "permission": "read"
              },
              "target": "repository"
            }
          ],
          "scopes": [
            "repository"
          ]
        }
      }
    }
  }

The checkAccessControls can also be specified per resource. In this case the checkAccessControls at the method takes precedence over any configuration at the resource level. For example:

"proxy": {
    "/api/repo/{workspace}/{repository}": {
      "checkAccessControls": false,
      "methods": {
        "get": {
          "checkAccessControls": true,
          "destination": "/connect/proxy/{target_user.uuid}/{repository.uuid}",
          "conditions": [
            {
              "condition": "has_permission",
              "params": {
                "permission": "read"
              },
              "target": "repository"
            }
          ],
          "scopes": [
            "repository"
          ]
        }
        "post": {
           ....
        }
      }
    }
  }
}

In this example calls to the post will use the setting in the resource while calls to get will use the setting in the method. If no checkAccessControls is specified it is assumed to be true.

Resources that target the request user

There are some resources that implicitly access information about the user making the request. For example:

"proxy": {
    "/api/my": {
        "destination": "/api/my/get_things?user={user.uuid}"
        ...
    }
}

In this case the "checkAccessControlsTarget": "currentUser" can be added to the resource to execute access controls against the current user.

"proxy": {
    "/api/my": {
        "checkAccessControlsTarget": "currentUser",
        "destination": "/api/my/get_things?user={user.uuid}"
        ...
    }
}

No access control checks will be enforced on this resource unless this setting is added. The setting can be added at the resource or method level. The setting at the method level will overwrite the setting at the resource level.

When will this change take effect?

The change will be rolled out no sooner than Aug 6th, 2020 UTC.

Looking for more information?

If you have any questions or need further clarifications about this change, please reach out in the Bitbucket Cloud Development forum in the Developer Community.

2 Likes