Skip to content

Commit

Permalink
Adding account_token_position to account exports
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Hanel <mh@synadia.com>
  • Loading branch information
matthiashanel committed May 18, 2020
1 parent 9382d4f commit e422e0c
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 7 deletions.
38 changes: 31 additions & 7 deletions exports.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package jwt

import (
"fmt"
"strings"
"time"
)

Expand Down Expand Up @@ -71,13 +72,14 @@ func (sl *ServiceLatency) Validate(vr *ValidationResults) {

// Export represents a single export
type Export struct {
Name string `json:"name,omitempty"`
Subject Subject `json:"subject,omitempty"`
Type ExportType `json:"type,omitempty"`
TokenReq bool `json:"token_req,omitempty"`
Revocations RevocationList `json:"revocations,omitempty"`
ResponseType ResponseType `json:"response_type,omitempty"`
Latency *ServiceLatency `json:"service_latency,omitempty"`
Name string `json:"name,omitempty"`
Subject Subject `json:"subject,omitempty"`
Type ExportType `json:"type,omitempty"`
TokenReq bool `json:"token_req,omitempty"`
Revocations RevocationList `json:"revocations,omitempty"`
ResponseType ResponseType `json:"response_type,omitempty"`
Latency *ServiceLatency `json:"service_latency,omitempty"`
AccountTokenPosition uint `json:"account_token_position,omitempty"`
}

// IsService returns true if an export is for a service
Expand Down Expand Up @@ -124,6 +126,28 @@ func (e *Export) Validate(vr *ValidationResults) {
e.Latency.Validate(vr)
}
e.Subject.Validate(vr)

if e.AccountTokenPosition > 0 {
if !e.Subject.HasWildCards() {
vr.AddError("Account Token Position can only be used when wildcard subjects: %s", e.Subject)
} else {
subj := string(e.Subject)
token := strings.Split(subj, ".")
tkCnt := uint(len(token))
if e.AccountTokenPosition == tkCnt && strings.HasSuffix(subj, "*") {
// all well, check for last token being '>' happens below
} else if e.AccountTokenPosition < tkCnt {
if tk := token[e.AccountTokenPosition-1]; tk != "*" {
vr.AddError("Account Token Position %d matches '%s' but must match a * in: %s",
e.AccountTokenPosition, tk, e.Subject)
}
} else if !strings.HasSuffix(subj, ">") {
vr.AddError(
"Account Token Position %d exceeds length of subject '%s' and last token is not >",
e.AccountTokenPosition, e.Subject)
}
}
}
}

// Revoke enters a revocation by publickey using time.Now().
Expand Down
68 changes: 68 additions & 0 deletions exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,71 @@ func TestExport_Sorting(t *testing.T) {
t.Fatal("exports not sorted")
}
}

func TestExportAccountTokenPos(t *testing.T) {
okp := createOperatorNKey(t)
akp := createAccountNKey(t)
apk := publicKey(akp, t)
tbl := map[Subject]uint{
">": 5,
"*": 1,
"foo.*": 2,
"foo.>": 2,
"foo.*.bar.*": 2,
"foo.*.bar.>": 2,
"*.*.*.>": 2,
"*.*.>": 1,
}
for k, v := range tbl {
t.Run(string(k), func(t *testing.T) {
account := NewAccountClaims(apk)
//account.Limits = OperatorLimits{}
account.Exports = append(account.Exports,
&Export{Type: Stream, Subject: k, AccountTokenPosition: v})
actJwt := encode(account, okp, t)
account2, err := DecodeAccountClaims(actJwt)
if err != nil {
t.Fatal("error decoding account jwt", err)
}
AssertEquals(account.String(), account2.String(), t)
vr := &ValidationResults{}
account2.Validate(vr)
if len(vr.Issues) != 0 {
t.Fatal("validation issues", *vr)
}
})
}
}

func TestExportAccountTokenPosFail(t *testing.T) {
okp := createOperatorNKey(t)
akp := createAccountNKey(t)
apk := publicKey(akp, t)
tbl := map[Subject]uint{
"foo.>": 1,
"*": 5,
"*.*": 5,
"bar": 1,
"foo.bar": 2,
"foo.*.bar": 3,
}
for k, v := range tbl {
t.Run(string(k), func(t *testing.T) {
account := NewAccountClaims(apk)
//account.Limits = OperatorLimits{}
account.Exports = append(account.Exports,
&Export{Type: Stream, Subject: k, AccountTokenPosition: v})
actJwt := encode(account, okp, t)
account2, err := DecodeAccountClaims(actJwt)
if err != nil {
t.Fatal("error decoding account jwt", err)
}
AssertEquals(account.String(), account2.String(), t)
vr := &ValidationResults{}
account2.Validate(vr)
if len(vr.Issues) != 1 {
t.Fatal("validation issue expected", *vr)
}
})
}
}

0 comments on commit e422e0c

Please sign in to comment.