* Adding read of default identity

* Adding tests, fixing a few residual issues.
This commit is contained in:
Martin Strobel 2018-01-12 12:28:38 -08:00 коммит произвёл GitHub
Родитель 8333ff65da
Коммит 44d80ce0a9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 112 добавлений и 0 удалений

Просмотреть файл

@ -1,6 +1,7 @@
package cmd
import (
"bytes"
"context"
"encoding/json"
"errors"
@ -9,6 +10,7 @@ import (
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"sync"
"time"
@ -68,6 +70,20 @@ var startCmd = &cobra.Command{
}()
}
if viper.IsSet("github-auth-token") && viper.GetString("github-auth-token") != "" {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
identity, err := FetchGitHubIdentity(ctx, viper.GetString("github-auth-token"))
if err == nil {
log.Print("Setting default GitHub identity: ", identity)
viper.Set("github-auth-username", identity)
} else {
log.Println("identity returned:")
log.Println("Unable to find identity to match access token because:", err)
}
}
if http.ListenAndServe(fmt.Sprintf(":%d", port), nil) != nil {
return
}
@ -113,8 +129,16 @@ func init() {
startCmd.Flags().StringP("redis-connection", "r", "", "The host to contact Redis with, if it's relevant.")
viper.BindPFlag("redis-connection", startCmd.Flags().Lookup("redis-connection"))
startCmd.Flags().StringP("github-auth-token", "g", "", "The default identity to assume when communicating with GitHub. Mirror configuration overrides this setting.")
viper.BindPFlag("github-auth-token", startCmd.Flags().Lookup("github-auth-token"))
viper.SetDefault("port", DefaultPort)
viper.SetDefault("clone-depth", DefaultCloneDepth)
if prefixlessAuthToken := os.Getenv("GITHUB_AUTH_TOKEN"); !viper.IsSet("github-auth-token") && prefixlessAuthToken != "" {
viper.BindEnv("github-auth-token", "GITHUB_AUTH_TOKEN")
log.Print(`Using environment variable "GITHUB_AUTH_TOKEN" because "MIRRORCAT_GITHUB_AUTH_TOKEN" wasn't found.`)
}
}
func handleGitHubPushEvent(resp http.ResponseWriter, req *http.Request) {
@ -169,8 +193,24 @@ loop:
break loop
}
var hasUser, hasPassword bool
repoURL, err := url.Parse(entry.Repository)
if err == nil && repoURL.User != nil {
hasUser = repoURL.User.Username() != ""
_, hasPassword = repoURL.User.Password()
}
if viper.IsSet("github-auth-token") && !hasUser && !hasPassword {
repoURL.User = url.UserPassword(viper.GetString("github-auth-username"), viper.GetString("github-auth-token"))
}
entry.Repository = repoURL.String()
err = mirrorcat.Push(ctx, original, entry, viper.GetInt("clone-depth"))
if err == nil {
// Strip password information before writing to logs.
repoURL.User = nil
entry.Repository = repoURL.String()
bodyWriter.Encode(WrittenTuple{
Original: original,
Mirror: entry,
@ -254,3 +294,47 @@ var populateStaticMirrors = func() func() error {
return nil
}
}()
// FetchGitHubIdentity uses the
func FetchGitHubIdentity(ctx context.Context, token string) (username string, err error) {
req, err := http.NewRequest(http.MethodGet, "https://api.github.com/user", &bytes.Buffer{})
if err != nil {
return
}
req = req.WithContext(ctx)
req.Header.Add("Accept", "application/vnd.github.jean-grey-preview+json")
req.SetBasicAuth("username", token) // The string "username" is arbitrary, and will be disregarded by the server when seeking an identity for a token.
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
} else if expected := 200; resp.StatusCode != expected {
err = fmt.Errorf("response status code (%d) wasn't the expected (%d): %v", resp.StatusCode, expected, resp)
return
}
const maxBytes = 5 * 1024 * 1024
rawBody, err := ioutil.ReadAll(&io.LimitedReader{
R: resp.Body,
N: maxBytes,
})
if err != nil {
return
}
partial := map[string]json.RawMessage{}
err = json.Unmarshal(rawBody, &partial)
if err != nil {
return
}
if marshaledName, ok := partial["login"]; ok {
err = json.Unmarshal([]byte(marshaledName), &username)
} else {
err = fmt.Errorf("login filed wasn't presnent in GitHub repsonse, status code %d", resp.StatusCode)
}
return
}

Просмотреть файл

@ -0,0 +1,28 @@
package cmd_test
import (
"context"
"testing"
"github.com/spf13/viper"
"github.com/Azure/mirrorcat/mirrorcat/cmd"
)
func TestFetchIdentity(t *testing.T) {
if !viper.IsSet("github-auth-token") || viper.GetString("github-auth-token") == "" {
t.Log("Unable to find environment variable defining Auth Token")
t.SkipNow()
}
result, err := cmd.FetchGitHubIdentity(context.Background(), viper.GetString("github-auth-token"))
if err != nil {
t.Error(err)
} else if result == "" {
t.Log("Personal Access Token not associated with any user.")
t.Fail()
} else {
t.Logf("Personal Access Token associated with user %q", result)
}
}