Skip to content

Commit

Permalink
implement HTTP auth, fix authconfig parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
iSchluff committed Nov 17, 2020
1 parent 15fbac6 commit ce169d3
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 52 deletions.
52 changes: 44 additions & 8 deletions auth/http.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,59 @@
package auth

import "github.com/voc/srtrelay/stream"
import (
"log"
"net/http"
"net/url"
"time"

"github.com/voc/srtrelay/stream"
)

type httpAuth struct {
url string
config HTTPAuthConfig
client *http.Client
}

type HttpAuthConfig struct {
URL string
type HTTPAuthConfig struct {
URL string
Application string
Timeout time.Duration // Timeout for Auth request
PasswordParam string // POST Parameter containing stream passphrase
}

func NewHttpAuth(config HttpAuthConfig) *httpAuth {
// NewHttpAuth creates an Authenticator with a HTTP backend
func NewHTTPAuth(config HTTPAuthConfig) *httpAuth {
return &httpAuth{
url: config.URL,
config: config,
client: &http.Client{
Timeout: config.Timeout,
},
}
}

// Implement Authenticator

// Authenticate sends form-data in a POST-request to the configured url.
// If the response code is 2xx the publish/play is allowed, otherwise it is denied.
// This should be compatible with nginx-rtmps on_play/on_publish directives.
// https://github.com/arut/nginx-rtmp-module/wiki/Directives#on_play
func (h *httpAuth) Authenticate(streamid stream.StreamID) bool {
// TODO: implement post request
return false
response, err := h.client.PostForm(h.config.URL, url.Values{
"call": {streamid.Mode().String()},
"app": {h.config.Application},
"name": {streamid.Name()},
h.config.PasswordParam: {streamid.Password()},
})

if err != nil {
log.Println("http-auth:", err)
return false
}
defer response.Body.Close()

if response.StatusCode < 200 || response.StatusCode >= 300 {
return false
}

return true
}
12 changes: 8 additions & 4 deletions auth/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ import (
"github.com/voc/srtrelay/stream"
)

type staticAuth struct {
type StaticAuth struct {
allow []string
}

type StaticAuthConfig struct {
Allow []string
}

func NewStaticAuth(config StaticAuthConfig) *staticAuth {
return &staticAuth{
// NewStaticAuth creates an Authenticator with a static config backend
func NewStaticAuth(config StaticAuthConfig) *StaticAuth {
return &StaticAuth{
allow: config.Allow,
}
}

// Implement Authenticator
func (auth *staticAuth) Authenticate(streamid stream.StreamID) bool {

// Authenticate tries to match the stream id against the locally
// configured matches in the allowlist.
func (auth *StaticAuth) Authenticate(streamid stream.StreamID) bool {
for _, allowed := range auth.allow {
if streamid.Match(allowed) {
return true
Expand Down
18 changes: 12 additions & 6 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@
#allow = ["*", "publish/foo/bar", "play/*"]

[auth.http]
# Streams are authenticated using HTTP callbacks
# nginx-rtmp on_publish/on_subscribe compatible http auth
#url = "http://localhost/auth"
# Streams are authenticated using HTTP POST calls against this URL
# Should be compatible to nginx-rtmp on_publish/on_subscribe directives
#url = "http://localhost:8080/publish"

# static
# the full url with be <url>/<app>/<stream-name>
#app = "stream"
# auth timeout duration
#timeout = "1s"

# Value of the 'app' form-field to send in the POST request
# Needed for compatibility with the RTMP-application field
#application = "stream"

# Key of the form-field to send the stream password in
#passwordParam = "auth"
53 changes: 20 additions & 33 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package config

import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"time"

"github.com/pelletier/go-toml"
"github.com/voc/srtrelay/auth"
Expand All @@ -23,42 +23,22 @@ type AppConfig struct {
Buffersize uint
}

type AuthType int

const (
AuthTypeStatic AuthType = iota
AuthTypeHttp
)

func (a *AuthType) UnmarshalTOML(src interface{}) error {
log.Println("got", src)
switch v := src.(type) {
case string:
if v == "static" {
*a = AuthTypeStatic
} else if v == "http" {
*a = AuthTypeHttp
} else {
return fmt.Errorf("Unknown type '%s'", v)
}
return nil
default:
}
return errors.New("Unknown type")
}

type AuthConfig struct {
Type AuthType
Type string
Static auth.StaticAuthConfig
Http auth.HttpAuthConfig
HTTP auth.HTTPAuthConfig
}

func GetAuthenticator(conf AuthConfig) auth.Authenticator {
if conf.Type == AuthTypeHttp {
return auth.NewHttpAuth(conf.Http)
// GetAuthenticator creates a new authenticator according to AuthConfig
func GetAuthenticator(conf AuthConfig) (auth.Authenticator, error) {
switch conf.Type {
case "static":
return auth.NewStaticAuth(conf.Static), nil
case "http":
return auth.NewHTTPAuth(conf.HTTP), nil
default:
return nil, fmt.Errorf("Unknown auth type '%v'", conf.Type)
}

return auth.NewStaticAuth(conf.Static)
}

// Parse tries to find and parse config from paths in order
Expand All @@ -73,10 +53,17 @@ func Parse(paths []string) (*Config, error) {
Buffersize: 384000,
},
Auth: AuthConfig{
Type: AuthTypeStatic,
Type: "static",
Static: auth.StaticAuthConfig{
// Allow everything by default
Allow: []string{"*"},
},
HTTP: auth.HTTPAuthConfig{
URL: "http://localhost:8080/publish",
Timeout: time.Second,
Application: "stream",
PasswordParam: "auth",
},
},
}

Expand Down
7 changes: 6 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@ func main() {
`relay buffer size in bytes, determines maximum delay of a client`)
flag.Parse()

auth, err := config.GetAuthenticator(conf.Auth)
if err != nil {
log.Println(err)
}

serverConfig := server.Config{
Server: server.ServerConfig{
Address: conf.App.Address,
Port: uint16(conf.App.Port),
Latency: conf.App.Latency,
Auth: config.GetAuthenticator(conf.Auth),
Auth: auth,
},
Relay: relay.RelayConfig{
Buffersize: conf.App.Buffersize, // 1s @ 3Mbits/
Expand Down
11 changes: 11 additions & 0 deletions stream/streamid.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ const (
ModePublish
)

func (m Mode) String() string {
switch m {
case ModePlay:
return "play"
case ModePublish:
return "publish"
default:
return "unknown"
}
}

// StreamID represents a connection tuple
type StreamID struct {
str string
Expand Down

0 comments on commit ce169d3

Please sign in to comment.