Skip to content

Commit

Permalink
[718] Prevent truncation of env var queries (stripe#719)
Browse files Browse the repository at this point in the history
  • Loading branch information
gracegoo-stripe authored Aug 2, 2021
1 parent 1aa026b commit 58182cb
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 28 deletions.
57 changes: 37 additions & 20 deletions pkg/fixtures/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type fixture struct {
}

type fixtureQuery struct {
Match string // The substring that matched the query pattern regex
Name string
Query string
DefaultValue string
Expand Down Expand Up @@ -381,8 +382,10 @@ func findSimilarQueryNames(fxt *Fixture, name string) ([]string, bool) {
return keys, len(keys) > 0
}

func (fxt *Fixture) parseQuery(value string) (string, error) {
if query, isQuery := toFixtureQuery(value); isQuery {
func (fxt *Fixture) parseQuery(queryString string) (string, error) {
value := queryString

if query, isQuery := toFixtureQuery(queryString); isQuery {
name := query.Name

// Check if there is a default value specified
Expand All @@ -392,26 +395,16 @@ func (fxt *Fixture) parseQuery(value string) (string, error) {

// Catch and insert .env values
if name == ".env" {
key := query.Query
// Check if env variable is present
envValue := os.Getenv(key)
if envValue == "" {
// Try to load from .env file
dir, err := os.Getwd()
if err != nil {
dir = ""
}
err = godotenv.Load(path.Join(dir, ".env"))
if err != nil {
return value, nil
}
envValue = os.Getenv(key)
}
if envValue == "" {
fmt.Printf("No value for env var: %s\n", key)
envValue, err := getEnvVar(query)
if err != nil || envValue == "" {
return value, nil
}
return envValue, nil

// Handle the case where only a substring of the original queryString was a query.
// Ex: ${.env:BLAH}/blah/blah
value = strings.ReplaceAll(queryString, query.Match, envValue)
return value, nil
}

if _, ok := fxt.responses[name]; ok {
Expand Down Expand Up @@ -454,6 +447,30 @@ func (fxt *Fixture) parseQuery(value string) (string, error) {
return value, nil
}

func getEnvVar(query fixtureQuery) (string, error) {
key := query.Query
// Check if env variable is present
envValue := os.Getenv(key)
if envValue == "" {
// Try to load from .env file
dir, err := os.Getwd()
if err != nil {
dir = ""
}
err = godotenv.Load(path.Join(dir, ".env"))
if err != nil {
return "", nil
}
envValue = os.Getenv(key)
}
if envValue == "" {
fmt.Printf("No value for env var: %s\n", key)
return "", nil
}

return envValue, nil
}

func (fxt *Fixture) updateEnv(env map[string]string) error {
dir, err := os.Getwd()
if err != nil {
Expand Down Expand Up @@ -506,7 +523,7 @@ func toFixtureQuery(value string) (fixtureQuery, bool) {
if r, didMatch := matchFixtureQuery(value); didMatch {
isQuery = true
match := r.FindStringSubmatch(value)
query = fixtureQuery{Name: match[1], Query: match[2], DefaultValue: match[3]}
query = fixtureQuery{Match: match[0], Name: match[1], Query: match[2], DefaultValue: match[3]}
}

return query, isQuery
Expand Down
33 changes: 25 additions & 8 deletions pkg/fixtures/fixtures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,23 @@ func TestParseWithEnvFile(t *testing.T) {
fs.Remove(envPath)
}

func TestParseWithEnvSubstring(t *testing.T) {
fs := afero.NewOsFs()
wd, _ := os.Getwd()
envPath := path.Join(wd, ".env")
afero.WriteFile(fs, envPath, []byte(`BASE_API_URL="https://myexample.com"`), os.ModePerm)

fxt := Fixture{}
data := make(map[string]interface{})
data["url"] = "${.env:BASE_API_URL}/hook/stripe"
output, _ := (fxt.parseInterface(data))

require.Equal(t, len(output), 1)
require.Equal(t, "url=https://myexample.com/hook/stripe", output[0])

fs.Remove(envPath)
}

func TestMakeRequest(t *testing.T) {
fs := afero.NewMemMapFs()
ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -476,42 +493,42 @@ func TestToFixtureQuery(t *testing.T) {
},
{
"/v1/charges/${char_bender:id}/capture",
fixtureQuery{"char_bender", "id", ""},
fixtureQuery{"${char_bender:id}", "char_bender", "id", ""},
true,
},
{
"${.env:PHONE_NOT_SET|+1234567890}",
fixtureQuery{".env", "PHONE_NOT_SET", "+1234567890"},
fixtureQuery{"${.env:PHONE_NOT_SET|+1234567890}", ".env", "PHONE_NOT_SET", "+1234567890"},
true,
},
{
"/v1/customers/${.env:CUST_ID}",
fixtureQuery{".env", "CUST_ID", ""},
fixtureQuery{"${.env:CUST_ID}", ".env", "CUST_ID", ""},
true,
},
{
"${.env:CUST_ID}",
fixtureQuery{".env", "CUST_ID", ""},
fixtureQuery{"${.env:CUST_ID}", ".env", "CUST_ID", ""},
true,
},
{
"${cust_bender:subscriptions.data.[0].id}",
fixtureQuery{"cust_bender", "subscriptions.data.[0].id", ""},
fixtureQuery{"${cust_bender:subscriptions.data.[0].id}", "cust_bender", "subscriptions.data.[0].id", ""},
true,
},
{
"${cust_bender:subscriptions.data.[0].name|Unknown Person}",
fixtureQuery{"cust_bender", "subscriptions.data.[0].name", "Unknown Person"},
fixtureQuery{"${cust_bender:subscriptions.data.[0].name|Unknown Person}", "cust_bender", "subscriptions.data.[0].name", "Unknown Person"},
true,
},
{
"${cust_bender:billing_details.address.country}",
fixtureQuery{"cust_bender", "billing_details.address.country", ""},
fixtureQuery{"${cust_bender:billing_details.address.country}", "cust_bender", "billing_details.address.country", ""},
true,
},
{
"${cust_bender:billing_details.address.country|San Mateo}",
fixtureQuery{"cust_bender", "billing_details.address.country", "San Mateo"},
fixtureQuery{"${cust_bender:billing_details.address.country|San Mateo}", "cust_bender", "billing_details.address.country", "San Mateo"},
true,
},
}
Expand Down

0 comments on commit 58182cb

Please sign in to comment.