diff --git a/authority/authorize_test.go b/authority/authorize_test.go index e40047c8..05b6db34 100644 --- a/authority/authorize_test.go +++ b/authority/authorize_test.go @@ -7,24 +7,53 @@ import ( "github.com/pkg/errors" "github.com/smallstep/assert" - "github.com/smallstep/cli/crypto/keys" - stepJOSE "github.com/smallstep/cli/jose" - jose "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" + "github.com/smallstep/cli/crypto/randutil" + "github.com/smallstep/cli/jose" ) +func generateToken(sub, iss, aud string, sans []string, iat time.Time, jwk *jose.JSONWebKey) (string, error) { + sig, err := jose.NewSigner( + jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, + new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID), + ) + if err != nil { + return "", err + } + + id, err := randutil.ASCII(64) + if err != nil { + return "", err + } + + claims := struct { + jose.Claims + SANS []string `json:"sans"` + }{ + Claims: jose.Claims{ + ID: id, + Subject: sub, + Issuer: iss, + IssuedAt: jose.NewNumericDate(iat), + NotBefore: jose.NewNumericDate(iat), + Expiry: jose.NewNumericDate(iat.Add(5 * time.Minute)), + Audience: []string{aud}, + }, + SANS: sans, + } + return jose.Signed(sig).Claims(claims).CompactSerialize() +} + func TestAuthorize(t *testing.T) { a := testAuthority(t) - jwk, err := stepJOSE.ParseKey("testdata/secrets/step_cli_key_priv.jwk", - stepJOSE.WithPassword([]byte("pass"))) - assert.FatalError(t, err) - - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, - (&jose.SignerOptions{}).WithType("JWT").WithHeader("kid", jwk.KeyID)) - assert.FatalError(t, err) - + time.Sleep(time.Second) now := time.Now() + key, err := jose.ParseKey("testdata/secrets/step_cli_key_priv.jwk", jose.WithPassword([]byte("pass"))) + assert.FatalError(t, err) + // Invalid keys + keyNoKid := &jose.JSONWebKey{Key: key.Key, KeyID: ""} + keyBadKid := &jose.JSONWebKey{Key: key.Key, KeyID: "foo"} + validIssuer := "step-cli" validAudience := []string{"https://test.ca.smallstep.com/sign"} @@ -44,18 +73,7 @@ func TestAuthorize(t *testing.T) { } }, "fail empty key id": func(t *testing.T) *authorizeTest { - _sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, - (&jose.SignerOptions{}).WithType("JWT")) - assert.FatalError(t, err) - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - ID: "43", - } - raw, err := jwt.Signed(_sig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", validIssuer, validAudience[0], nil, now, keyNoKid) assert.FatalError(t, err) return &authorizeTest{ auth: a, @@ -65,19 +83,7 @@ func TestAuthorize(t *testing.T) { } }, "fail provisioner not found": func(t *testing.T) *authorizeTest { - _sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, - (&jose.SignerOptions{}).WithType("JWT").WithHeader("kid", "foo")) - assert.FatalError(t, err) - - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - ID: "43", - } - raw, err := jwt.Signed(_sig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", validIssuer, validAudience[0], nil, now, keyBadKid) assert.FatalError(t, err) return &authorizeTest{ auth: a, @@ -86,41 +92,8 @@ func TestAuthorize(t *testing.T) { http.StatusUnauthorized, context{"ott": raw}}, } }, - "fail invalid provisioner": func(t *testing.T) *authorizeTest { - _a := testAuthority(t) - - _sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, - (&jose.SignerOptions{}).WithType("JWT").WithHeader("kid", "foo")) - assert.FatalError(t, err) - - // _a.provisioners.Store(validIssuer+":foo", "42") - - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - ID: "43", - } - raw, err := jwt.Signed(_sig).Claims(cl).CompactSerialize() - assert.FatalError(t, err) - return &authorizeTest{ - auth: _a, - ott: raw, - err: &apiError{errors.New("authorize: provisioner not found or invalid audience"), - http.StatusUnauthorized, context{"ott": raw}}, - } - }, "fail invalid issuer": func(t *testing.T) *authorizeTest { - cl := jwt.Claims{ - Subject: "subject", - Issuer: "invalid-issuer", - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - } - raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", "invalid-issuer", validAudience[0], nil, now, key) assert.FatalError(t, err) return &authorizeTest{ auth: a, @@ -130,14 +103,7 @@ func TestAuthorize(t *testing.T) { } }, "fail empty subject": func(t *testing.T) *authorizeTest { - cl := jwt.Claims{ - Subject: "", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - } - raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() + raw, err := generateToken("", validIssuer, validAudience[0], nil, now, key) assert.FatalError(t, err) return &authorizeTest{ auth: a, @@ -147,39 +113,17 @@ func TestAuthorize(t *testing.T) { } }, "fail verify-sig-failure": func(t *testing.T) *authorizeTest { - _, priv2, err := keys.GenerateDefaultKeyPair() - assert.FatalError(t, err) - invalidKeySig, err := jose.NewSigner(jose.SigningKey{ - Algorithm: jose.ES256, - Key: priv2, - }, (&jose.SignerOptions{}).WithType("JWT").WithHeader("kid", jwk.KeyID)) - assert.FatalError(t, err) - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - } - raw, err := jwt.Signed(invalidKeySig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", validIssuer, validAudience[0], nil, now, key) assert.FatalError(t, err) return &authorizeTest{ auth: a, - ott: raw, + ott: raw + "00", err: &apiError{errors.New("authorize: error parsing claims: square/go-jose: error in cryptographic primitive"), - http.StatusUnauthorized, context{"ott": raw}}, + http.StatusUnauthorized, context{"ott": raw + "00"}}, } }, "fail token-already-used": func(t *testing.T) *authorizeTest { - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - ID: "42", - } - raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", validIssuer, validAudience[0], nil, now, key) assert.FatalError(t, err) _, err = a.Authorize(raw) assert.FatalError(t, err) @@ -191,15 +135,7 @@ func TestAuthorize(t *testing.T) { } }, "ok": func(t *testing.T) *authorizeTest { - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: validIssuer, - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAudience, - ID: "43", - } - raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() + raw, err := generateToken("test.smallstep.com", validIssuer, validAudience[0], nil, now, key) assert.FatalError(t, err) return &authorizeTest{ auth: a,