mirror of
https://github.com/goharbor/harbor.git
synced 2025-01-03 14:37:44 +01:00
token request posted to token service directly
This commit is contained in:
parent
61a888926e
commit
5fbe2c1a72
@ -16,14 +16,10 @@
|
||||
package replication
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/harbor/models"
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
"github.com/vmware/harbor/utils/registry"
|
||||
"github.com/vmware/harbor/utils/registry/auth"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -42,11 +38,20 @@ type Deleter struct {
|
||||
|
||||
insecure bool
|
||||
|
||||
dstClient *registry.Repository
|
||||
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// NewDeleter returns a Deleter
|
||||
func NewDeleter(repository string, tags []string, dstURL, dstUsr, dstPwd string, insecure bool, logger *log.Logger) *Deleter {
|
||||
func NewDeleter(repository string, tags []string, dstURL, dstUsr, dstPwd string, insecure bool, logger *log.Logger) (*Deleter, error) {
|
||||
dstCred := auth.NewBasicAuthCredential(dstUsr, dstPwd)
|
||||
dstClient, err := newRepositoryClient(dstURL, insecure, dstCred,
|
||||
repository, "repository", repository, "pull", "push", "*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deleter := &Deleter{
|
||||
repository: repository,
|
||||
tags: tags,
|
||||
@ -54,11 +59,12 @@ func NewDeleter(repository string, tags []string, dstURL, dstUsr, dstPwd string,
|
||||
dstUsr: dstUsr,
|
||||
dstPwd: dstPwd,
|
||||
insecure: insecure,
|
||||
dstClient: dstClient,
|
||||
logger: logger,
|
||||
}
|
||||
deleter.logger.Infof("initialization completed: repository: %s, tags: %v, destination URL: %s, destination user: %s",
|
||||
deleter.repository, deleter.tags, deleter.dstURL, deleter.dstUsr)
|
||||
return deleter
|
||||
return deleter, nil
|
||||
}
|
||||
|
||||
// Exit ...
|
||||
@ -68,25 +74,22 @@ func (d *Deleter) Exit() error {
|
||||
|
||||
// Enter deletes repository or tags
|
||||
func (d *Deleter) Enter() (string, error) {
|
||||
url := strings.TrimRight(d.dstURL, "/") + "/api/repositories/"
|
||||
|
||||
// delete repository
|
||||
if len(d.tags) == 0 {
|
||||
u := url + "?repo_name=" + d.repository
|
||||
if err := del(u, d.dstUsr, d.dstPwd, d.insecure); err != nil {
|
||||
d.logger.Errorf("an error occurred while deleting repository %s on %s with user %s: %v", d.repository, d.dstURL, d.dstUsr, err)
|
||||
tags, err := d.dstClient.ListTag()
|
||||
if err != nil {
|
||||
d.logger.Errorf("an error occurred while listing tags of repository %s on %s with user %s: %v", d.repository, d.dstURL, d.dstUsr, err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
d.logger.Infof("repository %s on %s has been deleted", d.repository, d.dstURL)
|
||||
|
||||
return models.JobFinished, nil
|
||||
d.tags = append(d.tags, tags...)
|
||||
}
|
||||
|
||||
// delele tags
|
||||
d.logger.Infof("tags %v will be deleted", d.tags)
|
||||
|
||||
for _, tag := range d.tags {
|
||||
u := url + "?repo_name=" + d.repository + "&tag=" + tag
|
||||
if err := del(u, d.dstUsr, d.dstPwd, d.insecure); err != nil {
|
||||
|
||||
if err := d.dstClient.DeleteTag(tag); err != nil {
|
||||
d.logger.Errorf("an error occurred while deleting repository %s:%s on %s with user %s: %v", d.repository, tag, d.dstURL, d.dstUsr, err)
|
||||
return "", err
|
||||
}
|
||||
@ -96,37 +99,3 @@ func (d *Deleter) Enter() (string, error) {
|
||||
|
||||
return models.JobFinished, nil
|
||||
}
|
||||
|
||||
func del(url, username, password string, insecure bool) error {
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(username, password)
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: insecure,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("%d %s", resp.StatusCode, string(b))
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ func newRepositoryClient(endpoint string, insecure bool, credential auth.Credent
|
||||
}
|
||||
|
||||
uam := &userAgentModifier{
|
||||
userAgent: "registry-client",
|
||||
userAgent: "harbor-registry-client",
|
||||
}
|
||||
|
||||
client, err := registry.NewRepositoryWithModifiers(repository, endpoint, insecure, store, uam)
|
||||
|
@ -260,12 +260,9 @@ func (sm *SM) Reset(jid int64) error {
|
||||
}
|
||||
|
||||
func addImgTransferTransition(sm *SM) error {
|
||||
// TODO read variable from config file
|
||||
insecure := true
|
||||
|
||||
base, err := replication.InitBaseHandler(sm.Parms.Repository, sm.Parms.LocalRegURL, config.UISecret(),
|
||||
sm.Parms.TargetURL, sm.Parms.TargetUsername, sm.Parms.TargetPassword,
|
||||
insecure, sm.Parms.Tags, sm.Logger)
|
||||
sm.Parms.Insecure, sm.Parms.Tags, sm.Logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -279,10 +276,11 @@ func addImgTransferTransition(sm *SM) error {
|
||||
}
|
||||
|
||||
func addImgDeleteTransition(sm *SM) error {
|
||||
// TODO read variable from config file
|
||||
insecure := true
|
||||
deleter := replication.NewDeleter(sm.Parms.Repository, sm.Parms.Tags, sm.Parms.TargetURL,
|
||||
sm.Parms.TargetUsername, sm.Parms.TargetPassword, insecure, sm.Logger)
|
||||
deleter, err := replication.NewDeleter(sm.Parms.Repository, sm.Parms.Tags, sm.Parms.TargetURL,
|
||||
sm.Parms.TargetUsername, sm.Parms.TargetPassword, sm.Parms.Insecure, sm.Logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sm.AddTransition(models.JobRunning, replication.StateDelete, deleter)
|
||||
sm.AddTransition(replication.StateDelete, models.JobFinished, &StatusUpdater{DummyHandler{JobID: sm.JobID}, models.JobFinished})
|
||||
|
@ -56,7 +56,7 @@ func (n *NotificationHandler) Post() {
|
||||
matched = false
|
||||
}
|
||||
if matched && (strings.HasPrefix(e.Request.UserAgent, "docker") ||
|
||||
strings.ToLower(strings.TrimSpace(e.Request.UserAgent)) == "registry-client") {
|
||||
strings.ToLower(strings.TrimSpace(e.Request.UserAgent)) == "harbor-registry-client") {
|
||||
username = e.Actor.Name
|
||||
action = e.Action
|
||||
repo = e.Target.Repository
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -162,6 +163,8 @@ func NewStandardTokenAuthorizer(credential Credential, insecure bool, scopeType,
|
||||
}
|
||||
|
||||
func (s *standardTokenAuthorizer) generateToken(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) {
|
||||
realm = tokenURL(realm)
|
||||
|
||||
u, err := url.Parse(realm)
|
||||
if err != nil {
|
||||
return
|
||||
@ -223,6 +226,22 @@ func (s *standardTokenAuthorizer) generateToken(realm, service string, scopes []
|
||||
return
|
||||
}
|
||||
|
||||
// when the registry client is used inside Harbor, the token request
|
||||
// can be posted to token service directly rather than going through nginx.
|
||||
// this solution can resolve two problems:
|
||||
// 1. performance issue
|
||||
// 2. the realm field returned by registry is an IP which can not reachable
|
||||
// inside Harbor
|
||||
func tokenURL(realm string) string {
|
||||
extEndpoint := os.Getenv("EXT_ENDPOINT")
|
||||
tokenURL := os.Getenv("TOKEN_URL")
|
||||
if len(extEndpoint) != 0 && len(tokenURL) != 0 &&
|
||||
strings.Contains(realm, extEndpoint) {
|
||||
realm = strings.TrimRight(tokenURL, "/") + "/service/token"
|
||||
}
|
||||
return realm
|
||||
}
|
||||
|
||||
// Implements interface Handler
|
||||
type usernameTokenAuthorizer struct {
|
||||
tokenAuthorizer
|
||||
|
Loading…
Reference in New Issue
Block a user