From 6e615a8ff932cee03d767ebeae523aaa72e34fa5 Mon Sep 17 00:00:00 2001 From: Yoriyasu Yano <430092+yorinasub17@users.noreply.github.com> Date: Mon, 11 May 2020 10:56:53 -0500 Subject: [PATCH] Add ability to set git auth token using environment variables Currently the only way to set the git auth is by including it in the context git URL. This can be problematic for certain environments such as ECS where the command args for are stored in logs. Introduces updates to allow setting the authentication info using the environment variables `GIT_USERNAME` and `GIT_PASSWORD`. --- README.md | 3 ++ pkg/buildcontext/git.go | 18 ++++++++ pkg/buildcontext/git_test.go | 87 ++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/README.md b/README.md index 1575397a9..e20114ce0 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,9 @@ If you are using Azure Blob Storage for context file, you will need to pass [Azu ### Using Private Git Repository You can use `Personal Access Tokens` for Build Contexts from Private Repositories from [GitHub](https://blog.github.com/2012-09-21-easier-builds-and-deployments-using-git-over-https-and-oauth/). +You can either pass this in as part of the git URL (e.g., `git://TOKEN@github.com/acme/myproject.git#refs/heads/mybranch`) +or using the environment variable `GIT_USERNAME`. + ### Using Standard Input If running kaniko and using Standard Input build context, you will need to add the docker or kubernetes `-i, --interactive` flag. Once running, kaniko will then get the data from `STDIN` and create the build context as a compressed tar. diff --git a/pkg/buildcontext/git.go b/pkg/buildcontext/git.go index 7c2dddc6d..18d6e2ded 100644 --- a/pkg/buildcontext/git.go +++ b/pkg/buildcontext/git.go @@ -23,12 +23,17 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/constants" git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/transport" + "gopkg.in/src-d/go-git.v4/plumbing/transport/http" ) const ( gitPullMethodEnvKey = "GIT_PULL_METHOD" gitPullMethodHTTPS = "https" gitPullMethodHTTP = "http" + + gitAuthUsernameEnvKey = "GIT_USERNAME" + gitAuthPasswordEnvKey = "GIT_PASSWORD" ) var ( @@ -46,6 +51,7 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) { parts := strings.Split(g.context, "#") options := git.CloneOptions{ URL: getGitPullMethod() + "://" + parts[0], + Auth: getGitAuth(), Progress: os.Stdout, } if len(parts) > 1 { @@ -55,6 +61,18 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) { return directory, err } +func getGitAuth() transport.AuthMethod { + username := os.Getenv(gitAuthUsernameEnvKey) + password := os.Getenv(gitAuthPasswordEnvKey) + if username != "" || password != "" { + return &http.BasicAuth{ + Username: username, + Password: password, + } + } + return nil +} + func getGitPullMethod() string { gitPullMethod := os.Getenv(gitPullMethodEnvKey) if ok := supportedGitPullMethods[gitPullMethod]; !ok { diff --git a/pkg/buildcontext/git_test.go b/pkg/buildcontext/git_test.go index ccc53fcb9..aaa487c92 100644 --- a/pkg/buildcontext/git_test.go +++ b/pkg/buildcontext/git_test.go @@ -21,6 +21,8 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/testutil" + "gopkg.in/src-d/go-git.v4/plumbing/transport" + "gopkg.in/src-d/go-git.v4/plumbing/transport/http" ) func TestGetGitPullMethod(t *testing.T) { @@ -80,3 +82,88 @@ func TestGetGitPullMethod(t *testing.T) { }) } } + +func TestGetGitAuth(t *testing.T) { + tests := []struct { + testName string + setEnv func() (expectedValue transport.AuthMethod) + }{ + { + testName: "noEnv", + setEnv: func() (expectedValue transport.AuthMethod) { + expectedValue = nil + return + }, + }, + { + testName: "emptyUsernameEnv", + setEnv: func() (expectedValue transport.AuthMethod) { + _ = os.Setenv(gitAuthUsernameEnvKey, "") + expectedValue = nil + return + }, + }, + { + testName: "emptyPasswordEnv", + setEnv: func() (expectedValue transport.AuthMethod) { + _ = os.Setenv(gitAuthPasswordEnvKey, "") + expectedValue = nil + return + }, + }, + { + testName: "emptyEnv", + setEnv: func() (expectedValue transport.AuthMethod) { + _ = os.Setenv(gitAuthUsernameEnvKey, "") + _ = os.Setenv(gitAuthPasswordEnvKey, "") + expectedValue = nil + return + }, + }, + { + testName: "withUsername", + setEnv: func() (expectedValue transport.AuthMethod) { + username := "foo" + _ = os.Setenv(gitAuthUsernameEnvKey, username) + expectedValue = &http.BasicAuth{Username: username} + return + }, + }, + { + testName: "withPassword", + setEnv: func() (expectedValue transport.AuthMethod) { + pass := "super-secret-password-1234" + _ = os.Setenv(gitAuthPasswordEnvKey, pass) + expectedValue = &http.BasicAuth{Password: pass} + return + }, + }, + { + testName: "withUsernamePassword", + setEnv: func() (expectedValue transport.AuthMethod) { + username := "foo" + pass := "super-secret-password-1234" + _ = os.Setenv(gitAuthUsernameEnvKey, username) + _ = os.Setenv(gitAuthPasswordEnvKey, pass) + expectedValue = &http.BasicAuth{Username: username, Password: pass} + return + }, + }, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + // Make sure to unset environment vars to get a clean test each time + defer clearTestAuthEnv() + + expectedValue := tt.setEnv() + testutil.CheckDeepEqual(t, expectedValue, getGitAuth()) + }) + } + +} + +func clearTestAuthEnv() { + _ = os.Unsetenv(gitAuthUsernameEnvKey) + _ = os.Unsetenv(gitAuthPasswordEnvKey) +}