Skip to content

Commit

Permalink
Merge pull request netlify#5 from netlify/mask-tokens
Browse files Browse the repository at this point in the history
Remove GH access token from API output
  • Loading branch information
brycekahle authored Sep 6, 2017
2 parents 0b05b7e + ae2de73 commit 2a02177
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 45 deletions.
1 change: 0 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ func NewAPIWithVersion(ctx context.Context, globalConfig *conf.GlobalConfigurati
r.Get("/health", api.HealthCheck)

r.Route("/", func(r *router) {

if globalConfig.MultiInstanceMode {
r.Use(api.loadJWSSignatureHeader)
r.Use(api.loadInstanceConfig)
Expand Down
18 changes: 2 additions & 16 deletions api/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import (
"net/http/httputil"
"net/url"
"regexp"
"strings"

"github.com/netlify/git-gateway/conf"
)

// GitHubGateway acts as a proxy to GitHub
Expand Down Expand Up @@ -65,19 +62,8 @@ func (gh *GitHubGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

var endpoint string
if config.GitHub.Endpoint != "" {
endpoint = config.GitHub.Endpoint
} else {
endpoint = conf.DefaultGitHubEndpoint
}
var apiURL string
if strings.HasSuffix(endpoint, "/") {
apiURL = endpoint + "repos/" + config.GitHub.Repo
} else {
apiURL = endpoint + "/repos/" + config.GitHub.Repo
}

endpoint := config.GitHub.Endpoint
apiURL := singleJoiningSlash(endpoint, "/repos/"+config.GitHub.Repo)
target, err := url.Parse(apiURL)
if err != nil {
handleError(internalServerError("Unable to process GitHub endpoint"), w, r)
Expand Down
25 changes: 25 additions & 0 deletions api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"strings"

"github.com/netlify/git-gateway/conf"
"github.com/netlify/git-gateway/models"
"github.com/pborman/uuid"
"github.com/pkg/errors"
)
Expand All @@ -18,7 +20,30 @@ func addRequestID(w http.ResponseWriter, r *http.Request) (context.Context, erro
return ctx, nil
}

func sanitizeOutput(obj interface{}) interface{} {
switch v := obj.(type) {
case InstanceResponse:
v.Instance.BaseConfig.GitHub.AccessToken = ""
case *InstanceResponse:
v.Instance.BaseConfig.GitHub.AccessToken = ""
case models.Instance:
v.BaseConfig.GitHub.AccessToken = ""
case *models.Instance:
v.BaseConfig.GitHub.AccessToken = ""
case *conf.Configuration:
v.GitHub.AccessToken = ""
case conf.Configuration:
v.GitHub.AccessToken = ""
// must return here because v != obj due to value copying
return v
default:
}
return obj
}

func sendJSON(w http.ResponseWriter, status int, obj interface{}) error {
obj = sanitizeOutput(obj)

w.Header().Set("Content-Type", "application/json")
b, err := json.Marshal(obj)
if err != nil {
Expand Down
96 changes: 96 additions & 0 deletions api/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package api

import (
"testing"

"github.com/netlify/git-gateway/conf"
"github.com/netlify/git-gateway/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSanitizeOutput(t *testing.T) {
t.Run("InstanceResponse", func(t *testing.T) {
v := InstanceResponse{
Instance: models.Instance{
BaseConfig: &conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
},
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(InstanceResponse).Instance.BaseConfig.GitHub.AccessToken)
})

t.Run("InstanceResponsePtr", func(t *testing.T) {
v := &InstanceResponse{
Instance: models.Instance{
BaseConfig: &conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
},
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(*InstanceResponse).Instance.BaseConfig.GitHub.AccessToken)
})

t.Run("Instance", func(t *testing.T) {
v := models.Instance{
BaseConfig: &conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(models.Instance).BaseConfig.GitHub.AccessToken)
})

t.Run("InstancePtr", func(t *testing.T) {
v := &models.Instance{
BaseConfig: &conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(*models.Instance).BaseConfig.GitHub.AccessToken)
})

t.Run("Configuration", func(t *testing.T) {
v := conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(conf.Configuration).GitHub.AccessToken)
})

t.Run("ConfigurationPtr", func(t *testing.T) {
v := &conf.Configuration{
GitHub: conf.GitHubConfig{
AccessToken: "remove",
},
}

ov := sanitizeOutput(v)
require.IsType(t, v, ov)
assert.Equal(t, "", ov.(*conf.Configuration).GitHub.AccessToken)
})
}
4 changes: 2 additions & 2 deletions api/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ func (a *API) GetAppManifest(w http.ResponseWriter, r *http.Request) error {
// TODO update to real manifest
return sendJSON(w, http.StatusOK, map[string]string{
"version": a.version,
"name": "GoTrue",
"description": "GoTrue is a user registration and authentication API",
"name": "GitGateway",
"description": "GitGateway is an access control proxy to git repos",
})
}

Expand Down
30 changes: 4 additions & 26 deletions conf/configuration.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package conf

import (
"encoding/json"
"os"
"strings"

"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
Expand All @@ -13,7 +11,7 @@ import (
const DefaultGitHubEndpoint = "https://api.github.com"

type GitHubConfig struct {
AccessToken string `envconfig:"ACCESS_TOKEN" json:"access_token"`
AccessToken string `envconfig:"ACCESS_TOKEN" json:"access_token,omitempty"`
Endpoint string `envconfig:"ENDPOINT" json:"endpoint"`
Repo string `envconfig:"REPO" json:"repo"` // Should be "owner/repo" format
}
Expand Down Expand Up @@ -52,29 +50,6 @@ type Configuration struct {
Roles []string `envconfig:"ROLES" json:"roles"`
}

func maskAccessToken(token string) string {
return strings.Repeat("*", len(token))
}

func githubEndpoint(endpoint string) string {
if endpoint == "" {
return DefaultGitHubEndpoint
}
return endpoint
}

func (gh *GitHubConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
AccessToken string `json:"access_token"`
Endpoint string `json:"endpoint"`
Repo string `json:"repo"`
}{
AccessToken: maskAccessToken(gh.AccessToken),
Endpoint: githubEndpoint(gh.Endpoint),
Repo: gh.Repo,
})
}

func loadEnvironment(filename string) error {
var err error
if filename != "" {
Expand Down Expand Up @@ -121,4 +96,7 @@ func LoadConfig(filename string) (*Configuration, error) {

// ApplyDefaults sets defaults for a Configuration
func (config *Configuration) ApplyDefaults() {
if config.GitHub.Endpoint == "" {
config.GitHub.Endpoint = DefaultGitHubEndpoint
}
}

0 comments on commit 2a02177

Please sign in to comment.