stunner-auth-service

command module
v0.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2024 License: MIT Imports: 21 Imported by: 0

README

STUNner Authentication Service
Discord

A REST API for generating STUNner TURN authentication credentials

This service implements the REST API For Access To TURN Services IETF draft specification to assist in accessing the TURN services provided by STUNner. By default, STUNner uses a fixed username/password pair that can be leveraged by all clients to make TURN relay connections. This mode, however, is not recommended for production use. Instead, the STUNner authentication service provided by this REST API can be used to generate per-client ephemeral (i.e. time-limited) credentials with a configurable expiration deadline. The usage of ephemeral credentials ensures that access to STUNner can be controlled even if the credentials can be discovered by the user, as is the case in WebRTC where TURN credentials must be specified in JavaScript.

Description

By providing a cloud-based relay service, STUNner ensures that a WebRTC media connection can be established via TURN even when one or both sides is incapable of a direct P2P connection, as it is the case when the media servers run inside a Kubernetes cluster. However, as a gateway service, STUNner opens external access to the Kubernetes cluster. Therefore, it is recommended to tightly control user access to the TURN services provided by STUNner.

STUNner implements a mechanism to control access via long-term credentials that are provided as part of the TURN protocol. It is expected that these credentials will be kept secret; if the credentials are discovered, the TURN server could be used by unauthorized users or applications. However, in web applications, ensuring this secrecy is typically impossible.

To address this problem, this service provides a REST API that can be used to retrieve TURN credentials to access STUNner. The service watches the running STUNner dataplane configuration(s) from Kubernetes and automatically generates TURN credentials that will match the current authentication settings for STUNner. The REST API also allows to easily filter the returned TURN URIs to a selected set of STUNner Gateways: it is possible to return all public URIs per Kubernetes namespace, select a particular STUNner Gateways within a namespace, or specify exactly which STUNner Gateway listener (say, TCP or UDP) the returned credential should apply to. This allows to direct users to access the Kubernetes cluster via a specific STUNner listener.

The main use of this service is by a WebRTC application server to generate an ICE server configuration to be returned to clients during session setup.

Getting started

Most users will have the Stunner authentication REST API server automatically deployed into their cluster by the Stunner Helm charts. By default the authentication server is deployed into stunner-system namespace, it is exposed by the Service called stunner-auth, and it listens on port 8088 over plain HTTP, so you can reach it via the URL http://stunner-auth.stunner-system:8088.

Alternatively, you can deploy and test the REST API using the packaged static manifests as follows.

kubectl create namespace stunner-system
kubectl apply -f deploy/kubernetes-stunner-auth-service.yaml

The REST server can also be fired up locally for quick testing, provided that a usable valid kubeconfig is available for a remote cluster. The server can discover the remote CDS server to load STUNner configs.

go build -o authd main.go
./authd -v

If a CDS service is available on a well-known address, then that address can also be explicitly specified on the command line. The below will use the CDS server exposed at 127.0.0.1:13478 and sets the log level to maximum.

./authd --cds-server-address="127.0.0.1:13478" -l all:TRACE

Usage

For the purposes of this test, we set up the Simple tunnel STUNner tutorial and loaded the necessary Kubernetes manifests for demonstration purposes. The sample configuration defines 2 Gateways with the below config:

cd <stunner>
go build -o stunnerctl cmd/stunnerctl/main.go
./stunnerctl -n stunner config 
Gateway: stunner/tcp-gateway (loglevel: "all:INFO")
Authentication type: static, username/password: user-1/pass-1
Listeners:
  - Name: stunner/tcp-gateway/tcp-listener
    Protocol: TURN-TCP
    Public address:port: 10.102.33.126:3478
    Routes: [stunner/iperf-server]
    Endpoints: [10.106.145.240, 10.244.0.11]
Gateway: stunner/udp-gateway (loglevel: "all:INFO")
Authentication type: static, username/password: user-1/pass-1
Listeners:
  - Name: stunner/udp-gateway/udp-listener
    Protocol: TURN-UDP
    Public address:port: 10.103.187.184:3478
    Routes: [stunner/iperf-server]
    Endpoints: [10.106.145.240, 10.244.0.11]

In addition, we fired up a local auth-service REST server that connects to the test cluster running the tutorial, which is available at localhost:8088:

./authd -v

Note that in reality the authentication service should run in your Kubernetes cluster and it should be available only to clients inside the same cluster. In particular, in most installations the REST API will be exposed via the Kubernetes ClusterIP Service called stunner-auth.stunner-system. This helps prevent security problems arising from unauthenticated external clients obtaining valid TURN credentials for a running cluster.

Warning: Never expose the STUNner authentication service externally. Since the REST API is not authenticated, this would provide unchecked access to anyone to your STUNner gateways. If you want to supply TURN credentials to your WebRTC clients, generate the authentication tokens from the application server (that runs inside the cluster too) first and only then return the credentials obtained from the REST API during call setup!

Generating a TURN authentication token

The below will query the REST API for a TURN authentication token, setting the username to my-user and the expiration time of the returned TURN credentials to 1 hour from the present (ttl is set to 3600 sec).

curl -s http://localhost:8088?service=turn\&username=my-user\&ttl=3600| jq .
{
  "password": "pass-1",
  "ttl": 3600,
  "uris": [
    "turn:10.102.33.126:3478?transport=tcp"
  ],
  "username": "user-1"
}

The parameter service=turn is mandatory, the rest of the parameters are optional; see the REST API For Access To TURN Services IETF draft specification to understand the fields of the returned JSON or the OpenAPI specs packaged with the repo. Note also that jq is used above only to pretty-print the response JSON, feel free to remove it.

Due to a limitation of the REST API spec, the authentication service can generate the TURN access token for only a single Gateway. If you have multiple Gateways configured, a random Gateway will be chosen (use the /ice API endpoint below to sidestep this limitation). Observe that the response contains a single TURN URIs corresponding to the TCP gateway.

Generating a complete ICE configuration

In addition to TURN authentication tokens, the REST API server can also generate full ICE configurations. These should be sent from the application to the clients, so that clients can use the correct ICE config to connect via STUNner as the TURN server.

Use the /ice API endpoint to generate an ICE config:

curl -s http://localhost:8088/ice?service=turn\&username=my-user\&ttl=3600| jq .
{
  "iceServers": [
    {
      "credential": "pass-1",
      "urls": [
        "turn:10.102.33.126:3478?transport=tcp"
      ],
      "username": "user-1"
    },
    {
      "credential": "pass-1",
      "urls": [
        "turn:10.103.187.184:3478?transport=udp"
      ],
      "username": "user-1"
    }
  ],
  "iceTransportPolicy": "all"
}

By default the returned ICE configuration will contain a separate ICE server configuration for each Gateway in the cluster. In order to select only the Gateways within a single namespace, provide the name of the required namespace in the HTTP request parameters. You can select a particular Gateway using the gateway=<gateway-name> parameter and a particular listener using listener=<listenername>. For instance, the below will generate a TURN URI only for the first listener in the sample STUNner config:

curl -s "http://localhost:8088/ice?service=turn&namespace=stunner&gateway=udp-gateway&listener=udp-listener&iceTransportPolicy=relay" | jq .
{
  "iceServers": [
    {
      "credential": "pass-1",
      "urls": [
        "turn:10.103.187.184:3478?transport=udp"
      ],
      "username": "user-1"
    }
  ],
  "iceTransportPolicy": "relay"
}

The request parameters defined for the TURN REST API (namely, username and ttl) can be used for this API too. In addition, the parameter iceTransportPolicy=relay will force clients to skip generating host and server-reflexive ICE candidates (which will not work with STUNner anyway) and use TURN for connecting unconditionally. This will make client connections much faster.

API

The REST API exposes two API endpoints: getTurnAuth can be called to obtain a TURN authentication credential stanza as in the REST API For Access To TURN Services spec, while getIceAuth returns an ICE server configuration ready to be supplied to an RTCPeerConnection call as configuration. The difference between the two is mostly syntactic: we recommend the use of the latter API as it provides a standard format expected by client WebRTC implementations.

The getTurnAuth API

The getTurnAuth API can be used to obtain a TURN authentication credential stanza as in the REST API For Access To TURN Services spec.

Request

A request to the getTurnAuth API endpoint includes the following parameters, specified in the URL:

  • service: specifies the desired service (turn).
  • username: an optional user id to be associated with the credentials.
  • key: if an API key is used for authentication, the API key.
  • namespace: consider only the STUNner Gateways in the given namespace when generating TURN URIs.
  • gateway: consider only the specified STUNner Gateway; if gateway is set then namespace must be set as well.
  • listener: consider only the specified listener on the given STUNner Gateway; if listener is set then namespace and gateway must be set too.
Response

The response is returned with content-type "application/json", and consists of a JSON object with the following parameters:

  • username: the TURN username to use; depending on the running STUNner configuration this may be a fix username (for the static auth type) or a colon-delimited combination of an expiration time as a UNIX timestamp and the username parameter from the request (for the ephemeral auth type).
  • password: the TURN password to use; again, depending on the running STUNner configuration this may be a fix password or a value dynamically computed from the a secret key shared with STUNner and the returned username value (for the ephemeral auth type), see details in the spec.
  • ttl: the duration for which the username and password are valid, in seconds, default is one day (86400 seconds). Note that static passwords are valid forever.
  • uris: an array of TURN URIs, indicating the addresses and/or protocols that can be used to reach STUNner. Each Gateway will be wrapped by STUNner with a Kubernetes LoadBalancer service and the public IP address of that LoadBalancer service will be used as a TURN server address in the returned URI, the public port as the TURN port, and the Gateway protocol as the TURN protocol.

The getIceAuth API

The getIceAuth API can be used to obtain a full ICE server configuration. The use of this API is similar to that of the getTurnAuth API. An additional optional parameter called icetransportpolicy is also available, which can be set to fix the ICE transport policy to either all (let ICE to consider all candidates) or relay (consider only relayed ICE candidates). The response is in the format of a standard ICE server configuration that can be readily passed to the RTCPeerConnection call.

Help

STUNner development is coordinated in Discord, feel free to join.

License

Copyright 2021-2024 by its authors. Some rights reserved. See AUTHORS.

MIT License - see LICENSE for full text.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
client
Package client provides primitives to interact with the openapi HTTP API.
Package client provides primitives to interact with the openapi HTTP API.
pkg
client
Package client provides primitives to interact with the openapi HTTP API.
Package client provides primitives to interact with the openapi HTTP API.
server
Package server provides primitives to interact with the openapi HTTP API.
Package server provides primitives to interact with the openapi HTTP API.
types
Package types provides primitives to interact with the openapi HTTP API.
Package types provides primitives to interact with the openapi HTTP API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL