mirror of
https://github.com/goharbor/harbor
synced 2024-09-20 23:59:56 +00:00
token expires
This commit is contained in:
parent
fbe341bf5d
commit
545ca4135c
|
@ -108,7 +108,7 @@ func FilterAccess(username string, authenticated bool, a *token.ResourceActions)
|
|||
}
|
||||
|
||||
// GenTokenForUI is for the UI process to call, so it won't establish a https connection from UI to proxy.
|
||||
func GenTokenForUI(username string, service string, scopes []string) (string, error) {
|
||||
func GenTokenForUI(username string, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) {
|
||||
access := GetResourceActions(scopes)
|
||||
for _, a := range access {
|
||||
FilterAccess(username, true, a)
|
||||
|
@ -117,22 +117,22 @@ func GenTokenForUI(username string, service string, scopes []string) (string, er
|
|||
}
|
||||
|
||||
// MakeToken makes a valid jwt token based on parms.
|
||||
func MakeToken(username, service string, access []*token.ResourceActions) (string, error) {
|
||||
func MakeToken(username, service string, access []*token.ResourceActions) (token string, expiresIn int, issuedAt *time.Time, err error) {
|
||||
pk, err := libtrust.LoadKeyFile(privateKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", 0, nil, err
|
||||
}
|
||||
tk, err := makeTokenCore(issuer, username, service, expiration, access, pk)
|
||||
tk, expiresIn, issuedAt, err := makeTokenCore(issuer, username, service, expiration, access, pk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", 0, nil, err
|
||||
}
|
||||
rs := fmt.Sprintf("%s.%s", tk.Raw, base64UrlEncode(tk.Signature))
|
||||
return rs, nil
|
||||
return rs, expiresIn, issuedAt, nil
|
||||
}
|
||||
|
||||
//make token core
|
||||
func makeTokenCore(issuer, subject, audience string, expiration int,
|
||||
access []*token.ResourceActions, signingKey libtrust.PrivateKey) (*token.Token, error) {
|
||||
access []*token.ResourceActions, signingKey libtrust.PrivateKey) (t *token.Token, expiresIn int, issuedAt *time.Time, err error) {
|
||||
|
||||
joseHeader := &token.Header{
|
||||
Type: "JWT",
|
||||
|
@ -142,10 +142,12 @@ func makeTokenCore(issuer, subject, audience string, expiration int,
|
|||
|
||||
jwtID, err := randString(16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error to generate jwt id: %s", err)
|
||||
return nil, 0, nil, fmt.Errorf("Error to generate jwt id: %s", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
now := time.Now().UTC()
|
||||
issuedAt = &now
|
||||
expiresIn = expiration * 60
|
||||
|
||||
claimSet := &token.ClaimSet{
|
||||
Issuer: issuer,
|
||||
|
@ -161,10 +163,10 @@ func makeTokenCore(issuer, subject, audience string, expiration int,
|
|||
var joseHeaderBytes, claimSetBytes []byte
|
||||
|
||||
if joseHeaderBytes, err = json.Marshal(joseHeader); err != nil {
|
||||
return nil, fmt.Errorf("unable to marshal jose header: %s", err)
|
||||
return nil, 0, nil, fmt.Errorf("unable to marshal jose header: %s", err)
|
||||
}
|
||||
if claimSetBytes, err = json.Marshal(claimSet); err != nil {
|
||||
return nil, fmt.Errorf("unable to marshal claim set: %s", err)
|
||||
return nil, 0, nil, fmt.Errorf("unable to marshal claim set: %s", err)
|
||||
}
|
||||
|
||||
encodedJoseHeader := base64UrlEncode(joseHeaderBytes)
|
||||
|
@ -173,12 +175,13 @@ func makeTokenCore(issuer, subject, audience string, expiration int,
|
|||
|
||||
var signatureBytes []byte
|
||||
if signatureBytes, _, err = signingKey.Sign(strings.NewReader(payload), crypto.SHA256); err != nil {
|
||||
return nil, fmt.Errorf("unable to sign jwt payload: %s", err)
|
||||
return nil, 0, nil, fmt.Errorf("unable to sign jwt payload: %s", err)
|
||||
}
|
||||
|
||||
signature := base64UrlEncode(signatureBytes)
|
||||
tokenString := fmt.Sprintf("%s.%s", payload, signature)
|
||||
return token.NewToken(tokenString)
|
||||
t, err = token.NewToken(tokenString)
|
||||
return
|
||||
}
|
||||
|
||||
func randString(length int) (string, error) {
|
||||
|
|
|
@ -17,6 +17,7 @@ package token
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/harbor/auth"
|
||||
"github.com/vmware/harbor/models"
|
||||
|
@ -59,14 +60,16 @@ func (h *Handler) Get() {
|
|||
func (h *Handler) serveToken(username, service string, access []*token.ResourceActions) {
|
||||
writer := h.Ctx.ResponseWriter
|
||||
//create token
|
||||
rawToken, err := MakeToken(username, service, access)
|
||||
rawToken, expiresIn, issuedAt, err := MakeToken(username, service, access)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to make token, error: %v", err)
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
tk := make(map[string]string)
|
||||
tk := make(map[string]interface{})
|
||||
tk["token"] = rawToken
|
||||
tk["expires_in"] = expiresIn
|
||||
tk["issued_at"] = issuedAt.Format(time.RFC3339)
|
||||
h.Data["json"] = tk
|
||||
h.ServeJSON()
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ type Handler interface {
|
|||
AuthorizeRequest(req *http.Request, params map[string]string) error
|
||||
}
|
||||
|
||||
// RequestAuthorizer holds a handler list, which will authorize request
|
||||
// RequestAuthorizer holds a handler list, which will authorize request.
|
||||
// Implements interface RequestModifier
|
||||
type RequestAuthorizer struct {
|
||||
handlers []Handler
|
||||
challenges []au.Challenge
|
||||
|
|
|
@ -25,6 +25,7 @@ type Credential interface {
|
|||
AddAuthorization(req *http.Request)
|
||||
}
|
||||
|
||||
// Implements interface Credential
|
||||
type basicAuthCredential struct {
|
||||
username string
|
||||
password string
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -41,6 +42,7 @@ func (s *scope) string() string {
|
|||
|
||||
type tokenGenerator func(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error)
|
||||
|
||||
// Implements interface Handler
|
||||
type tokenHandler struct {
|
||||
scope *scope
|
||||
tg tokenGenerator
|
||||
|
@ -92,6 +94,7 @@ func (t *tokenHandler) AuthorizeRequest(req *http.Request, params map[string]str
|
|||
return nil
|
||||
}
|
||||
|
||||
// Implements interface Handler
|
||||
type standardTokenHandler struct {
|
||||
tokenHandler
|
||||
client *http.Client
|
||||
|
@ -119,10 +122,10 @@ func NewStandardTokenHandler(credential Credential, scopeType, scopeName string,
|
|||
return handler
|
||||
}
|
||||
|
||||
func (s *standardTokenHandler) generateToken(realm, service string, scopes []string) (string, int, *time.Time, error) {
|
||||
func (s *standardTokenHandler) generateToken(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) {
|
||||
u, err := url.Parse(realm)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
return
|
||||
}
|
||||
q := u.Query()
|
||||
q.Add("service", service)
|
||||
|
@ -132,41 +135,61 @@ func (s *standardTokenHandler) generateToken(realm, service string, scopes []str
|
|||
u.RawQuery = q.Encode()
|
||||
r, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
return
|
||||
}
|
||||
|
||||
s.credential.AddAuthorization(r)
|
||||
|
||||
resp, err := s.client.Do(r)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
return
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", 0, nil, registry_errors.Error{
|
||||
err = registry_errors.Error{
|
||||
StatusCode: resp.StatusCode,
|
||||
Message: string(b),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TODO
|
||||
tk := struct {
|
||||
Token string `json:"token"`
|
||||
Token string `json:"token"`
|
||||
ExpiresIn string `json:"expires_in"`
|
||||
IssuedAt string `json:"issued_at"`
|
||||
}{}
|
||||
if err = json.Unmarshal(b, &tk); err != nil {
|
||||
return "", 0, nil, err
|
||||
return
|
||||
}
|
||||
|
||||
token = tk.Token
|
||||
|
||||
expiresIn, err = strconv.Atoi(tk.ExpiresIn)
|
||||
if err != nil {
|
||||
expiresIn = 0
|
||||
log.Errorf("error occurred while converting expires_in: %v", err)
|
||||
err = nil
|
||||
} else {
|
||||
t, err := time.Parse(time.RFC3339, tk.IssuedAt)
|
||||
if err != nil {
|
||||
log.Errorf("error occurred while parsing issued_at: %v", err)
|
||||
err = nil
|
||||
} else {
|
||||
issuedAt = &t
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("get token from token server")
|
||||
|
||||
return tk.Token, 0, nil, nil
|
||||
return
|
||||
}
|
||||
|
||||
// Implements interface Handler
|
||||
type usernameTokenHandler struct {
|
||||
tokenHandler
|
||||
username string
|
||||
|
@ -192,7 +215,7 @@ func NewUsernameTokenHandler(username string, scopeType, scopeName string, scope
|
|||
|
||||
func (u *usernameTokenHandler) generateToken(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) {
|
||||
// TODO
|
||||
token, err = token_util.GenTokenForUI(u.username, service, scopes)
|
||||
token, expiresIn, issuedAt, err = token_util.GenTokenForUI(u.username, service, scopes)
|
||||
log.Debug("get token by calling GenTokenForUI directly")
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user