Skip to content

Commit 0f10a68

Browse files
authored
Merge pull request #152 from lacework/afiune/146/user-agent-header
feat: set User-Agent header (backend metrics)
2 parents e274eb3 + bb4cfc8 commit 0f10a68

21 files changed

+193
-201
lines changed

api/client.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Client struct {
4141
auth *authConfig
4242
c *http.Client
4343
log *zap.Logger
44+
headers map[string]string
4445

4546
Events *EventsService
4647
Compliance *ComplianceService
@@ -81,6 +82,9 @@ func NewClient(account string, opts ...Option) (*Client, error) {
8182
account: account,
8283
baseURL: baseURL,
8384
apiVersion: "v1",
85+
headers: map[string]string{
86+
"User-Agent": fmt.Sprintf("Go Client/%s", Version),
87+
},
8488
auth: &authConfig{
8589
expiration: defaultTokenExpiryTime,
8690
},
@@ -123,6 +127,17 @@ func WithURL(baseURL string) Option {
123127
})
124128
}
125129

130+
// WithHeader configures a HTTP Header to pass to every request
131+
func WithHeader(header, value string) Option {
132+
return clientFunc(func(c *Client) error {
133+
if header != "" && value != "" {
134+
c.log.Debug("setting up header", zap.String(header, value))
135+
c.headers[header] = value
136+
}
137+
return nil
138+
})
139+
}
140+
126141
// URL returns the base url configured
127142
func (c *Client) URL() string {
128143
return c.baseURL.String()

api/client_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func TestNewClientWithOptions(t *testing.T) {
5454
api.WithExpirationTime(1800),
5555
api.WithApiV2(),
5656
api.WithLogLevel("DEBUG"),
57+
api.WithHeader("User-Agent", "test-agent"),
5758
api.WithTokenFromKeys("KEY", "SECRET"), // this option has to be the last one
5859
)
5960
if assert.Nil(t, err) {

api/http.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ func (c *Client) NewRequest(method string, apiURL string, body io.Reader) (*http
7171
request.Header.Set(k, v)
7272
}
7373

74+
// add all global headers that the client has configured,
75+
// by default we set only the User-Agent header
76+
for k, v := range c.headers {
77+
request.Header.Set(k, v)
78+
}
79+
7480
// parse and encode query string values
7581
values := request.URL.Query()
7682
request.URL.RawQuery = values.Encode()
@@ -79,7 +85,7 @@ func (c *Client) NewRequest(method string, apiURL string, body io.Reader) (*http
7985
zap.String("method", request.Method),
8086
zap.String("url", c.baseURL.String()),
8187
zap.String("endpoint", apiPath.String()),
82-
zap.Reflect("headers", c.httpHeadersSniffer(headers)),
88+
zap.Reflect("headers", c.httpHeadersSniffer(request.Header)),
8389
zap.String("body", c.httpRequestBodySniffer(request)),
8490
)
8591

api/version.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/version_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//
2+
// Author:: Salim Afiune Maya (<afiune@lacework.net>)
3+
// Copyright:: Copyright 2020, Lacework Inc.
4+
// License:: Apache License, Version 2.0
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
package api_test
20+
21+
import (
22+
"io/ioutil"
23+
"testing"
24+
25+
"github.com/stretchr/testify/assert"
26+
27+
subject "github.com/lacework/go-sdk/api"
28+
)
29+
30+
func TestVersionMatchVERSIONfile(t *testing.T) {
31+
expectedVersion, err := ioutil.ReadFile("../VERSION")
32+
assert.Nil(t, err)
33+
assert.Equalf(t, string(expectedVersion), subject.Version,
34+
"api/version.go doesn't match with VERSION file; run scripts/version_updater.sh")
35+
}

cli/cmd/api.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"github.com/pkg/errors"
2626
"github.com/spf13/cobra"
2727

28-
"github.com/lacework/go-sdk/api"
2928
"github.com/lacework/go-sdk/internal/array"
3029
)
3130

@@ -77,16 +76,8 @@ func runApiCommand(_ *cobra.Command, args []string) error {
7776
}
7877
}
7978

80-
lacework, err := api.NewClient(cli.Account,
81-
api.WithLogLevel(cli.LogLevel),
82-
api.WithApiKeys(cli.KeyID, cli.Secret),
83-
)
84-
if err != nil {
85-
return errors.Wrap(err, "unable to generate api client")
86-
}
87-
8879
response := new(map[string]interface{})
89-
err = lacework.RequestDecoder(
80+
err := cli.LwApi.RequestDecoder(
9081
strings.ToUpper(args[0]),
9182
strings.TrimPrefix(args[1], "/"),
9283
strings.NewReader(apiData),

cli/cmd/cli_state.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"github.com/pkg/errors"
2929
"github.com/spf13/viper"
3030
"go.uber.org/zap"
31+
32+
"github.com/lacework/go-sdk/api"
3133
)
3234

3335
// cliState holds the state of the entire Lacework CLI
@@ -39,6 +41,7 @@ type cliState struct {
3941
Token string
4042
LogLevel string
4143

44+
LwApi *api.Client
4245
JsonF *prettyjson.Formatter
4346
Log *zap.SugaredLogger
4447

@@ -128,6 +131,26 @@ func (c *cliState) VerifySettings() error {
128131
return nil
129132
}
130133

134+
// NewClient creates and stores a new Lacework API client to be used by the CLI
135+
func (c *cliState) NewClient() error {
136+
err := c.VerifySettings()
137+
if err != nil {
138+
return err
139+
}
140+
141+
client, err := api.NewClient(c.Account,
142+
api.WithLogLevel(c.LogLevel),
143+
api.WithApiKeys(c.KeyID, c.Secret),
144+
api.WithHeader("User-Agent", fmt.Sprintf("Command-Line/%s", Version)),
145+
)
146+
if err != nil {
147+
return errors.Wrap(err, "unable to generate api client")
148+
}
149+
150+
c.LwApi = client
151+
return nil
152+
}
153+
131154
// InteractiveMode returns true if the cli is running in interactive mode
132155
func (c *cliState) InteractiveMode() bool {
133156
return !c.nonInteractive

cli/cmd/compliance.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import (
2323
"sort"
2424
"strings"
2525

26-
"github.com/lacework/go-sdk/api"
2726
"github.com/olekukonko/tablewriter"
2827
"github.com/spf13/cobra"
28+
29+
"github.com/lacework/go-sdk/api"
2930
)
3031

3132
var (

cli/cmd/compliance_aws.go

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import (
2323
"strings"
2424
"time"
2525

26-
"github.com/lacework/go-sdk/api"
2726
"github.com/olekukonko/tablewriter"
2827
"github.com/pkg/errors"
2928
"github.com/spf13/cobra"
29+
30+
"github.com/lacework/go-sdk/api"
3031
)
3132

3233
var (
@@ -63,22 +64,14 @@ To run an ad-hoc compliance assessment use the command:
6364
`,
6465
Args: cobra.ExactArgs(1),
6566
RunE: func(_ *cobra.Command, args []string) error {
66-
lacework, err := api.NewClient(cli.Account,
67-
api.WithLogLevel(cli.LogLevel),
68-
api.WithApiKeys(cli.KeyID, cli.Secret),
69-
)
70-
if err != nil {
71-
return errors.Wrap(err, "unable to generate api client")
72-
}
73-
7467
config := api.ComplianceAwsReportConfig{
7568
AccountID: args[0],
7669
Type: compCmdState.Type,
7770
}
7871

7972
if compCmdState.PdfName != "" {
8073
cli.StartProgress(" Downloading compliance report...")
81-
err := lacework.Compliance.DownloadAwsReportPDF(compCmdState.PdfName, config)
74+
err := cli.LwApi.Compliance.DownloadAwsReportPDF(compCmdState.PdfName, config)
8275
cli.StopProgress()
8376
if err != nil {
8477
return errors.Wrap(err, "unable to get aws pdf compliance report")
@@ -89,7 +82,7 @@ To run an ad-hoc compliance assessment use the command:
8982
}
9083

9184
cli.StartProgress(" Getting compliance report...")
92-
response, err := lacework.Compliance.GetAwsReport(config)
85+
response, err := cli.LwApi.Compliance.GetAwsReport(config)
9386
cli.StopProgress()
9487
if err != nil {
9588
return errors.Wrap(err, "unable to get aws compliance report")
@@ -124,15 +117,7 @@ To run an ad-hoc compliance assessment use the command:
124117
Long: `Run a compliance assessment for the provided AWS account.`,
125118
Args: cobra.ExactArgs(1),
126119
RunE: func(_ *cobra.Command, args []string) error {
127-
lacework, err := api.NewClient(cli.Account,
128-
api.WithLogLevel(cli.LogLevel),
129-
api.WithApiKeys(cli.KeyID, cli.Secret),
130-
)
131-
if err != nil {
132-
return errors.Wrap(err, "unable to generate api client")
133-
}
134-
135-
response, err := lacework.Compliance.RunAwsReport(args[0])
120+
response, err := cli.LwApi.Compliance.RunAwsReport(args[0])
136121
if err != nil {
137122
return errors.Wrap(err, "unable to run aws compliance report")
138123
}

cli/cmd/compliance_azure.go

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import (
2323
"strings"
2424
"time"
2525

26-
"github.com/lacework/go-sdk/api"
2726
"github.com/olekukonko/tablewriter"
2827
"github.com/pkg/errors"
2928
"github.com/spf13/cobra"
29+
30+
"github.com/lacework/go-sdk/api"
3031
)
3132

3233
var (
@@ -47,15 +48,7 @@ Then, select one GUID from an integration and visialize its details using the co
4748
`,
4849
Args: cobra.ExactArgs(1),
4950
RunE: func(_ *cobra.Command, args []string) error {
50-
lacework, err := api.NewClient(cli.Account,
51-
api.WithLogLevel(cli.LogLevel),
52-
api.WithApiKeys(cli.KeyID, cli.Secret),
53-
)
54-
if err != nil {
55-
return errors.Wrap(err, "unable to generate api client")
56-
}
57-
58-
response, err := lacework.Compliance.ListAzureSubscriptions(args[0])
51+
response, err := cli.LwApi.Compliance.ListAzureSubscriptions(args[0])
5952
if err != nil {
6053
return errors.Wrap(err, "unable to list azure subscriptions")
6154
}
@@ -94,14 +87,6 @@ To run an ad-hoc compliance assessment use the command:
9487
`,
9588
Args: cobra.ExactArgs(2),
9689
RunE: func(_ *cobra.Command, args []string) error {
97-
lacework, err := api.NewClient(cli.Account,
98-
api.WithLogLevel(cli.LogLevel),
99-
api.WithApiKeys(cli.KeyID, cli.Secret),
100-
)
101-
if err != nil {
102-
return errors.Wrap(err, "unable to generate api client")
103-
}
104-
10590
config := api.ComplianceAzureReportConfig{
10691
TenantID: args[0],
10792
SubscriptionID: args[1],
@@ -110,7 +95,7 @@ To run an ad-hoc compliance assessment use the command:
11095

11196
if compCmdState.PdfName != "" {
11297
cli.StartProgress(" Downloading compliance report...")
113-
err := lacework.Compliance.DownloadAzureReportPDF(compCmdState.PdfName, config)
98+
err := cli.LwApi.Compliance.DownloadAzureReportPDF(compCmdState.PdfName, config)
11499
cli.StopProgress()
115100
if err != nil {
116101
return errors.Wrap(err, "unable to get azure pdf compliance report")
@@ -121,7 +106,7 @@ To run an ad-hoc compliance assessment use the command:
121106
}
122107

123108
cli.StartProgress(" Getting compliance report...")
124-
response, err := lacework.Compliance.GetAzureReport(config)
109+
response, err := cli.LwApi.Compliance.GetAzureReport(config)
125110
cli.StopProgress()
126111
if err != nil {
127112
return errors.Wrap(err, "unable to get azure compliance report")
@@ -156,15 +141,7 @@ To run an ad-hoc compliance assessment use the command:
156141
Long: `Run a compliance assessment of the provided Azure tenant.`,
157142
Args: cobra.ExactArgs(1),
158143
RunE: func(_ *cobra.Command, args []string) error {
159-
lacework, err := api.NewClient(cli.Account,
160-
api.WithLogLevel(cli.LogLevel),
161-
api.WithApiKeys(cli.KeyID, cli.Secret),
162-
)
163-
if err != nil {
164-
return errors.Wrap(err, "unable to generate api client")
165-
}
166-
167-
response, err := lacework.Compliance.RunAzureReport(args[0])
144+
response, err := cli.LwApi.Compliance.RunAzureReport(args[0])
168145
if err != nil {
169146
return errors.Wrap(err, "unable to run azure compliance assessment")
170147
}

0 commit comments

Comments
 (0)