[ADDED] Support for token in configuration file

So far, it was only possible to use token from the command line.

Resolves #464
This commit is contained in:
Ivan Kozlovic
2017-03-30 10:36:48 -06:00
parent 91f4997795
commit 0cf8455a3a
4 changed files with 99 additions and 2 deletions

View File

@@ -394,6 +394,16 @@ authorization {
}
```
Or, if you chose to use a token:
```
authorization {
# You can generate the token using /util/mkpassword.go
token: $2a$11$pBwUBpza8vdJ7tWZcP5GRO13qRgh4dwNn8g67k5i/41yIKBp.sHke
timeout: 1
}
```
**Multi-user authentication**
You can enable multi-user authentication using a NATS server configuration file that defines user credentials (`user` and `password`), and optionally `permissions`, for two or more users. Multi-user authentication leverages [variables](#variables).

View File

@@ -88,8 +88,9 @@ type Options struct {
// Configuration file authorization section.
type authorization struct {
// Singles
user string
pass string
user string
pass string
token string
// Multiple Users
users []*User
timeout float64
@@ -174,12 +175,19 @@ func ProcessConfigFile(configFile string) (*Options, error) {
}
opts.Username = auth.user
opts.Password = auth.pass
opts.Authorization = auth.token
if (auth.user != "" || auth.pass != "") && auth.token != "" {
return nil, fmt.Errorf("Cannot have a user/pass and token")
}
opts.AuthTimeout = auth.timeout
// Check for multiple users defined
if auth.users != nil {
if auth.user != "" {
return nil, fmt.Errorf("Can not have a single user/pass and a users array")
}
if auth.token != "" {
return nil, fmt.Errorf("Can not have a token and a users array")
}
opts.Users = auth.users
}
case "http":
@@ -340,6 +348,8 @@ func parseAuthorization(am map[string]interface{}) (*authorization, error) {
auth.user = mv.(string)
case "pass", "password":
auth.pass = mv.(string)
case "token":
auth.token = mv.(string)
case "timeout":
at := float64(1)
switch mv.(type) {

View File

@@ -4,8 +4,11 @@ package server
import (
"crypto/tls"
"io/ioutil"
"net/url"
"os"
"reflect"
"strings"
"testing"
"time"
)
@@ -605,3 +608,46 @@ func TestAuthorizationConfig(t *testing.T) {
t.Fatalf("Expected Susan's subscribe permissions to be 'PUBLIC.>', got %q\n", subPerm)
}
}
func TestTokenWithUserPass(t *testing.T) {
confFileName := "test.conf"
defer os.Remove(confFileName)
content := `
authorization={
user: user
pass: password
token: $2a$11$whatever
}`
if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
t.Fatalf("Error writing config file: %v", err)
}
_, err := ProcessConfigFile(confFileName)
if err == nil {
t.Fatal("Expected error, got none")
}
if !strings.Contains(err.Error(), "token") {
t.Fatalf("Expected error related to token, got %v", err)
}
}
func TestTokenWithUsers(t *testing.T) {
confFileName := "test.conf"
defer os.Remove(confFileName)
content := `
authorization={
token: $2a$11$whatever
users: [
{user: test, password: test}
]
}`
if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
t.Fatalf("Error writing config file: %v", err)
}
_, err := ProcessConfigFile(confFileName)
if err == nil {
t.Fatal("Expected error, got none")
}
if !strings.Contains(err.Error(), "token") {
t.Fatalf("Expected error related to token, got %v", err)
}
}

View File

@@ -4,6 +4,8 @@ package test
import (
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/nats-io/go-nats"
@@ -48,3 +50,32 @@ func TestMultipleUserAuth(t *testing.T) {
}
defer nc.Close()
}
// Resolves to "test"
const testToken = "$2a$05$3sSWEVA1eMCbV0hWavDjXOx.ClBjI6u1CuUdLqf22cbJjXsnzz8/."
func TestTokenInConfig(t *testing.T) {
confFileName := "test.conf"
defer os.Remove(confFileName)
content := `
listen: 127.0.0.1:4567
authorization={
token: ` + testToken + `
timeout: 5
}`
if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
t.Fatalf("Error writing config file: %v", err)
}
s, opts := RunServerWithConfig(confFileName)
defer s.Shutdown()
url := fmt.Sprintf("nats://test@%s:%d/", opts.Host, opts.Port)
nc, err := nats.Connect(url)
if err != nil {
t.Fatalf("Expected a successful connect, got %v\n", err)
}
defer nc.Close()
if !nc.AuthRequired() {
t.Fatal("Expected auth to be required for the server")
}
}