Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes to make activation token have single export #13

Merged
merged 1 commit into from
Nov 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions account_claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ func TestNewAccountClaims(t *testing.T) {
activation := NewActivationClaims(apk)
activation.Max = 1024 * 1024
activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
activation.Exports = Exports{}
activation.Exports.Add(&Export{Subject: "test", Type: Stream})
activation.Export = Export{Subject: "test", Type: Stream}
actJWT := encode(activation, akp2, t)

account := NewAccountClaims(apk)
Expand Down
12 changes: 4 additions & 8 deletions activation_claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,14 @@ import (

// Activation defines the custom parts of an activation claim
type Activation struct {
Exports Exports `json:"exports,omitempty"`
Export Export `json:"export,omitempty"`
Limits
}

// Validate checks the exports and limits in an activation JWT
func (a *Activation) Validate(vr *ValidationResults) {
a.Exports.Validate(vr)
a.Export.Validate(vr)
a.Limits.Validate(vr)

if len(a.Exports) > 1 {
vr.AddError("activation tokens can only contain a single export")
}
}

// ActivationClaims holds the data specific to an activation JWT
Expand Down Expand Up @@ -92,11 +88,11 @@ func (a *ActivationClaims) String() string {
// the one special case is that if the export start with "*" or is ">" the <subject> "_"
func (a *ActivationClaims) HashID() (string, error) {

if a.Issuer == "" || a.Subject == "" || len(a.Exports) == 0 || a.Exports[0].Subject == "" {
if a.Issuer == "" || a.Subject == "" || a.Export.Subject == "" {
return "", fmt.Errorf("not enough data in the activaion claims to create a hash")
}

subject := cleanSubject(string(a.Exports[0].Subject))
subject := cleanSubject(string(a.Export.Subject))
base := fmt.Sprintf("%s.%s.%s", a.Issuer, a.Subject, subject)
h := sha256.New()
h.Write([]byte(base))
Expand Down
29 changes: 15 additions & 14 deletions activation_claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ func TestNewActivationClaims(t *testing.T) {
activation.Limits.Payload = 10
activation.Limits.Src = "255.255.255.0"

activation.Export.Subject = "foo"
activation.Export.TokenReq = false
activation.Export.Name = "Foo"
activation.Export.Type = Stream

vr := CreateValidationResults()
activation.Validate(vr)

Expand Down Expand Up @@ -131,6 +136,12 @@ func TestActivationValidation(t *testing.T) {
activation.Issuer = apk
activation.Subject = apk2
activation.Expires = time.Now().Add(time.Duration(time.Hour)).Unix()

activation.Export.Subject = "foo"
activation.Export.TokenReq = false
activation.Export.Name = "Foo"
activation.Export.Type = Stream

activation.Limits.Max = 10
activation.Limits.Payload = 10
activation.Limits.Src = "1.1.1.1"
Expand All @@ -152,7 +163,7 @@ func TestActivationValidation(t *testing.T) {
t.Error("valid activation should pass validation")
}

activation.Exports.Add(&Export{Type: Stream, Name: "times", Subject: "times.*"})
activation.Export = Export{Type: Stream, Name: "times", Subject: "times.*"}

vr = CreateValidationResults()
activation.Validate(vr)
Expand All @@ -161,17 +172,7 @@ func TestActivationValidation(t *testing.T) {
t.Error("valid activation should pass validation")
}

activation.Exports.Add(&Export{Type: Stream, Name: "other", Subject: "other.*"})

vr = CreateValidationResults()
activation.Validate(vr)

if vr.IsEmpty() || !vr.IsBlocking(true) {
t.Error("activation can only have 1 export")
}

activation.Exports = Exports{}
activation.Exports.Add(&Export{Type: Stream, Name: "other", Subject: "other.*"})
activation.Export = Export{Type: Stream, Name: "other", Subject: "other.*"}

activation.Limits.Max = -1
vr = CreateValidationResults()
Expand Down Expand Up @@ -237,7 +238,7 @@ func TestActivationHashIDLimits(t *testing.T) {
t.Fatal("activation without subject should fail to hash")
}

activation.Exports.Add(&Export{Type: Stream, Name: "times", Subject: "times.*"})
activation.Export = Export{Type: Stream, Name: "times", Subject: "times.*"}

hash, err := activation.HashID()
if err != nil {
Expand All @@ -247,7 +248,7 @@ func TestActivationHashIDLimits(t *testing.T) {
activation2 := NewActivationClaims(apk)
activation2.Issuer = apk
activation2.Subject = apk2
activation2.Exports.Add(&Export{Type: Stream, Name: "times", Subject: "times.*.bar"})
activation2.Export = Export{Type: Stream, Name: "times", Subject: "times.*.bar"}

hash2, err := activation2.HashID()
if err != nil {
Expand Down
10 changes: 3 additions & 7 deletions imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,18 @@ func (i *Import) Validate(actPubKey string, vr *ValidationResults) {
var err error
act, err = DecodeActivationClaims(i.Token)
if err != nil {
vr.AddWarning("import %s contains an invalid activation token", i.Subject)
vr.AddWarning("import %q contains an invalid activation token", i.Subject)
}
}
}

if act != nil {
if act.Issuer != i.Account {
vr.AddWarning("activation token doesn't match account for import %s", i.Subject)
vr.AddWarning("activation token doesn't match account for import %q", i.Subject)
}

if act.Subject != actPubKey {
vr.AddWarning("activation token doesn't match account it is being included in, %s", i.Subject)
}

if !act.Exports.HasExportContainingSubject(i.Subject) {
vr.AddWarning("activation token include the subject trying to be imported, %s", i.Subject)
vr.AddWarning("activation token doesn't match account it is being included in, %q", i.Subject)
}
} else {
vr.AddWarning("no activation provided for import %s", i.Subject)
Expand Down
27 changes: 12 additions & 15 deletions imports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ func TestImportValidation(t *testing.T) {
activation := NewActivationClaims(akp)
activation.Max = 1024 * 1024
activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
activation.Exports = Exports{}
activation.Exports.Add(&Export{Subject: "test", Type: Stream})
activation.Export = Export{Subject: "test", Type: Stream}
actJWT := encode(activation, ak2, t)

i.Token = actJWT
Expand Down Expand Up @@ -138,8 +137,7 @@ func TestInvalidImportTokenValuesValidation(t *testing.T) {
activation := NewActivationClaims(akp)
activation.Max = 1024 * 1024
activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
activation.Exports = Exports{}
activation.Exports.Add(&Export{Subject: "test", Type: Stream})
activation.Export = Export{Subject: "test", Type: Stream}
actJWT := encode(activation, ak2, t)

i.Token = actJWT
Expand Down Expand Up @@ -232,8 +230,7 @@ func TestTokenURLImportValidation(t *testing.T) {
activation := NewActivationClaims(akp)
activation.Max = 1024 * 1024
activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
activation.Exports = Exports{}
activation.Exports.Add(&Export{Subject: "test", Type: Stream})
activation.Export = Export{Subject: "test", Type: Stream}

actJWT := encode(activation, ak2, t)

Expand Down Expand Up @@ -288,37 +285,37 @@ func TestTokenURLImportValidation(t *testing.T) {

func TestImportSubjectValidation(t *testing.T) {
ak := createAccountNKey(t)
ak2 := createAccountNKey(t)
akp := publicKey(ak, t)
akp2 := publicKey(ak2, t)
i := &Import{Subject: "one.two", Account: akp2, To: "bar", Type: Stream}

activation := NewActivationClaims(akp)
activation.Max = 1024 * 1024
activation.Expires = time.Now().Add(time.Duration(time.Hour)).UTC().Unix()
activation.Exports = Exports{}
activation.Exports.Add(&Export{Subject: "one.*", Type: Stream})
activation.Export = Export{Subject: "one.*", Type: Stream}

ak2 := createAccountNKey(t)
akp2 := publicKey(ak2, t)
i := &Import{Subject: "one.two", Account: akp2, To: "bar", Type: Stream}

actJWT := encode(activation, ak2, t)
i.Token = actJWT
vr := CreateValidationResults()
i.Validate(akp, vr)

if !vr.IsEmpty() {
t.Log(vr.Issues[0].Description)
t.Errorf("imports with valid contains subject should be valid")
}

activation.Exports[0].Subject = "two"
activation.Export.Subject = "two"
actJWT = encode(activation, ak2, t)
i.Token = actJWT
vr = CreateValidationResults()
i.Validate(akp, vr)

if vr.IsEmpty() {
if !vr.IsEmpty() {
t.Errorf("imports with non-contains subject should be not valid")
}

activation.Exports[0].Subject = ">"
activation.Export.Subject = ">"
actJWT = encode(activation, ak2, t)
i.Token = actJWT
vr = CreateValidationResults()
Expand Down