|
| 1 | +# Function Authentication |
| 2 | + |
| 3 | +With OpenFaaS Identity and Access Management (IAM) you can secure function endpoints without having to write any additional code. Access permissions for functions can be configured using IAM Roles and Policies. |
| 4 | + |
| 5 | +!!! note Technical preview |
| 6 | + Function authentication is currently under technical preview |
| 7 | + |
| 8 | +You can follow this comprehensive tutorial form our blog to get started with built-in function authentication: [Introducing built-in authentication for OpenFaaS Functions](https://www.openfaas.com/blog/built-in-function-authentication/) |
| 9 | + |
| 10 | +## Enable built-in authentication |
| 11 | + |
| 12 | +OpenFaaS Identity and Access Management needs to be enabled and configured in order to use function authentication, see: [Identity and Access Management (IAM)](/openfaas-pro/iam/overview/#installation) |
| 13 | + |
| 14 | +To enable function authentication your functions need to be using a compatible version of the [OpenFaaS watchdog](/architecture/watchdog/). For the classic-watchdog this is any version `> 0.2.3`. The of-watchdog support function authentication for releases `> 0.9.15`. |
| 15 | + |
| 16 | +Authentication can be enabled on a per function basis by setting the `jwt_auth` environment variable to true in the function configuration, e.g: |
| 17 | + |
| 18 | +```yaml |
| 19 | +functions: |
| 20 | + figlet: |
| 21 | + skip_build: true |
| 22 | + image: ghcr.io/openfaas/figlet:latest |
| 23 | + environment: |
| 24 | + jwt_auth: true |
| 25 | +``` |
| 26 | +
|
| 27 | +!!! note |
| 28 | + Existing functions using an older watchdog version and functions without the `jwt_auth` environment variable are not affected if you start using built-in function authentication. By default all functions can be invoked without authentication. |
| 29 | + |
| 30 | +### Define Roles and Policies |
| 31 | + |
| 32 | +Create a new policy or update your existing policies and include the `Function:Invoke` action to allow function invocations. |
| 33 | + |
| 34 | +The `resource` field can be used to specify what resources the `Function:Invoke` action is applied to: |
| 35 | + |
| 36 | +- `*` - allow invocations for all functions in the cluster |
| 37 | +- `staging:*` - allow invocations for all functions in a namespace. In this case the `staging` namespace. |
| 38 | +- `openfaas-fn:env` - allow invocations for an individual function. |
| 39 | + |
| 40 | +The following policy will allow the `env` function in the `dev` namespace to be invoked, and any function in the `openfaas-fn` namespace: |
| 41 | + |
| 42 | +```yaml |
| 43 | +apiVersion: iam.openfaas.com/v1 |
| 44 | +kind: Policy |
| 45 | +metadata: |
| 46 | + name: invoke-policy |
| 47 | + namespace: openfaas |
| 48 | +spec: |
| 49 | + statement: |
| 50 | + - sid: 1-invoke-policy |
| 51 | + action: |
| 52 | + - "Function:Invoke" |
| 53 | + effect: Allow |
| 54 | + resource: |
| 55 | + - "openfaas-fn:*" |
| 56 | + - "dev:env" |
| 57 | +
|
| 58 | +``` |
| 59 | + |
| 60 | +Create a Role to map the `invoke-policy` to a user or group: |
| 61 | + |
| 62 | +```yaml |
| 63 | +apiVersion: iam.openfaas.com/v1 |
| 64 | +kind: Role |
| 65 | +metadata: |
| 66 | + name: invoke-role |
| 67 | + namespace: openfaas |
| 68 | +spec: |
| 69 | + policy: |
| 70 | + - invoke-policy |
| 71 | + condition: |
| 72 | + principal: |
| 73 | + jwt:sub: |
| 74 | + - a9e0e67a-5758-4373-a4ba-23957fa66e6b |
| 75 | + StringEqual: |
| 76 | + jwt:iss: ["https://keycloak.example.com/realms/openfaas"] |
| 77 | +``` |
| 78 | + |
| 79 | + |
| 80 | +## Invoke authenticated functions |
| 81 | + |
| 82 | +To invoke a function that has authentication enabled you need to obtain a function access token. Function access token can be obtained by exchanging a valid ID token or OpenFaaS API access token for a function access token through the OpenFaaS Gateways token exchange endpoint. |
| 83 | + |
| 84 | + |
| 85 | +> Function authentication flow from IdP to function invocation. |
| 86 | + |
| 87 | +1. Obtain an OIDC ID token |
| 88 | + |
| 89 | + Obtain an initial token that can be exchanged for a function access token. This can either be an OIDC ID token from an identity provider registered with OpenFaaS or an OpenFaaS API access token. |
| 90 | + |
| 91 | + This example uses the OAuth2 client credentials flow. This flow can be used for machine to machine interactions and does not need human interaction. Any other OAuth flow or mechanism supported by your identity provider can be used to obtain the initial ID token. |
| 92 | + |
| 93 | + ```bash |
| 94 | + export IDP_TOKEN_URL="https://keycloak.example.com/realms/openfaas/protocol/openid-connect/token" |
| 95 | + export CLIENT_ID="openfaas" |
| 96 | + export CLIENT_SECRET="$(cat ./client-secret.txt)" |
| 97 | +
|
| 98 | + curl -S -L -X POST "${IDP_TOKEN_URL}" \ |
| 99 | + --header 'Content-Type: application/x-www-form-urlencoded' \ |
| 100 | + --data-urlencode "client_id=${CLIENT_ID}" \ |
| 101 | + --data-urlencode "client_secret=${CLIENT_SECRET}" \ |
| 102 | + --data-urlencode 'scope=email' \ |
| 103 | + --data-urlencode 'grant_type=client_credentials' |
| 104 | + ``` |
| 105 | + |
| 106 | +2. Exchange a token for a function access token |
| 107 | + |
| 108 | + Call the token exchange endpoint to exchange the ID token or OpenFaaS API access token obtained in step 1 for a function access token. |
| 109 | + |
| 110 | + !!! info "Permission attenuation" |
| 111 | + |
| 112 | + The optional `audience` parameter can be used to reduce the permissions of a function access token so that it can only be used to invoke a single function, or a subset of functions. |
| 113 | + |
| 114 | + ```bash |
| 115 | + export IDP_TOKEN_URL="https://gateway.example.com/oauth/token" |
| 116 | + export TOKEN="$(cat token.txt)" |
| 117 | +
|
| 118 | + curl -S -L -X POST "${IDP_TOKEN_URL}" \ |
| 119 | + --header 'Content-Type: application/x-www-form-urlencoded' \ |
| 120 | + --data-urlencode "subject_token=${TOKEN}" \ |
| 121 | + --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:id_token" \ |
| 122 | + --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \ |
| 123 | + --data-urlencode 'scope=function' \ |
| 124 | + --data-urlencode 'audience=openfaas-fn:env' # Optional audience parameter |
| 125 | + ``` |
| 126 | + |
| 127 | +3. Invoke an authenticated function |
| 128 | + |
| 129 | + Invoke an authenticated function with the function access token. |
| 130 | + |
| 131 | + ```bash |
| 132 | + curl -i "https://gateway.example.com/function/env" \ |
| 133 | + -H "Authorization: Bearer $(cat ./function-token.txt)" |
| 134 | + ``` |
| 135 | + |
| 136 | +### Invoke authenticated functions with the faas-cli |
| 137 | + |
| 138 | +The `faas-cli invoke` command can be used to invoke authenticated functions. You will only be able to invoke authenticated functions if the CLI is authenticated with the gateway, `faas-cli pro auth`. |
| 139 | + |
| 140 | +```bash |
| 141 | +echo "OpenFaaS" | faas-cli invoke figlet |
| 142 | +``` |
| 143 | + |
| 144 | +For more info on using the CLI with IAM for OpenFaaS, see: [SSO with CLI](/openfaas-pro/sso/cli/) |
| 145 | + |
| 146 | +**Auto-detection for authenticated functions** |
| 147 | + |
| 148 | +The CLI detects if a function needs authentication by calling the function a first time without any authorization header. If it receives a 401 response code the response is inspected to check if authentication with a function access token is required. If this is the case the CLI automatically retries the request with an access token. |
| 149 | + |
| 150 | +If you know that a function needs authentication you can provide the optional `--auth` flag to skip the detection step. The CLI will immediately include the access token in the first call. |
0 commit comments