A library to generate ICE configuration and TURN credentials for the STUNner Kubernetes ingress gateway for WebRTC.
const auth = require('@l7mp/stunner-auth-lib');
var credentials = auth.getStunnerCredentials({
auth_type: 'longterm',
secret: 'my-shared-secret',
duration: 24*60*60, // credentials valid for one day
});
Install from NPM.
npm install @l7mp/stunner-auth-lib
The intended use is to ease the generation of STUN/TURN credentials and ICE server configuration stanza in the WebRTC application server. The application server can send these back to the WebRTC clients during the WebSocket/JSON call setup process. Clients can then use the STUN/TURN credentials and ICE server configuration received from the application server to authenticate with STUNner, in order to reach the WebRTC media plane deployed into Kubernetes behind STUNner.
The library will automatically parse the current STUNner configuration from the Kubernetes control plane if available. Otherwise, it falls back to taking configuration from environment variables.
The library depends on a valid STUNner configuration for generating STUN/TURN credentials, which is
typically generated by the STUNner Kubernetes Gateway
Operator. The STUNner configuration is rendered
into a Kubernetes
ConfigMap,
which is then picked up by the STUNner dataplane to ingest
WebRTC media into the Kubernetes cluster. Suppose that this ConfigMap is named stunnerd-config
(this is the default name). The below Kubernetes pod template snippet shows how to map this
configuration into your WebRTC application server.
...
spec:
containers:
- name: <my-application-server>
image: <my-application-server-image>
...
env:
- name: STUNNER_CONFIG_FILENAME
value: "/etc/stunnerd/stunnerd.conf"
volumeMounts:
- name: stunnerd-config-volume
mountPath: /etc/stunnerd
readOnly: true
...
volumes:
- name: stunnerd-config-volume
configMap:
name: stunnerd-config
...
From this point, the STUNner configuration, as actually existing in the stunnerd-config
ConfigMap, will be mapped into the application server pod's filesystem under the path
/etc/stunnerd/stunnerd.conf
and the full path will be available in the STUNNER_CONFIG_FILENAME
environment variable. The library will pick up this configuration and use it to generate the
STUN/TURN credentials and full ICE server configurations necessary to reach STUNner.
Every time you change the STUNner configuration through the Kubernetes Gateway API, the new configuration will be immediately mapped into the filesystem of your application server. When called, the library will re-parse the active configuration from the filesystem and the new settings will immediately take effect: new client requests will receive up-to-date STUN/TURN credentials.
If no valid configuration file is found, the library falls back to the standalone mode.
The recommended usage is generating the ICE configuration along with the STUNner credentials in a single step and sending it back the WebRTC clients during call setup.
-
Generate a full ICE configuration object on the WebRTC application server.
const auth = require('@l7mp/stunner-auth-lib'); ... var ICE_config = auth.getIceConfig(); console.log(ICE_config);
Output:
{ iceServers: [ { url: 'turn:1.2.3.4:3478?transport=udp', username: 'my-user', credential: 'my-password' } ], iceTransportPolicy: 'relay' }
-
Send the generated ICE configuration back to the clients during the WebSocket/JSON call setup process (e.g., during user registration) and use this configuration in the clients to initialize the WebRTC
PeerConnection
.var ICE_config = ...; // read ICE configuration from the WebSocket/JSON connection var pc = new RTCPeerConnection(ICE_config);
You can override the path to the STUNner configuration file (and other options) when calling the function.
var ICE_config = auth.getIceConfig({config_file: <MY_STUNNER_CONFIG_FILENAME>});
Alternatively, you can simply generate a new STUN/TURN long-term credentials that you can use for authenticating with STUNner.
var cred = auth.getStunnerCredentials({
duration: 24 * 60 * 60, // lifetime the longterm credential is effective
});
console.log(`STUNner credentials: ${cred.username} / ${cred.credential}`);
Output:
STUNner credentials: 1652118264 / nRU+Iz2ENeP2Y3sDXzSRsFRDs8s=
Some may favor running STUNner in the standalone mode in order
to be able to manually customize the STUNner dataplane instead of relying on the operator to render
the configuration. The library automatically falls back to using the standalone mode when no
configuration file is available under the path specified by the STUNNER_CONFIG_FILENAME
environment variable. For this, the application server needs to have access to the following
environment variables.
STUNNER_PUBLIC_ADDR
(no default, must be customized): STUNner public IP address.STUNNER_PUBLIC_PORT
(default: 3478): STUNner public port.STUNNER_REALM
(default:stunner.l7mp.io
): STUN/TURN realm.STUNNER_AUTH_TYPE
(default:plaintext
): STUNner authentication mode; eitherplaintext
orlongterm
.STUNNER_USERNAME
(default:user
): username forplaintext
authentication.STUNNER_PASSWORD
(default:pass
): password forplaintext
authentication.STUNNER_SHARED_SECRET
(default:secret
): the shared secret forlongterm
authentication.
For most configuration parameters the library specifies sane defaults, which can be overridden by the environment variables (i.e., the STUNner configuration), which can in turn be further overridden in the function arguments specified on the library calls.
The below code will generate a full ICE configuration object in the fallback mode using the specified overrides.
const auth = require('@l7mp/stunner-auth-lib');
...
var ICE_config = auth.getIceConfig({
address: '1.2.3.4', // ovveride STUNNER_PUBLIC_ADDR
port: 3478, // ovveride STUNNER_PUBLIC_PORT
auth_type: 'plaintext', // override STUNNER_AUTH_TYPE
username: 'my-user', // override STUNNER_USERNAME
password: 'my-password', // override STUNNER_PASSWORD
ice_transport_policy: 'relay', // override STUNNER_ICE_TRANSPORT_POLICY
});
console.log(ICE_config);
The below will generate a new set of STUN/TURN long-term credentials, again using manual overrides.
var cred = auth.getStunnerCredentials({
auth_type: 'longterm', // override STUNNER_AUTH_TYPE
secret: 'my-secret', // override STUNNER_SHARED_SECRET
duration: 24 * 60 * 60, // lifetime the longterm credential is effective
});
console.log(`STUNner credentials: ${cred.username} / ${cred.credential}`);
Output:
STUNner credentials: 1652118264 / nRU+Iz2ENeP2Y3sDXzSRsFRDs8s=
Note that all manual overrides are available in the default mode as well.
-
In order for the library to be able to read the STUNner configuration, the corresponding ConfigMap (i.e.,
stunnerd-config
) and the application server must live in the same Kubernetes namespace (Kubernetes does not allow a ConfigMap to be mapped into a pod that exists in a different namespace). See the STUNner examples on how to configure the STUNner Kubernetes Gateway Operator to render the configuration into an arbitrary namespace from where your application server can pick it up. -
If you change the STUNner credentials from the Kubernetes Gateway API then active clients, which have already received an ICE configuration that is now being rendered invalid by your change, will need to go through the authentication process (receive a new ICE configuration, re-request TURN permissions again from STUNner, etc.) again. Otherwise, they will time out on the next TURN permission refresh cycle. Currently it is the responsibility of the application server to orchestrate this process. As a rule of thumb, try to avoid resetting the authentication settings when active users are authenticated with STUNner.
STUNner development is coordinated in Discord, send us an email to ask an invitation.
Copyright 2021-2022 by its authors. Some rights reserved. See AUTHORS.
MIT License - see LICENSE for full text.
Initial code adopted from @rojo2/turn-credentials.