Add a new authentiate method GIT_SYNC_AUTH_URL.
It specifies a HTTP URL which will return username&password which will be used to authenticate access to the git repo. This is mainly used for git repo accecpt dynamic password (for example oauth bare token). Because the dynamic password might expire very soon, so it's added to the main syncRepo loop. Typical usage case is work with a sidecar called gce-node-auth on GKE, it uses the GCE service account's oauth token as password to access Cloud Source Repo. Please see the repo below for how it worked. https://github.com/cydu-cloud/gce-node-auth/blob/master/git-sync-with-gce-node-auth.yaml
This commit is contained in:
parent
a2a8f72733
commit
9cae624f8c
|
|
@ -98,6 +98,9 @@ var flSSHKnownHostsFile = flag.String("ssh-known-hosts-file", envString("GIT_SSH
|
|||
var flCookieFile = flag.Bool("cookie-file", envBool("GIT_COOKIE_FILE", false),
|
||||
"use git cookiefile")
|
||||
|
||||
var flAuthURL = flag.String("auth-url", envString("GIT_SYNC_AUTH_URL", ""),
|
||||
"the URL for git auth callback")
|
||||
|
||||
var flGitCmd = flag.String("git", envString("GIT_SYNC_GIT", "git"),
|
||||
"the git command to run (subject to PATH search, mostly for testing)")
|
||||
|
||||
|
|
@ -233,8 +236,8 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
if (*flUsername != "" || *flPassword != "" || *flCookieFile) && *flSSH {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: --ssh is set but --username, --password, or --cookie-file were provided\n")
|
||||
if (*flUsername != "" || *flPassword != "" || *flCookieFile || *flAuthURL != "") && *flSSH {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: --ssh is set but --username, --password, --auth-url, or --cookie-file were provided\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -263,6 +266,13 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
if *flAuthURL != "" {
|
||||
if err := setupGitAuthURL(ctx); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: can't set auth callback url: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// The scope of the initialization context ends here, so we call cancel to release resources associated with it.
|
||||
cancel()
|
||||
|
||||
|
|
@ -315,7 +325,7 @@ func main() {
|
|||
for {
|
||||
start := time.Now()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(*flSyncTimeout))
|
||||
if changed, hash, err := syncRepo(ctx, *flRepo, *flBranch, *flRev, *flDepth, *flRoot, *flDest); err != nil {
|
||||
if changed, hash, err := syncRepo(ctx, *flRepo, *flBranch, *flRev, *flDepth, *flRoot, *flDest, *flAuthURL); err != nil {
|
||||
syncDuration.WithLabelValues("error").Observe(time.Since(start).Seconds())
|
||||
syncCount.WithLabelValues("error").Inc()
|
||||
if *flMaxSyncFailures != -1 && failCount >= *flMaxSyncFailures {
|
||||
|
|
@ -571,7 +581,15 @@ func revIsHash(ctx context.Context, rev, gitRoot string) (bool, error) {
|
|||
|
||||
// syncRepo syncs the branch of a given repository to the destination at the given rev.
|
||||
// returns (1) whether a change occured, (2) the new hash, and (3) an error if one happened
|
||||
func syncRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot, dest string) (bool, string, error) {
|
||||
func syncRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot, dest string, authUrl string) (bool, string, error) {
|
||||
if authUrl != "" {
|
||||
// For Auth Callback URL, the credentials behind is dynamic, it needs to be
|
||||
// re-fetched each time.
|
||||
if err := setupGitAuthURL(ctx); err != nil {
|
||||
return false, "", fmt.Errorf("can't set auth callback url: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
target := path.Join(gitRoot, dest)
|
||||
gitRepoPath := path.Join(target, ".git")
|
||||
var hash string
|
||||
|
|
@ -756,3 +774,54 @@ func setupGitCookieFile(ctx context.Context) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// The expected output of the auth URL are:
|
||||
// username=xxx@example.com
|
||||
// password=ya29.xxxyyyzzz
|
||||
func setupGitAuthURL(ctx context.Context) error {
|
||||
log.V(1).Info("configuring auth callback URL")
|
||||
|
||||
var netClient = &http.Client{
|
||||
Timeout: time.Second * 1,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "GET", *flAuthURL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error create auth request: %v", err)
|
||||
}
|
||||
resp, err := netClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error access auth url: %v", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("access auth url: %v", err)
|
||||
}
|
||||
authData, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error read auth response: %v", err)
|
||||
}
|
||||
|
||||
username := ""
|
||||
password := ""
|
||||
for _, line := range strings.Split(string(authData), "\n") {
|
||||
keyValues := strings.SplitN(line, "=", 2)
|
||||
if len(keyValues) != 2 {
|
||||
continue
|
||||
}
|
||||
switch keyValues[0] {
|
||||
case "username":
|
||||
username = keyValues[1]
|
||||
case "password":
|
||||
password = keyValues[1]
|
||||
}
|
||||
}
|
||||
|
||||
if err := setupGitAuth(ctx, username, password, *flRepo); err != nil {
|
||||
return fmt.Errorf("error setup git auth: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
# Using an Http Auth URL with git-sync
|
||||
|
||||
# Step 1: Create Auth Service
|
||||
|
||||
First, create a http service which can provide the username and password for the
|
||||
git repo.
|
||||
|
||||
Example of the auth url output:
|
||||
|
||||
```
|
||||
username=xxx@example.com
|
||||
password=ya29.xxxxyyyyzzzz
|
||||
```
|
||||
|
||||
# Step 2: Configure git-sync container
|
||||
|
||||
In your git-sync container configuration, specify the auth url.
|
||||
|
||||
The credentials will pass in plain text, make sure the connection between git-sync
|
||||
and auth server are secure. The recommended way is the auth server running within
|
||||
the same pod as git-sync.
|
||||
|
||||
```
|
||||
{
|
||||
name: "git-sync",
|
||||
...
|
||||
env: [
|
||||
{
|
||||
name: "GIT_SYNC_REPO",
|
||||
value: "https://source.developers.google.com/p/[GCP PROJECT ID]/r/[REPO NAME]"
|
||||
}, {
|
||||
name: "GIT_SYNC_AUTH_URL",
|
||||
value: "http://localhost:8080/gce_node_auth",
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
|
@ -34,7 +34,7 @@ volumes: [
|
|||
],
|
||||
```
|
||||
|
||||
# Step 2: Configure git-sync container
|
||||
# Step 3: Configure git-sync container
|
||||
|
||||
In your git-sync container configuration, mount your volume at
|
||||
"/etc/git-secret". Make sure to pass the `--cookie-file` flag or set the
|
||||
|
|
|
|||
Loading…
Reference in New Issue