Compare commits

...
10 Commits
Author SHA1 Message Date
Snyk bot 1a09a13cfa fix: package.json & package-lock.json to reduce vulnerabilities (#97)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-XML2JS-5414874
2023-04-25 07:47:16 -04:00
Hoan Luu Huu b311d4af48 fix: ice issue (#95)
* fix: ice issue

* fix: review comment
2023-04-13 08:43:56 -04:00
Anton Voylenko 0fe8843729 README and env variables validation (#91)
* validate env at startup

* README updated with environment variables
2023-04-10 15:36:36 -04:00
Dave Horton 0b0e37020c push to docker 2023-04-10 09:43:00 -04:00
Antony Jukes 01cde07117 if else made authorization check unreachable (#90) 2023-04-06 09:34:37 -04:00
Hoan Luu Huu 31b4534878 fix: update stat collector version (#89) 2023-04-05 12:03:36 -04:00
Hoan Luu Huu 0c6365a8df fix: update stat collector version (#89) 2023-04-05 12:03:17 -04:00
Dave Hortonandsnyk-bot def2cb2be2 fix: Dockerfile to reduce vulnerabilities (#88)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3368756
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3368756
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-5291792
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-5291792

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2023-03-30 13:31:30 -04:00
Dave Horton baaee6f063 bump version 2023-03-28 14:16:07 -04:00
Hoan Luu HuuandQuan HL d2f32229a2 feat: add instance_id to gause calls metric (#87)
Co-authored-by: Quan HL <quanluuhoang8@gmail.com>
2023-03-21 07:54:52 -04:00
7 changed files with 104 additions and 80 deletions
+31 -30
View File
@@ -2,16 +2,8 @@ name: Docker
on:
push:
# Publish `master` as Docker `latest` image.
branches:
- main
# Publish `v1.2.3` tags as releases.
tags:
- v*
env:
IMAGE_NAME: sbc-inbound
- '*'
jobs:
push:
@@ -20,32 +12,41 @@ jobs:
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v3
- name: Build image
run: docker build . --file Dockerfile --tag $IMAGE_NAME
- name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push image
- name: prepare tag
id: prepare_tag
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
IMAGE_ID=$GITHUB_REPOSITORY
# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# Use Docker `latest` tag convention
[ "$VERSION" == "main" ] && VERSION=latest
# Use Docker `latest` tag convention
[ "$VERSION" == "main" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
echo "image_id=$IMAGE_ID" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.prepare_tag.outputs.image_id }}:${{ steps.prepare_tag.outputs.version }}
build-args: |
GITHUB_REPOSITORY=$GITHUB_REPOSITORY
GITHUB_REF=$GITHUB_REF
+1 -1
View File
@@ -1,4 +1,4 @@
FROM --platform=linux/amd64 node:18.14.1-alpine3.16 as base
FROM --platform=linux/amd64 node:18.15-alpine3.16 as base
RUN apk --update --no-cache add --virtual .builds-deps build-base python3
+31 -2
View File
@@ -1,10 +1,39 @@
# sbc-inbound ![Build Status](https://github.com/jambonz/sbc-inbound/workflows/CI/badge.svg)
This application provides a part of the SBC (Session Border Controller) functionality of jambonz. It handles incoming INVITE requests from carrier sip trunks or from sip devices and webrtc applications. SIP INVITEs from known carriers are allowed in, while INVITEs from sip devices are challenged to authenticate. SIP traffic that is allowed in is sent on to a jambonz application server in a private subnet.
This application provides a part of the SBC (Session Border Controller) functionality of jambonz platform. It handles incoming INVITE requests from carrier sip trunks or from sip devices and webrtc applications. SIP INVITEs from known carriers are allowed in, while INVITEs from sip devices are challenged to authenticate. SIP traffic that is allowed in is sent on to a jambonz application server in a private subnet.
## Configuration
Configuration is provided via the [npmjs config](https://www.npmjs.com/package/config) package. The following elements make up the configuration for the application:
Configuration is provided via environment variables:
| variable | meaning | required?|
|----------|----------|---------|
|DRACHTIO_HOST| ip address of drachtio server (typically '127.0.0.1')|yes|
|DRACHTIO_PORT| listening port of drachtio server for control connections (typically 9022)|yes|
|DRACHTIO_SECRET| shared secret|yes|
|HTTP_PORT| http listen port |no|
|JAMBONES_LOGLEVEL| log level for application, 'info' or 'debug'|no|
|JAMBONES_MYSQL_HOST| mysql host|yes|
|JAMBONES_MYSQL_PORT| mysql port |no|
|JAMBONES_MYSQL_USER| mysql username|yes|
|JAMBONES_MYSQL_PASSWORD| mysql password|yes|
|JAMBONES_MYSQL_DATABASE| mysql data|yes|
|JAMBONES_MYSQL_CONNECTION_LIMIT| mysql connection limit |no|
|DTMF_LISTEN_PORT| DTMF listening port |no|
|JAMBONES_NG_PROTOCOL| rtpengine NG protocol |no|
|RTPENGINE_PORT| rtpengine port |no|
|JAMBONES_CLUSTER_ID| cluster id |no|
|JAMBONES_NETWORK_CIDR| CIDR of private network that feature server is running in (e.g. '172.31.0.0/16')|yes|
|JAMBONES_REDIS_HOST| redis host|yes|
|JAMBONES_REDIS_PORT|redis port|no|
|JAMBONES_RTPENGINES| commas-separated list of ip:ng-port for rtpengines (e.g. '172.31.32.10:22222')|no|
|JAMBONES_TIME_SERIES_HOST| influxdb host |yes|
|JAMBONES_TIME_SERIES_PORT| influxdb port |no|
|JAMBONES_RECORD_ALL_CALLS| enable auto record calls, 'yes' or 'no' |no|
|K8S| service running as kubernetes service |no|
|K8S_RTPENGINE_SERVICE_NAME| rtpengine service name(required for K8S) |no|
|K8S_FEATURE_SERVER_SERVICE_NAME| feature server service name(required for K8S) |no|
##### drachtio server location
```
{
+7 -3
View File
@@ -3,10 +3,12 @@ assert.ok(process.env.JAMBONES_MYSQL_HOST &&
process.env.JAMBONES_MYSQL_USER &&
process.env.JAMBONES_MYSQL_PASSWORD &&
process.env.JAMBONES_MYSQL_DATABASE, 'missing JAMBONES_MYSQL_XXX env vars');
assert.ok(process.env.DRACHTIO_PORT || process.env.DRACHTIO_HOST, 'missing DRACHTIO_PORT env var');
assert.ok(process.env.JAMBONES_REDIS_HOST, 'missing JAMBONES_REDIS_HOST env var');
assert.ok(process.env.DRACHTIO_PORT || process.env.DRACHTIO_HOST, 'missing DRACHTIO_PORT env vars');
assert.ok(process.env.DRACHTIO_SECRET, 'missing DRACHTIO_SECRET env var');
assert.ok(process.env.JAMBONES_TIME_SERIES_HOST, 'missing JAMBONES_TIME_SERIES_HOST env var');
assert.ok(process.env.JAMBONES_NETWORK_CIDR || process.env.K8S, 'missing JAMBONES_NETWORK_CIDR env var');
const Srf = require('drachtio-srf');
const srf = new Srf('sbc-inbound');
const opts = Object.assign({
@@ -50,6 +52,7 @@ const {
queryCallLimits
} = require('@jambonz/db-helpers')({
host: process.env.JAMBONES_MYSQL_HOST,
port: process.env.JAMBONES_MYSQL_PORT || 3306,
user: process.env.JAMBONES_MYSQL_USER,
password: process.env.JAMBONES_MYSQL_PASSWORD,
database: process.env.JAMBONES_MYSQL_DATABASE,
@@ -63,7 +66,7 @@ const {
removeFromSet,
incrKey,
decrKey} = require('@jambonz/realtimedb-helpers')({
host: process.env.JAMBONES_REDIS_HOST || 'localhost',
host: process.env.JAMBONES_REDIS_HOST,
port: process.env.JAMBONES_REDIS_PORT || 6379
}, logger);
@@ -247,7 +250,8 @@ if (process.env.K8S || process.env.HTTP_PORT) {
if ('test' !== process.env.NODE_ENV) {
/* update call stats periodically */
setInterval(() => {
stats.gauge('sbc.sip.calls.count', activeCallIds.size, ['direction:inbound']);
stats.gauge('sbc.sip.calls.count', activeCallIds.size,
['direction:inbound', `instance_id:${process.env.INSTANCE_ID || 0}`]);
}, 20000);
}
+3 -3
View File
@@ -223,7 +223,7 @@ class CallSession extends Emitter {
if (this.req.locals.application_sid) {
Object.assign(headers, {'X-Application-Sid': this.req.locals.application_sid});
}
else if (this.req.authorization) {
if (this.req.authorization) {
if (this.req.authorization.grant && this.req.authorization.grant.application_sid) {
Object.assign(headers, {'X-Application-Sid': this.req.authorization.grant.application_sid});
}
@@ -293,7 +293,6 @@ class CallSession extends Emitter {
} catch (err) {
this.rtpEngineResource.destroy().catch((err) => this.logger.info({err}, 'Error destroying rtpe after failure'));
this.activeCallIds.delete(this.req.get('Call-ID'));
this.stats.gauge('sbc.sip.calls.count', this.activeCallIds.size);
if (err instanceof SipError) {
const tags = ['accepted:no', `sipStatus:${err.status}`, `originator:${this.req.locals.originator}`];
this.stats.increment('sbc.terminations', tags);
@@ -612,7 +611,8 @@ Duration=${payload.duration} `
direction,
sdp: offeredSdp,
};
if (reason && opts.flags && !opts.flags.includes('reset')) opts.flags.push('reset');
// Dont reset ICE - causes audiocodes webrtrc to fail with "missing ice-ufrag and ice-pwd in re-invite"
// if (reason && opts.flags && !opts.flags.includes('reset')) opts.flags.push('reset');
let response = await this.offer(opts);
if ('ok' !== response.result) {
+28 -38
View File
@@ -1,12 +1,12 @@
{
"name": "sbc-inbound",
"version": "v0.8.1",
"version": "v0.8.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "sbc-inbound",
"version": "v0.8.1",
"version": "v0.8.2",
"license": "MIT",
"dependencies": {
"@jambonz/db-helpers": "^0.7.4",
@@ -15,9 +15,9 @@
"@jambonz/realtimedb-helpers": "^0.7.0",
"@jambonz/rtpengine-utils": "^0.4.3",
"@jambonz/siprec-client-utils": "^0.2.4",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/stats-collector": "^0.1.8",
"@jambonz/time-series": "^0.2.5",
"aws-sdk": "^2.1261.0",
"aws-sdk": "^2.1354.0",
"bent": "^7.3.12",
"cidr-matcher": "^2.1.1",
"debug": "^4.3.4",
@@ -670,9 +670,9 @@
}
},
"node_modules/@jambonz/stats-collector": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.8.tgz",
"integrity": "sha512-PadBKTmcphU7bZI7pVr4awhoIi+DMLw7An6AGE0GGsLCn2x0IGnxr9k47gI4Bk3OaSF6N7RyVLEAMkJfr24l8Q==",
"dependencies": {
"debug": "^4.3.2",
"hot-shots": "^8.5.0"
@@ -930,9 +930,9 @@
}
},
"node_modules/aws-sdk": {
"version": "2.1293.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1293.0.tgz",
"integrity": "sha512-Wq4zPwJsrYLerXkWzllrTky3DM/Gwg8rKmC/79cDckGzDT8vZ2w/JfI5lW94ckRHjbqQXalChMH3GmWp0sV29Q==",
"version": "2.1354.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1354.0.tgz",
"integrity": "sha512-3aDxvyuOqMB9DqJguCq6p8momdsz0JR1axwkWOOCzHA7a35+Bw+WLmqt3pWwRjR1tGIwkkZ2CvGJObYHsOuw3w==",
"dependencies": {
"buffer": "4.9.2",
"events": "1.1.1",
@@ -943,7 +943,7 @@
"url": "0.10.3",
"util": "^0.12.4",
"uuid": "8.0.0",
"xml2js": "0.4.19"
"xml2js": "0.5.0"
},
"engines": {
"node": ">= 10.0.0"
@@ -958,20 +958,15 @@
}
},
"node_modules/aws-sdk/node_modules/xml2js": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~9.0.1"
}
},
"node_modules/aws-sdk/node_modules/xmlbuilder": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==",
"xmlbuilder": "~11.0.0"
},
"engines": {
"node": ">=4.0"
"node": ">=4.0.0"
}
},
"node_modules/balanced-match": {
@@ -5809,9 +5804,9 @@
}
},
"@jambonz/stats-collector": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.8.tgz",
"integrity": "sha512-PadBKTmcphU7bZI7pVr4awhoIi+DMLw7An6AGE0GGsLCn2x0IGnxr9k47gI4Bk3OaSF6N7RyVLEAMkJfr24l8Q==",
"requires": {
"debug": "^4.3.2",
"hot-shots": "^8.5.0"
@@ -6003,9 +5998,9 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"aws-sdk": {
"version": "2.1293.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1293.0.tgz",
"integrity": "sha512-Wq4zPwJsrYLerXkWzllrTky3DM/Gwg8rKmC/79cDckGzDT8vZ2w/JfI5lW94ckRHjbqQXalChMH3GmWp0sV29Q==",
"version": "2.1354.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1354.0.tgz",
"integrity": "sha512-3aDxvyuOqMB9DqJguCq6p8momdsz0JR1axwkWOOCzHA7a35+Bw+WLmqt3pWwRjR1tGIwkkZ2CvGJObYHsOuw3w==",
"requires": {
"buffer": "4.9.2",
"events": "1.1.1",
@@ -6016,7 +6011,7 @@
"url": "0.10.3",
"util": "^0.12.4",
"uuid": "8.0.0",
"xml2js": "0.4.19"
"xml2js": "0.5.0"
},
"dependencies": {
"uuid": {
@@ -6025,18 +6020,13 @@
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="
},
"xml2js": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~9.0.1"
"xmlbuilder": "~11.0.0"
}
},
"xmlbuilder": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ=="
}
}
},
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "sbc-inbound",
"version": "v0.8.1",
"version": "v0.8.2",
"main": "app.js",
"engines": {
"node": ">= 12.0.0"
@@ -31,9 +31,9 @@
"@jambonz/realtimedb-helpers": "^0.7.0",
"@jambonz/rtpengine-utils": "^0.4.3",
"@jambonz/siprec-client-utils": "^0.2.4",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/stats-collector": "^0.1.8",
"@jambonz/time-series": "^0.2.5",
"aws-sdk": "^2.1261.0",
"aws-sdk": "^2.1354.0",
"bent": "^7.3.12",
"cidr-matcher": "^2.1.1",
"debug": "^4.3.4",