Skip to content

Commit

Permalink
Backport v1 codetree from v2.3.0 to v1.2.3
Browse files Browse the repository at this point in the history
Signed-off-by: Waldemar Quevedo <wally@nats.io>
  • Loading branch information
wallyqs committed Jan 20, 2023
1 parent 0ea3265 commit 0dd8184
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 113 deletions.
5 changes: 2 additions & 3 deletions account_claims_test.go
Expand Up @@ -16,7 +16,6 @@
package jwt

import (
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -165,7 +164,7 @@ func TestInvalidAccountClaimIssuer(t *testing.T) {
bad := encode(temp, i.kp, t)
_, err = DecodeAccountClaims(bad)
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to decode account signed by %q", i.name)
Expand Down Expand Up @@ -199,7 +198,7 @@ func TestInvalidAccountSubjects(t *testing.T) {
}
_, err = c.Encode(i.kp)
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to encode account with with %q subject", i.name)
Expand Down
9 changes: 8 additions & 1 deletion activation_claims.go
Expand Up @@ -102,7 +102,14 @@ func (a *ActivationClaims) Payload() interface{} {

// Validate checks the claims
func (a *ActivationClaims) Validate(vr *ValidationResults) {
a.ClaimsData.Validate(vr)
a.validateWithTimeChecks(vr, true)
}

// Validate checks the claims
func (a *ActivationClaims) validateWithTimeChecks(vr *ValidationResults, timeChecks bool) {
if timeChecks {
a.ClaimsData.Validate(vr)
}
a.Activation.Validate(vr)
if a.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(a.IssuerAccount) {
vr.AddError("account_id is not an account public key")
Expand Down
5 changes: 2 additions & 3 deletions activation_claims_test.go
Expand Up @@ -16,7 +16,6 @@
package jwt

import (
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -78,7 +77,7 @@ func TestInvalidActivationTargets(t *testing.T) {
c := NewActivationClaims(publicKey(i.kp, t))
_, err := c.Encode(createOperatorNKey(t))
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to encode user with with %q subject", i.name)
Expand Down Expand Up @@ -116,7 +115,7 @@ func TestInvalidActivationClaimIssuer(t *testing.T) {
bad := encode(temp, i.kp, t)
_, err = DecodeActivationClaims(bad)
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to decode account signed by %q", i.name)
Expand Down
5 changes: 2 additions & 3 deletions cluster_claims_test.go
Expand Up @@ -16,7 +16,6 @@
package jwt

import (
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -73,7 +72,7 @@ func TestClusterClaimsIssuer(t *testing.T) {
bad := encode(temp, i.kp, t)
_, err = DecodeClusterClaims(bad)
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to decode cluster signed by %q", i.name)
Expand Down Expand Up @@ -101,7 +100,7 @@ func TestClusterSubjects(t *testing.T) {
c := NewClusterClaims(publicKey(i.kp, t))
_, err := c.Encode(createOperatorNKey(t))
if i.ok && err != nil {
t.Fatal(fmt.Sprintf("unexpected error for %q: %v", i.name, err))
t.Fatalf("unexpected error for %q: %v", i.name, err)
}
if !i.ok && err == nil {
t.Logf("should have failed to encode cluster with with %q subject", i.name)
Expand Down
15 changes: 8 additions & 7 deletions creds_utils.go
Expand Up @@ -51,13 +51,14 @@ func formatJwt(kind string, jwtString string) ([]byte, error) {

// DecorateSeed takes a seed and returns a string that wraps
// the seed in the form:
// ************************* IMPORTANT *************************
// NKEY Seed printed below can be used sign and prove identity.
// NKEYs are sensitive and should be treated as secrets.
//
// -----BEGIN USER NKEY SEED-----
// SUAIO3FHUX5PNV2LQIIP7TZ3N4L7TX3W53MQGEIVYFIGA635OZCKEYHFLM
// ------END USER NKEY SEED------
// ************************* IMPORTANT *************************
// NKEY Seed printed below can be used sign and prove identity.
// NKEYs are sensitive and should be treated as secrets.
//
// -----BEGIN USER NKEY SEED-----
// SUAIO3FHUX5PNV2LQIIP7TZ3N4L7TX3W53MQGEIVYFIGA635OZCKEYHFLM
// ------END USER NKEY SEED------
func DecorateSeed(seed []byte) ([]byte, error) {
w := bytes.NewBuffer(nil)
ts := bytes.TrimSpace(seed)
Expand Down Expand Up @@ -97,7 +98,7 @@ NKEYs are sensitive and should be treated as secrets.
return w.Bytes(), nil
}

var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))`)
var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}(\r?\n|\z)))`)

// An user config file looks like this:
// -----BEGIN NATS USER JWT-----
Expand Down
24 changes: 12 additions & 12 deletions exports.go
Expand Up @@ -40,20 +40,20 @@ const (
// Results is the subject where the latency metrics are published.
// A metric will be defined by the nats-server's ServiceLatency. Time durations
// are in nanoseconds.
// see https://github.com/nats-io/nats-server/blob/master/server/accounts.go#L524
// see https://github.com/nats-io/nats-server/blob/main/server/accounts.go#L524
// e.g.
// {
// "app": "dlc22",
// "start": "2019-09-16T21:46:23.636869585-07:00",
// "svc": 219732,
// "nats": {
// "req": 320415,
// "resp": 228268,
// "sys": 0
// },
// "total": 768415
// }
//
// {
// "app": "dlc22",
// "start": "2019-09-16T21:46:23.636869585-07:00",
// "svc": 219732,
// "nats": {
// "req": 320415,
// "resp": 228268,
// "sys": 0
// },
// "total": 768415
// }
type ServiceLatency struct {
Sampling int `json:"sampling,omitempty"`
Results Subject `json:"results"`
Expand Down
6 changes: 4 additions & 2 deletions go.mod
@@ -1,5 +1,7 @@
module github.com/nats-io/jwt

require github.com/nats-io/nkeys v0.2.0
go 1.18

go 1.14
require github.com/nats-io/nkeys v0.3.0

require golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b // indirect
18 changes: 9 additions & 9 deletions go.sum
@@ -1,9 +1,9 @@
github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM=
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
41 changes: 24 additions & 17 deletions imports.go
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 The NATS Authors
* Copyright 2018-2022 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -16,7 +16,7 @@
package jwt

import (
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
Expand Down Expand Up @@ -62,7 +62,7 @@ func (i *Import) Validate(actPubKey string, vr *ValidationResults) {
}

if i.Account == "" {
vr.AddWarning("account to import from is not specified")
vr.AddError("account to import from is not specified")
}

i.Subject.Validate(vr)
Expand All @@ -78,46 +78,53 @@ func (i *Import) Validate(actPubKey string, vr *ValidationResults) {

if i.Token != "" {
// Check to see if its an embedded JWT or a URL.
if url, err := url.Parse(i.Token); err == nil && url.Scheme != "" {
if u, err := url.Parse(i.Token); err == nil && u.Scheme != "" {
c := &http.Client{Timeout: 5 * time.Second}
resp, err := c.Get(url.String())
resp, err := c.Get(u.String())
if err != nil {
vr.AddWarning("import %s contains an unreachable token URL %q", i.Subject, i.Token)
vr.AddError("import %s contains an unreachable token URL %q", i.Subject, i.Token)
}

if resp != nil {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
vr.AddWarning("import %s contains an unreadable token URL %q", i.Subject, i.Token)
vr.AddError("import %s contains an unreadable token URL %q", i.Subject, i.Token)
} else {
act, err = DecodeActivationClaims(string(body))
if err != nil {
vr.AddWarning("import %s contains a url %q with an invalid activation token", i.Subject, i.Token)
vr.AddError("import %s contains a URL %q with an invalid activation token", i.Subject, i.Token)
}
}
}
} else {
var err error
act, err = DecodeActivationClaims(i.Token)
if err != nil {
vr.AddWarning("import %q contains an invalid activation token", i.Subject)
vr.AddError("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 %q", i.Subject)
if !(act.Issuer == i.Account || act.IssuerAccount == i.Account) {
vr.AddError("activation token doesn't match account for import %q", i.Subject)
}

if act.ClaimsData.Subject != actPubKey {
vr.AddWarning("activation token doesn't match account it is being included in, %q", i.Subject)
vr.AddError("activation token doesn't match account it is being included in, %q", i.Subject)
}
if act.ImportType != i.Type {
vr.AddError("mismatch between token import type %s and type of import %s", act.ImportType, i.Type)
}
act.validateWithTimeChecks(vr, false)
subj := i.Subject
if i.IsService() && i.To != "" {
subj = i.To
}
if !subj.IsContainedIn(act.ImportSubject) {
vr.AddError("activation token import subject %q doesn't match import %q", act.ImportSubject, i.Subject)
}
} else {
vr.AddWarning("no activation provided for import %s", i.Subject)
}

}

// Imports is a list of import structs
Expand Down

0 comments on commit 0dd8184

Please sign in to comment.