|
|
|
@ -4,14 +4,10 @@ import (
|
|
|
|
|
"crypto"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"net/http"
|
|
|
|
|
"net/http/httptest"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/smallstep/cli/crypto/randutil"
|
|
|
|
|
"github.com/smallstep/cli/jose"
|
|
|
|
|
"github.com/smallstep/cli/token"
|
|
|
|
|
"github.com/smallstep/cli/token/provision"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var testAudiences = []string{
|
|
|
|
@ -210,90 +206,3 @@ func generateToken(sub, iss, aud string, sans []string, jwk *jose.JSONWebKey) (s
|
|
|
|
|
}
|
|
|
|
|
return jose.Signed(sig).Claims(claims).CompactSerialize()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func generateToken2(sub string, sans []string, kid, iss, aud, root string, notBefore, notAfter time.Time, jwk *jose.JSONWebKey) (string, error) {
|
|
|
|
|
// A random jwt id will be used to identify duplicated tokens
|
|
|
|
|
jwtID, err := randutil.Hex(64) // 256 bits
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tokOptions := []token.Options{
|
|
|
|
|
token.WithJWTID(jwtID),
|
|
|
|
|
token.WithKid(kid),
|
|
|
|
|
token.WithIssuer(iss),
|
|
|
|
|
token.WithAudience(aud),
|
|
|
|
|
}
|
|
|
|
|
if len(root) > 0 {
|
|
|
|
|
tokOptions = append(tokOptions, token.WithRootCA(root))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there are no SANs then add the 'subject' (common-name) as the only SAN.
|
|
|
|
|
if len(sans) == 0 {
|
|
|
|
|
sans = []string{sub}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tokOptions = append(tokOptions, token.WithSANS(sans))
|
|
|
|
|
if !notBefore.IsZero() || !notAfter.IsZero() {
|
|
|
|
|
if notBefore.IsZero() {
|
|
|
|
|
notBefore = time.Now()
|
|
|
|
|
}
|
|
|
|
|
if notAfter.IsZero() {
|
|
|
|
|
notAfter = notBefore.Add(token.DefaultValidity)
|
|
|
|
|
}
|
|
|
|
|
tokOptions = append(tokOptions, token.WithValidity(notBefore, notAfter))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tok, err := provision.New(sub, tokOptions...)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tok.SignedString(jwk.Algorithm, jwk.Key)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseToken(token string) (*jose.JSONWebToken, *jose.Claims, error) {
|
|
|
|
|
tok, err := jose.ParseSigned(token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, err
|
|
|
|
|
}
|
|
|
|
|
claims := new(jose.Claims)
|
|
|
|
|
if err := tok.UnsafeClaimsWithoutVerification(claims); err != nil {
|
|
|
|
|
return nil, nil, err
|
|
|
|
|
}
|
|
|
|
|
return tok, claims, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func generateJWKServer(n int) *httptest.Server {
|
|
|
|
|
hits := struct {
|
|
|
|
|
Hits int `json:"hits"`
|
|
|
|
|
}{}
|
|
|
|
|
writeJSON := func(w http.ResponseWriter, v interface{}) {
|
|
|
|
|
b, err := json.Marshal(v)
|
|
|
|
|
if err != nil {
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
w.Header().Add("Content-Type", "application/json")
|
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
|
w.Write(b)
|
|
|
|
|
}
|
|
|
|
|
// keySet, err := generateJSONWebKeySet(n)
|
|
|
|
|
defaultKeySet := must(generateJSONWebKeySet(2))[0].(jose.JSONWebKeySet)
|
|
|
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
hits.Hits++
|
|
|
|
|
switch r.RequestURI {
|
|
|
|
|
case "/error":
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
|
|
|
case "/hits":
|
|
|
|
|
writeJSON(w, hits)
|
|
|
|
|
case "/random":
|
|
|
|
|
keySet := must(generateJSONWebKeySet(2))[0].(jose.JSONWebKeySet)
|
|
|
|
|
w.Header().Add("Cache-Control", "max-age=5")
|
|
|
|
|
writeJSON(w, keySet)
|
|
|
|
|
default:
|
|
|
|
|
w.Header().Add("Cache-Control", "max-age=5")
|
|
|
|
|
writeJSON(w, defaultKeySet)
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|