Reputation: 1254
I'm trying to figure out how to create a simple API key protected proxy with Ambassador on k8s, yet can't seem to find any docs on this.
Specifically, I just want to set it up so it can take a request with API-KEY header, authenticate it, and if API-KEY is valid for some client, pass it onto my backend.
Upvotes: 3
Views: 2150
Reputation: 1148
I settled on this quick and dirty solution after not finding a simple approach (that would not involve spinning up an external authentication service).
You can use Header-based Routing and only allow incoming requests with a matching header:value
.
---
apiVersion: getambassador.io/v2
kind: Mapping
metadata:
name: protected-mapping
namespace: default
spec:
prefix: /protected-path/
rewrite: /
headers:
# Poorman's Bearer authentication
# Ambassador will return a 404 error unless the Authorization header value is set as below on the incoming requests.
Authorization: "Bearer <token>"
service: app:80
Testing
# Not authenticated => 404
$ curl -sI -X GET https://ambassador/protected-path/
HTTP/1.1 404 Not Found
date: Thu, 11 Mar 2021 18:30:27 GMT
server: envoy
content-length: 0
# Authenticated => 200
$ curl -sI -X GET -H 'Authorization: Bearer eEVCV1JtUzBSVUFvQmw4eVRVM25BenJa' https://ambassador/protected-path/
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
vary: Origin
date: Thu, 11 Mar 2021 18:23:20 GMT
content-length: 15
x-envoy-upstream-service-time: 3
server: envoy
While you could technically use any header:value
pair (e.g., x-my-auth-header: header-value
) here, the Authorization: Bearer ...
scheme seems to be the best option if you want to follow a standard.
Whether to base64-encode or not your token in this case is up to you.
Here's a lengthy explanation of how to read and understand the spec(s) in this regard: https://stackoverflow.com/a/56704746/4550880
It boils down to the following regex format for the token value:
[-a-zA-Z0-9._~+/]+=*
Upvotes: 1
Reputation: 8892
I suggest you do the following:
Create an Authentication Application: for each protected endpoint, this app will be responsible for validating the Api Key.
Configuring Ambassador to redirect requests to this service: you just need to annotate your authentication app service definition. Example:
---
apiVersion: v1
kind: Service
metadata:
name: auth-app
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: AuthService
name: authentication
auth_service: "auth-app:8080"
allowed_request_headers:
- "API-KEY"
spec:
type: ClusterIP
selector:
app: auth-app
ports:
- port: 8080
name: auth-app
targetPort: auth-app
apiVersion: ambassador/v1
kind: Mapping
name: myapp-mapping
prefix: /myapp/
service: myapp:8000
Then you need to have an endpoint "/myapp/" in auth-app. You will read your API-KEY header there. If the key is valid, return a HTTP 200 (OK). Ambassador will then send the original message to myapp. If auth-app returns any other thing besides a HTTP 200, Ambassador will return that response to the client.
apiVersion: ambassador/v1
kind: Mapping
name: login-mapping
prefix: /login/
service: login-app:8080
bypass_auth: true
Check this if you want to know more about authentication in Ambassador
EDIT: According to this answer it is a good practice if you use as header Authorization: Bearer {base64-API-KEY}
. In Ambassador the Authorization header is allowed by default, so you don't need to pass it in the allowed_request_headers field.
Upvotes: 4