Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

profiler: add API key check at initialization of Profiler object #718

Merged
merged 12 commits into from
Sep 10, 2020
16 changes: 16 additions & 0 deletions profiler/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const (
defaultEnv = "none"
)

// Length of valid API key
const optionAPIKeyLength = 32
gbbr marked this conversation as resolved.
Show resolved Hide resolved

var defaultProfileTypes = []ProfileType{CPUProfile, HeapProfile}

type config struct {
Expand All @@ -71,6 +74,19 @@ func urlForSite(site string) (string, error) {
return u, err
}

// Check for API key constraints:
func apiKeyCheck(key string) bool {
gbbr marked this conversation as resolved.
Show resolved Hide resolved
if optionAPIKeyLength != len(key) {
gbbr marked this conversation as resolved.
Show resolved Hide resolved
return false
}
for _, c := range key {
if !((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
gbbr marked this conversation as resolved.
Show resolved Hide resolved
return false
}
}
return true
}

func (c *config) addProfileType(t ProfileType) {
if c.types == nil {
c.types = make(map[ProfileType]struct{})
Expand Down
15 changes: 9 additions & 6 deletions profiler/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,20 @@ func TestOptions(t *testing.T) {
})

t.Run("WithAPIKey", func(t *testing.T) {
var validKey = "12345678901234567890123456789012"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var validKey = "12345678901234567890123456789012"
validKey := "12345678901234567890123456789012"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, maybe we can have just one global constant testAPIKey

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestions.

Writing the tests revealed an issue with non-ASCII glyphs returning true by unicode.IsLower(), so this already paid off.

Also added a simple positive and negative check for Profiler instantiation.

var cfg config
WithAPIKey("123")(&cfg)
assert.Equal(t, "123", cfg.apiKey)
WithAPIKey(validKey)(&cfg)
assert.Equal(t, validKey, cfg.apiKey)
assert.Equal(t, cfg.apiURL, cfg.targetURL)
})

t.Run("WithAPIKey/override", func(t *testing.T) {
os.Setenv("DD_API_KEY", "apikey")
defer os.Unsetenv("DD_API_KEY")
var validKey = "12345678901234567890123456789012"
var cfg config
WithAPIKey("123")(&cfg)
assert.Equal(t, "123", cfg.apiKey)
WithAPIKey(validKey)(&cfg)
assert.Equal(t, validKey, cfg.apiKey)
})

t.Run("WithURL", func(t *testing.T) {
Expand Down Expand Up @@ -179,10 +181,11 @@ func TestEnvVars(t *testing.T) {
})

t.Run("DD_API_KEY", func(t *testing.T) {
os.Setenv("DD_API_KEY", "123")
var validKey = "12345678901234567890123456789012"
os.Setenv("DD_API_KEY", validKey)
defer os.Unsetenv("DD_API_KEY")
cfg := defaultConfig()
assert.Equal(t, "123", cfg.apiKey)
assert.Equal(t, validKey, cfg.apiKey)
})

t.Run("DD_SITE", func(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions profiler/profiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func newProfiler(opts ...Option) (*profiler, error) {
opt(cfg)
}
if cfg.apiKey != "" {
if !apiKeyCheck(cfg.apiKey) {
return nil, fmt.Errorf("API key has incorrect format; try checking your DD_API_KEY environment variable if submitting an API key is necessary for your configuration")
gbbr marked this conversation as resolved.
Show resolved Hide resolved
}
cfg.targetURL = cfg.apiURL
} else {
cfg.targetURL = cfg.agentURL
Expand Down