Skip to content

Commit

Permalink
Add support to retrieve team and environment (#183)
Browse files Browse the repository at this point in the history
Co-authored-by: Vera Reynolds <vreynolds@users.noreply.github.com>
  • Loading branch information
MikeGoldsmith and vreynolds authored Jul 13, 2022
1 parent c9e7df0 commit 8ec8aa7
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 12 deletions.
56 changes: 44 additions & 12 deletions libhoney.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,31 @@ func VerifyWriteKey(config Config) (team string, err error) {
// rejected.
func VerifyAPIKey(config Config) (team string, err error) {
dc.ensureLogger()
defer func() { dc.logger.Printf("verify write key got back %s with err=%s", team, err) }()
auth, err := getAuth(config)
dc.logger.Printf("verify write key got back %s with err=%s", auth.Team.Slug, err)
if err != nil {
return "", err
}
return auth.Team.Slug, nil
}

// GetTeamAndEnvironment calls out to the Honeycomb API to validate the API key
// and retrieve the associated team and environment names.
func GetTeamAndEnvironment(config Config) (team string, environment string, err error) {
dc.ensureLogger()
auth, err := getAuth(config)
dc.logger.Printf("verify API key got back %s with err=%s", auth.Team.Slug, err)
if err != nil {
return "", "", err
}
return auth.Team.Slug, auth.Environment.Slug, nil
}

func getAuth(config Config) (authInfo, error) {
auth := authInfo{}
if config.APIKey == "" {
if config.WriteKey == "" {
return team, errors.New("config.APIKey and config.WriteKey are both empty; can't verify empty key")
return auth, errors.New("config.APIKey and config.WriteKey are both empty; can't verify empty key")
}
config.APIKey = config.WriteKey
}
Expand All @@ -329,35 +350,46 @@ func VerifyAPIKey(config Config) (team string, err error) {
}
u, err := url.Parse(config.APIHost)
if err != nil {
return team, fmt.Errorf("Error parsing API URL: %s", err)
return auth, fmt.Errorf("Error parsing API URL: %s", err)
}
u.Path = path.Join(u.Path, "1", "team_slug")
u.Path = path.Join(u.Path, "1", "auth")
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return team, err
return auth, err
}
req.Header.Set("User-Agent", UserAgentAddition)
req.Header.Add("X-Honeycomb-Team", config.APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return team, err
return auth, err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusUnauthorized {
return team, errors.New("Write key provided is invalid")
return auth, errors.New("Write key provided is invalid")
}
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return team, fmt.Errorf(`Abnormal non-200 response verifying Honeycomb write key: %d
return auth, fmt.Errorf(`Abnormal non-200 response verifying Honeycomb write/API key: %d
Response body: %s`, resp.StatusCode, string(body))
}
ret := map[string]string{}
if err := json.Unmarshal(body, &ret); err != nil {
return team, err
if err := json.Unmarshal(body, &auth); err != nil {
return auth, fmt.Errorf("failed to JSON decode of AuthInfo response from Honeycomb API")
}
return auth, nil
}

type teamInfo struct {
Slug string `json:"slug"`
}

type environmentInfo struct {
Slug string `json:"slug"`
}

return ret["team_slug"], nil
type authInfo struct {
Team teamInfo `json:"team"`
Environment environmentInfo `json:"environment"`
}

// Deprecated: Response is deprecated; please use transmission.Response instead.
Expand Down
47 changes: 47 additions & 0 deletions libhoney_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1187,3 +1187,50 @@ func TestConfigVariationsForClassicNonClassic(t *testing.T) {
testEquals(t, config.getDataset(), tc.expectedDataset)
}
}

func TestVerifyAPIKey(t *testing.T) {
testCases := []struct {
Name string
APIKey string
expectedEnvironment string
}{
{Name: "classic", APIKey: "lcYrFflRUR6rHbIifwqhfGRUR6rHbIic", expectedEnvironment: ""},
{Name: "non-classic", APIKey: "lcYrFflRUR6rHbIifwqhfG", expectedEnvironment: "test_env"},
}

for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
config := Config{
APIKey: tc.APIKey,
}

server := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/1/auth", r.URL.Path)
assert.Equal(t, []string{tc.APIKey}, r.Header["X-Honeycomb-Team"])

if config.isClassic() {
w.Write([]byte(`{"team":{"slug":"test_team"}}`))
} else {
w.Write([]byte(`{"team":{"slug":"test_team"},"environment":{"slug":"test_env"}}`))
}
}),
)
defer server.Close()
config.APIHost = server.URL

// There are 3 places we can verify and/or get the team and environment given
// an APIkey: VerifyWriteKey, VerifyAPIKey and GetTeamAndEnvironment
team, err := VerifyWriteKey(config)
assert.Equal(t, "test_team", team)
assert.Nil(t, err)

team, err = VerifyAPIKey(config)
assert.Equal(t, "test_team", team)
assert.Nil(t, err)

team, env, err := GetTeamAndEnvironment(config)
assert.Equal(t, tc.expectedEnvironment, env)
})
}
}

0 comments on commit 8ec8aa7

Please sign in to comment.