Repository: chanzuckerberg/fogg
Pull request #679 (2022-07-15 18:33:51)

feat: allowing fogg to run with a github app token
### Summary
This PR allows Github Actions utilize installation tokens as an authentication mechanism as opposed to SSH keys.

### Test Plan
Unittests

### References
* https://github.com/tibdex/github-app-token


Patch:
diff --git a/util/module_storage.go b/util/module_storage.go
index db643894..4559b58c 100644
--- a/util/module_storage.go
+++ b/util/module_storage.go
@@ -112,17 +112,54 @@ func convertSSHToGithubHTTPURL(sURL, token string) string {
 	return fmt.Sprintf("git::%s", u.String())
 }
 
+// Changes a URL to use the git protocol over HTTPS instead of SSH.
+// If the URL was not a remote URL or an git/SSH protocol,
+// it will return the path that was passed in. If it does
+// convert it properly, it will add Github credentials to the path
+func convertSSHToGithubAppHTTPURL(sURL, token string) string {
+	// only detect the remote destinations
+	s, err := getter.Detect(sURL, token, []getter.Detector{
+		&getter.GitLabDetector{},
+		&getter.GitHubDetector{},
+		&getter.GitDetector{},
+		&getter.BitBucketDetector{},
+		&getter.S3Detector{},
+		&getter.GCSDetector{},
+	})
+	if err != nil {
+		logrus.Debug(err)
+		return sURL
+	}
+
+	splits := strings.Split(s, "git::ssh://git@")
+	if len(splits) != 2 {
+		return sURL
+	}
+	u, err := url.Parse(fmt.Sprintf("https://%s", splits[1]))
+	if err != nil {
+		logrus.Debug(err)
+		return sURL
+	}
+	u.User = url.UserPassword("x-access-token", token)
+
+	// we want to force the git protocol
+	return fmt.Sprintf("git::%s", u.String())
+}
+
 func MakeDownloader(src string) (*Downloader, error) {
 	type HTTPAuth struct {
-		GithubToken *string
+		GithubToken    *string
+		GithubAppToken *string
 	}
 	var httpAuth HTTPAuth
 	err := envconfig.Process("fogg", &httpAuth)
 	if err != nil {
-		return nil, errs.WrapUser(err, "unable to get env FOGG_GITHUBTOKEN flag")
+		return nil, errs.WrapUser(err, "unable to parse Github tokens")
 	}
 	if httpAuth.GithubToken != nil {
 		src = convertSSHToGithubHTTPURL(src, *httpAuth.GithubToken)
+	} else if httpAuth.GithubAppToken != nil {
+		src = convertSSHToGithubAppHTTPURL(src, *httpAuth.GithubAppToken)
 	}
 	return &Downloader{Source: src}, nil
 }


Test patch:
diff --git a/util/module_storage_test.go b/util/module_storage_test.go
index ba1596a9..c74f6bd4 100644
--- a/util/module_storage_test.go
+++ b/util/module_storage_test.go
@@ -61,6 +61,20 @@ func TestMakeDownloader(t *testing.T) {
 	r.Equal(fmt.Sprintf("git::https://%s@github.com/chanzuckerberg/test-repo//terraform/modules/eks-airflow?ref=v0.80.0", creds), downloader.Source)
 }
 
+func TestMakeDownloaderGithubApp(t *testing.T) {
+	r := require.New(t)
+	creds := "REDACTED"
+	downloader, err := MakeDownloader("git@github.com:chanzuckerberg/test-repo//terraform/modules/eks-airflow?ref=v0.80.0")
+	r.NoError(err)
+	r.Equal("git@github.com:chanzuckerberg/test-repo//terraform/modules/eks-airflow?ref=v0.80.0", downloader.Source)
+
+	os.Setenv("FOGG_GITHUBAPPTOKEN", creds)
+	defer os.Unsetenv("FOGG_GITHUBAPPTOKEN")
+	downloader, err = MakeDownloader("git@github.com:chanzuckerberg/test-repo//terraform/modules/eks-airflow?ref=v0.80.0")
+	r.NoError(err)
+	r.Equal(fmt.Sprintf("git::https://x-access-token:%s@github.com/chanzuckerberg/test-repo//terraform/modules/eks-airflow?ref=v0.80.0", creds), downloader.Source)
+}
+
 func TestConvertSSHToHTTP(t *testing.T) {
 	r := require.New(t)