Skip to content

Commit

Permalink
Support Bearer token authentication and test.
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Jul 30, 2023
1 parent c513663 commit 2527d5e
Show file tree
Hide file tree
Showing 40 changed files with 2,255 additions and 519 deletions.
38 changes: 34 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,48 @@ jobs:
docker tag platform:latest ossrs/srs-cloud:$SRS_TAG &&
docker tag platform:latest registry.cn-hangzhou.aliyuncs.com/ossrs/srs-cloud:$SRS_TAG &&
docker images
- name: Test build install package
- name: Build package
run: |
bash scripts/setup-ubuntu/build.sh --language zh --version $SRS_TAG \
--output build --extract
--output build --extract
du -sh build/*
- name: Test install package
- name: Install package
run: |
sudo bash build/srs-cloud/scripts/setup-ubuntu/install.sh --verbose &&
du -sh /usr/local/srs-cloud/*
- name: Check installed package
- name: Check service
run: |
# Wait for service ready.
make -j -C test
./test/srs-cloud.test -test.v -srs-log -endpoint http://localhost:2022 \
-wait-ready -check-api-secret=false \
-test.run TestApi_Empty
echo "Record log of services."
docker ps -a
systemctl status srs-cloud
journalctl -u srs-cloud -f >journalctl.log 2>&1 & pid_journalctl=$!
docker logs -f srs-cloud >docker.log 2>&1 & pid_docker=$!
- name: Test service
run: |
# We will handle the error by ourselves.
set +e
SRS_PLATFORM_SECRET=$(docker exec srs-cloud redis-cli hget SRS_PLATFORM_SECRET token)
./test/srs-cloud.test -test.v -wait-ready -srs-log -endpoint http://localhost:2022 \
-wait-ready -check-api-secret=true -api-secret=$SRS_PLATFORM_SECRET \
-init-password
ret=$?; echo "Test with ${SRS_PLATFORM_SECRET} result: $ret"
echo "Stop service"
sudo systemctl stop srs-cloud
kill $pid_journalctl 2>/dev/null
kill $pid_docker 2>/dev/null
echo "Log of journalctl.log" && cat journalctl.log
echo "Log of docker.log" && cat docker.log
exit $ret
final:
name: Final
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,4 @@ t.md
/build
/*.tar
/srs-cloud2
/test/srs-cloud.test
2 changes: 1 addition & 1 deletion DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ Platform:
* `/terraform/v1/mgmt/beian/query` Query the beian information.
* `/terraform/v1/mgmt/beian/update` Update the beian information.
* `/terraform/v1/mgmt/secret/query` Query the api secret for OpenAPI.
* `/terraform/v1/mgmt/secret/token` Create token for OpenAPI.
* `/terraform/v1/mgmt/nginx/hls` Update NGINX config, to enable HLS delivery.
* `/terraform/v1/host/versions` Public version api.
* `/terraform/v1/releases` Version management for all components.
Expand Down Expand Up @@ -282,6 +281,7 @@ Also provided by platform for static Files:
* `/terraform/v1/mgmt/upgrade` Upgrade the mgmt to latest version.
* `/terraform/v1/mgmt/containers` Query SRS container.
* `/terraform/v1/host/exec` Exec command sync, response the stdout and stderr.
* `/terraform/v1/mgmt/secret/token` Create token for OpenAPI.

## Depends

Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ADD mgmt /g/mgmt
ADD platform /g/platform
ADD ui /g/ui
ADD usr /g/usr
ADD test /g/test
ADD Makefile /g/Makefile

# Note that we only build the platform without ui, because already build ui for all OS.
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.script
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ FROM ${ARCH}jrei/systemd-ubuntu:focal AS dist
ENV DEBIAN_FRONTEND=noninteractive

# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#apt-get
RUN apt update -y && apt-get install -y docker.io
RUN apt update -y && apt-get install -y docker.io make gdb gcc g++

# Copy nodejs for ui build.
COPY --from=node /usr/local/bin /usr/local/bin
Expand Down
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ __REAL_INSTALL = $(DESTDIR)$(PREFIX)
default: build

help:
@echo "Usage: make build|install|test"
@echo "Usage: make build|install|utest"
@echo " default Show help and quit"
@echo " build Build the project, npm install and build the ui"
@echo " install Copy files for installer"
Expand All @@ -15,11 +15,13 @@ help:
build:
make -C platform
make -C ui
make -C test
make -C releases

clean:
make -C platform clean
make -C ui clean
make -C test clean
make -C releases clean

install:
Expand Down Expand Up @@ -48,6 +50,7 @@ else
endif

test:
cd platform && go test ./...
cd releases && go test ./...
cd platform && go test -v ./...
cd releases && go test -v ./...
cd test && go test -v -check-api-secret=false -test.run TestApi_Empty ./...
cd ui && npm run test
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ You have the option to modify the volumes for srs-cloud and direct them to diffe

* `/data` The global data directory.
* `redis` The redis data directory, the publish secret and record configuration.
* `srs-cloud` The data directory for srs-cloud
* `config` The mgmt password and cloud configuration.
* `record` The record storage directory, save record files.
* `vlive` The storage directory for virtual live, save video files.
* `config` The mgmt password and cloud configuration.
* `record` The record storage directory, save record files.
* `vlive` The storage directory for virtual live, save video files.

You can use environment variables to modify the settings.

Expand Down
1 change: 1 addition & 0 deletions mgmt/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ echo "Start platform container"
CMD="docker run -v ${DATA_HOME}:/data ${EXTRA_PARAMS}
-p ${MGMT_PORT}:2022 -p ${RTMP_PORT}:1935/tcp -p ${API_PORT}:1985/tcp -p
${HTTP_PORT}:8080/tcp -p ${RTC_PORT}:8000/udp -p ${SRT_PORT}:10080/udp
--log-driver=json-file --log-opt=max-size=1g --log-opt=max-file=3
--restart no --rm -it --name srs-cloud --detach
${IMAGE}"
echo $CMD && $CMD
Expand Down
77 changes: 20 additions & 57 deletions platform/dvr-local-disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
Expand All @@ -25,7 +24,6 @@ import (

// Use v8 because we use Go 1.16+, while v9 requires Go 1.18+
"github.com/go-redis/redis/v8"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
)

Expand All @@ -52,27 +50,18 @@ func (v *RecordWorker) Handle(ctx context.Context, handler *http.ServeMux) error
logger.Tf(ctx, "Handle %v", ep)
handler.HandleFunc(ep, func(w http.ResponseWriter, r *http.Request) {
if err := func() error {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return errors.Wrapf(err, "read body")
}

var token string
if err := json.Unmarshal(b, &struct {
if err := ParseBody(ctx, r.Body, &struct {
Token *string `json:"token"`
}{
Token: &token,
}); err != nil {
return errors.Wrapf(err, "json unmarshal %v", string(b))
return errors.Wrapf(err, "parse body")
}

apiSecret := os.Getenv("SRS_PLATFORM_SECRET")
// Verify token first, @see https://www.npmjs.com/package/jsonwebtoken#errors--codes
// See https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac
if _, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(apiSecret), nil
}); err != nil {
return errors.Wrapf(err, "verify token %v", token)
if err := Authenticate(ctx, apiSecret, token, r.Header); err != nil {
return errors.Wrapf(err, "authenticate")
}

if all, err := rdb.HGet(ctx, SRS_RECORD_PATTERNS, "all").Result(); err != nil && err != redis.Nil {
Expand All @@ -97,29 +86,20 @@ func (v *RecordWorker) Handle(ctx context.Context, handler *http.ServeMux) error
logger.Tf(ctx, "Handle %v", ep)
handler.HandleFunc(ep, func(w http.ResponseWriter, r *http.Request) {
if err := func() error {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return errors.Wrapf(err, "read body")
}

var token string
var all bool
if err := json.Unmarshal(b, &struct {
if err := ParseBody(ctx, r.Body, &struct {
Token *string `json:"token"`
All *bool `json:"all"`
}{
Token: &token, All: &all,
}); err != nil {
return errors.Wrapf(err, "json unmarshal %v", string(b))
return errors.Wrapf(err, "parse body")
}

apiSecret := os.Getenv("SRS_PLATFORM_SECRET")
// Verify token first, @see https://www.npmjs.com/package/jsonwebtoken#errors--codes
// See https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac
if _, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(apiSecret), nil
}); err != nil {
return errors.Wrapf(err, "verify token %v", token)
if err := Authenticate(ctx, apiSecret, token, r.Header); err != nil {
return errors.Wrapf(err, "authenticate")
}

if all, err := rdb.HSet(ctx, SRS_RECORD_PATTERNS, "all", fmt.Sprintf("%v", all)).Result(); err != nil && err != redis.Nil {
Expand All @@ -138,31 +118,23 @@ func (v *RecordWorker) Handle(ctx context.Context, handler *http.ServeMux) error
logger.Tf(ctx, "Handle %v", ep)
handler.HandleFunc(ep, func(w http.ResponseWriter, r *http.Request) {
if err := func() error {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return errors.Wrapf(err, "read body")
}

var token, uuid string
if err := json.Unmarshal(b, &struct {
if err := ParseBody(ctx, r.Body, &struct {
Token *string `json:"token"`
UUID *string `json:"uuid"`
}{
Token: &token, UUID: &uuid,
}); err != nil {
return errors.Wrapf(err, "json unmarshal %v", string(b))
}
if uuid == "" {
return errors.New("no uuid")
return errors.Wrapf(err, "parse body")
}

apiSecret := os.Getenv("SRS_PLATFORM_SECRET")
// Verify token first, @see https://www.npmjs.com/package/jsonwebtoken#errors--codes
// See https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac
if _, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(apiSecret), nil
}); err != nil {
return errors.Wrapf(err, "verify token %v", token)
if err := Authenticate(ctx, apiSecret, token, r.Header); err != nil {
return errors.Wrapf(err, "authenticate")
}

if uuid == "" {
return errors.New("no uuid")
}

var metadata M3u8VoDArtifact
Expand Down Expand Up @@ -216,27 +188,18 @@ func (v *RecordWorker) Handle(ctx context.Context, handler *http.ServeMux) error
logger.Tf(ctx, "Handle %v", ep)
handler.HandleFunc(ep, func(w http.ResponseWriter, r *http.Request) {
if err := func() error {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return errors.Wrapf(err, "read body")
}

var token string
if err := json.Unmarshal(b, &struct {
if err := ParseBody(ctx, r.Body, &struct {
Token *string `json:"token"`
}{
Token: &token,
}); err != nil {
return errors.Wrapf(err, "json unmarshal %v", string(b))
return errors.Wrapf(err, "parse body")
}

apiSecret := os.Getenv("SRS_PLATFORM_SECRET")
// Verify token first, @see https://www.npmjs.com/package/jsonwebtoken#errors--codes
// See https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac
if _, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(apiSecret), nil
}); err != nil {
return errors.Wrapf(err, "verify token %v", token)
if err := Authenticate(ctx, apiSecret, token, r.Header); err != nil {
return errors.Wrapf(err, "authenticate")
}

keys, cursor, err := rdb.HScan(ctx, SRS_RECORD_M3U8_ARTIFACT, 0, "*", 100).Result()
Expand Down

0 comments on commit 2527d5e

Please sign in to comment.