This service is used for checking a request's authenticity.
For non-human clients, it has to ensure that the request originates from a security principal we know:
This works by checking that the requests has the correct headers (or basic auth, some other mechanism), as per our local credentials database.
For all other requests (those with an active human in the mix), it tries to validate the ID token, and if that fails (or there's no ID token present), it redirects to the internal OIDC identity provider (currently dex).
Authenticating requests works by configuring a set of authenticators, via config.yml:
authenticators:
# proper OIDC: check signature, expiry, audience, and issuer
- id: dex
type: oidc
config:
issuer: http://127.0.0.1:5556/dex
client_id: example-app
# same as oidc, but doesn't interact with the server
# merely checks some token details (iss, aud)
# => can be used without dex, but looks very similar to the setup that is
# using dex
- id: oidc-mock
type: mock-oidc
config:
issuer: http://127.0.0.1:5556/dex
client_id: example-app
# static mock: authenticate every request as coming from foobear
# ⚠️ only for testing and development ️⚠️ -- if this in authenticators,
# authentication never fails
- id: static
type: mock-static
config:
requestor: foobear
Note: We'll have to mirror the group settings (for external groups), but this still TODO.
The service operates as a (reverse) proxy:
upstream: http://traefik/internal # reverse proxy this host...
proxy_http: 0.0.0.0:9090 # ...on this endpoint
Currently, it does not persist any state on the local filesystem.
This service consists in a single executable, authn
, with the following command line interface:
$ ./authn
Usage:
authn [flags]
authn [command]
Available Commands:
help Help about any command
serve Begin serving requests.
version Print the version and exit
Flags:
-h, --help help for authn
Use "authn [command] --help" for more information about a command.
This requires working installations of habitat and direnv. If you haven't ever done that before, setup your Habitat CLI environment:
$ hab cli setup
Then, you can use the studio as development environment:
$ hab studio enter
Please note, we advise you run this service in Habitat studio, which we are using as our working dev environment.
$ make test
This example uses the mock-credentials authenticator example config, but there are other config files that configure other authenticators in the examples directory.
$ make build && ./authn serve examples/config-mock-credentials.yml
The authentication API works analogous to HTTP header-based auth -- it's checking the metadata coming along with the request.
$ grpc_cli call 127.0.0.1:9091 auth.Authentication.Authenticate ''
connecting to 127.0.0.1:9091
Rpc failed with status code 16, error message: request not authenticated
To send a GRPC call with metadata, use this for client tokens, based on the api-token or x-data-collector-token header (assuming the service is configured to use that, which it should be for the immediately foreseeable future),
$ grpc_cli call 127.0.0.1:9091 auth.Authentication.Authenticate '' --metadata "api-token:_o29rYivBitJ7peJKIX3cBuJXnU="
connecting to 127.0.0.1:9091
Sending client initial metadata:
api-token : _o29rYivBitJ7peJKIX3cBuJXnU=
actor: "0920b880-a8bf-48a2-be51-ef23c4994fe4"
Rpc succeeded with OK status
and that for adding a JWT ID token:
$ export TOK="eyJhb..." # your token
$ grpc_cli call 127.0.0.1:9091 auth.Authentication.Authenticate '' --metadata "authorization:bearer $TOK"
If your request is meant to go through automate-gateway's GRPC endpoint, you'll have to ensure the proper metadata headers are set, by using the same arguments outlined above.
While not available as a public API in A2 (so no entry in the load balancer), the authenticate API is also exposed via HTTP1, accessible at /api/authenticate, for use by other A2 services (e.g. the Workflow back end).
[234][default:/src:0]# curl -v -H "api-token: $TOK" http://0.0.0.0:10555/api/authenticate
* Trying 0.0.0.0...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 10555 (#0)
> GET /api/authenticate HTTP/1.1
> Host: 0.0.0.0:10555
> User-Agent: curl/7.54.1
> Accept: */*
> api-token: 4_VoqDUP8wMV0jL9EvHMqTJc18A=
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Grpc-Metadata-Content-Type: application/grpc
< Date: Tue, 14 Aug 2018 17:40:28 GMT
< Content-Length: 56
<
* Connection #0 to host 0.0.0.0 left intact
{"subject":"token:c0a812fb-f2d3-4a3a-9c19-88250c590ff9"}