Skip to content

Commit

Permalink
config: allow HTTP client to specify claims
Browse files Browse the repository at this point in the history
Before this commit, the client unconditionally created JWTs with a fixed
issuer claim.

With this commit, the caller is expected to fill in the claims they want
for every outgoing request.

Signed-off-by: Hank Donnay <hdonnay@redhat.com>
  • Loading branch information
hdonnay committed Oct 2, 2020
1 parent d105283 commit a4e0410
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
3 changes: 2 additions & 1 deletion cmd/clairctl/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/quay/claircore/updater"
_ "github.com/quay/claircore/updater/defaults"
"github.com/urfave/cli/v2"
"gopkg.in/square/go-jose.v2/jwt"
)

// ExportCmd is the "export-updaters" subcommand.
Expand Down Expand Up @@ -70,7 +71,7 @@ func exportAction(c *cli.Context) error {
cfgs[name] = node.Decode
}

cl, _, err := cfg.Client(nil)
cl, _, err := cfg.Client(nil, jwt.Claims{})
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/clairctl/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/jackc/pgx/v4/pgxpool"
"github.com/quay/claircore/libvuln"
"github.com/urfave/cli/v2"
"gopkg.in/square/go-jose.v2/jwt"
)

// ImportCmd is the "import-updaters" subcommand.
Expand Down Expand Up @@ -39,7 +40,7 @@ func importAction(c *cli.Context) error {
return err
}

cl, _, err := cfg.Client(nil)
cl, _, err := cfg.Client(nil, jwt.Claims{})
if err != nil {
return err
}
Expand Down
19 changes: 10 additions & 9 deletions config/httpclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
//
// It returns an *http.Client and a boolean indicating whether the client is
// configured for authentication, or an error that occurred during construction.
func (cfg *Config) Client(next *http.Transport) (c *http.Client, authed bool, err error) {
func (cfg *Config) Client(next *http.Transport, cl jwt.Claims) (c *http.Client, authed bool, err error) {
if next == nil {
next = http.DefaultTransport.(*http.Transport).Clone()
}
Expand All @@ -29,7 +29,10 @@ func (cfg *Config) Client(next *http.Transport) (c *http.Client, authed bool, er
sk.Key = cfg.Auth.PSK.Key
default:
}
rt := &transport{next: next}
rt := &transport{
next: next,
base: cl,
}
c = &http.Client{Transport: rt}

// Both of the JWT-based methods set the signing key.
Expand All @@ -50,24 +53,22 @@ var _ http.RoundTripper = (*transport)(nil)
type transport struct {
jose.Signer
next http.RoundTripper
base jwt.Claims
}

func (cs *transport) RoundTrip(r *http.Request) (*http.Response, error) {
const (
issuer = `clair-intraservice`
userAgent = `clair/v4`
)
r.Header.Set("user-agent", userAgent)
if cs.Signer != nil {
// TODO(hank) Make this mint longer-lived tokens and re-use them, only
// refreshing when needed. Like a resettable sync.Once.
now := time.Now()
cl := jwt.Claims{
IssuedAt: jwt.NewNumericDate(now),
NotBefore: jwt.NewNumericDate(now.Add(-jwt.DefaultLeeway)),
Expiry: jwt.NewNumericDate(now.Add(jwt.DefaultLeeway)),
Issuer: issuer,
}
cl := cs.base
cl.IssuedAt = jwt.NewNumericDate(now)
cl.NotBefore = jwt.NewNumericDate(now.Add(-jwt.DefaultLeeway))
cl.Expiry = jwt.NewNumericDate(now.Add(jwt.DefaultLeeway))
h, err := jwt.Signed(cs).Claims(&cl).CompactSerialize()
if err != nil {
return nil, err
Expand Down
26 changes: 25 additions & 1 deletion httptransport/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"net/http/httptest"
"testing"

"gopkg.in/square/go-jose.v2/jwt"

"github.com/quay/clair/v4/config"
)

Expand All @@ -18,6 +20,11 @@ type authTestcase struct {
Config config.Config
ShouldFail bool
ConfigMod func(*testing.T, *config.Config)
Claims *jwt.Claims
}

var defaultClaims = jwt.Claims{
Issuer: IntraserviceIssuer,
}

func (tc *authTestcase) Run(t *testing.T) {
Expand Down Expand Up @@ -51,8 +58,13 @@ func (tc *authTestcase) Run(t *testing.T) {
f(t, &tc.Config)
}

// Use a default intraservice claim if not set.
if tc.Claims == nil {
tc.Claims = &defaultClaims
}

// Create a client that has auth according to the config.
c, authed, err := tc.Config.Client(nil)
c, authed, err := tc.Config.Client(nil, *tc.Claims)
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -101,6 +113,18 @@ func TestAuth(t *testing.T) {
},
},
},
{
Name: "PSKMultipleIssuer",
Config: config.Config{
Auth: config.Auth{
PSK: &config.AuthPSK{
Issuer: []string{`sweet-bro`, `hella-jeff`, `geromy`},
Key: fakeKey,
},
},
},
Claims: &jwt.Claims{Issuer: `geromy`},
},
{
Name: "FakeKeyserver",
Config: config.Config{
Expand Down
10 changes: 7 additions & 3 deletions initialize/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import (
"fmt"
"time"

notifier "github.com/quay/clair/v4/notifier/service"
"github.com/quay/claircore/libindex"
"github.com/quay/claircore/libvuln"
"github.com/quay/claircore/libvuln/driver"
"github.com/rs/zerolog"
"gopkg.in/square/go-jose.v2/jwt"

clairerror "github.com/quay/clair/v4/clair-error"
"github.com/quay/clair/v4/config"
"github.com/quay/clair/v4/httptransport"
"github.com/quay/clair/v4/httptransport/client"
notifier "github.com/quay/clair/v4/notifier/service"
)

const (
Expand Down Expand Up @@ -170,7 +172,7 @@ func (i *Init) Services() error {
return fmt.Errorf("failed to initialize libvuln: %v", err)
}
// matcher mode needs a remote indexer client
c, auth, err := i.conf.Client(nil)
c, auth, err := i.conf.Client(nil, intraservice)
switch {
case err != nil:
return err
Expand All @@ -190,7 +192,7 @@ func (i *Init) Services() error {
i.Matcher = libV
case config.NotifierMode:
// notifier uses a remote indexer and matcher
c, auth, err := i.conf.Client(nil)
c, auth, err := i.conf.Client(nil, intraservice)
switch {
case err != nil:
return err
Expand Down Expand Up @@ -254,3 +256,5 @@ func (i *Init) Services() error {

return nil
}

var intraservice = jwt.Claims{Issuer: httptransport.IntraserviceIssuer}

0 comments on commit a4e0410

Please sign in to comment.