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

feature(cli): The new lacework-cli MVP #28

Merged
5 commits merged into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
.idea

# vim
Expand Down
35 changes: 27 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
default: ci

ci: lint test fmt-check imports-check

export GOFLAGS=-mod=vendor
ci: lint test fmt-check imports-check build-cli-cross-platform

GOLANGCILINTVERSION?=1.23.8
COVERAGEOUT?=coverage.out
CLINAME?=lacework-cli
GO_LDFLAGS="-X github.com/lacework/go-sdk/cli/cmd.Version=$(shell cat cli/VERSION) \
-X github.com/lacework/go-sdk/cli/cmd.GitSHA=$(shell git rev-parse HEAD) \
-X github.com/lacework/go-sdk/cli/cmd.BuildTime=$(shell date +%Y%m%d%H%M%S)"
GOFLAGS=-mod=vendor
export GOFLAGS GO_LDFLAGS

prepare: install-tools go-vendor

Expand Down Expand Up @@ -37,11 +40,24 @@ fmt-check:
imports-check:
@test -z $(shell goimports -l $(shell go list -f {{.Dir}} ./...))

build-cli:
go build -o bin/$(CLINAME) cli/main.go
@echo
@echo To execute the generated binary run:
@echo " ./bin/$(CLINAME)"
build-cli-cross-platform:
gox -output="bin/$(CLINAME)-{{.OS}}-{{.Arch}}" \
-os="darwin linux windows" \
-arch="amd64 386" \
-ldflags=$(GO_LDFLAGS) \
github.com/lacework/go-sdk/cli

install-cli: build-cli-cross-platform
ifeq (x86_64, $(shell uname -m))
ln -sf bin/$(CLINAME)-$(shell uname -s | tr '[:upper:]' '[:lower:]')-amd64 bin/$(CLINAME)
else
ln -sf bin/$(CLINAME)-$(shell uname -s | tr '[:upper:]' '[:lower:]')-386 bin/$(CLINAME)
endif
@echo "\nUpdate your PATH environment variable to execute the compiled lacework-cli:"
@echo "\n $$ export PATH=\"$(PWD)/bin:$$PATH\"\n"

release-cli: lint fmt-check imports-check test
scripts/lacework_cli_release.sh

install-tools:
ifeq (, $(shell which golangci-lint))
Expand All @@ -50,3 +66,6 @@ endif
ifeq (, $(shell which goimports))
go get golang.org/x/tools/cmd/goimports
endif
ifeq (, $(shell which gox))
go get github.com/mitchellh/gox
endif
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,21 @@ Look at the [api/](api/) folder for more documentation.

## Lacework CLI ([`cli`](cli/))

_(work-in-progress)_ The Lacework Command Line Interface.
The Lacework Command Line Interface.

### Basic Usage

Today, you have to first build the CLI by running `make build-cli`, then you will be
able to execute it directly:
Build and install the CLI by running `make install-cli`, the automation will
ask you to update your `PATH` environment variable to execute the compiled
`lacework-cli` binary.
```
$ make build-cli
$ ./bin/lacework-cli
$ make install-cli

# Make sure to update your PATH with the command provided from the above command

$ lacework-cli help
```
Look at the [cli/](cli/) folder for more documentation.

## License and Copyright
Copyright 2020, Lacework Inc.
Expand Down
5 changes: 5 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,8 @@ func WithURL(baseURL string) Option {
return nil
})
}

// URL returns the base url configured
func (c *Client) URL() string {
return c.baseURL.String()
}
80 changes: 80 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<img src="https://techally-content.s3-us-west-1.amazonaws.com/public-content/lacework_logo_full.png" width="600">

# `lacework-cli`

The Lacework Command Line Interface is a tool that helps you manage your
Lacework cloud security platform. You can use it to manage compliance
reports, external integrations, vulnerability scans, and other operations.

## Install

### Bash:
```
$ curl https://raw.githubusercontent.com/lacework/go-sdk/master/cli/install.sh | sudo bash
```

### Powershell:
```
C:\> Set-ExecutionPolicy Bypass -Scope Process -Force
C:\> iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/lacework/go-sdk/master/cli/install.ps1'))
```

## Configuration File

The `lacework-cli` looks for a file named `.lacework.toml` inside your home
directory (`$HOME/.lacework.toml`) to access the following parameters:
* `account`: Account subdomain of URL (i.e. `<ACCOUNT>.lacework.net`)
* `api_key`: API Access Key ID
* `api_secret`: API Access Secret Key


An example of a Lacework configuration file:
```toml
account = "example"
api_key = "EXAMPLE_1234567890ABC"
api_secret = "_super_secret_key"
```

You can provide a different configuration file with the option `--config`.

## Basic Usage
Once you have created your configuration file `$HOME/.lacework.toml`,
you are ready to use the Lacework cli, a few basic commands are:

1) List all integration in your account:
```bash
$ lacework-cli integration list
```
1) Use the `api` command to access Lacework's ResfulAPI, for example,
to get details about and specific event:
```bash
$ lacework-cli api get '/external/events/GetEventDetails?EVENT_ID=16700'
```

## Development
To build and install the CLI from source, use the `make install-cli` directive,
this command will ask you to update your `PATH` environment variable to point
to the compiled `lacework-cli` binary.
```
$ make install-cli

# Make sure to update your PATH with the command provided from the above command

$ lacework-cli help
```

## License and Copyright
Copyright 2020, Lacework Inc.
```
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
1 change: 1 addition & 0 deletions cli/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.1.0
123 changes: 123 additions & 0 deletions cli/cmd/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// Author:: Salim Afiune Maya (<[email protected]>)
// Copyright:: Copyright 2020, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cmd

import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/lacework/go-sdk/api"
"github.com/lacework/go-sdk/internal/array"
)

var (
// list of valid API methods
validApiMethods = []string{"get", "post", "delete", "patch"}

// data to send for POST/PATCH request
apiData string

// apiCmd represents the api command
apiCmd = &cobra.Command{
Use: "api <method> <path>",
Short: "Helper to call Lacework's ResfulAPI",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be "Restful"

Long: `Use this helper to call any available Lacework API endpoint.

An example, list all integrations configured in your account:

lacework-cli api get /external/integrations

For a complete list of available API endpoints visit:

https://<ACCOUNT>.lacework.net/api/v1/external/docs
`,
Args: argsApiValidator,
RunE: runApiCommand,
}
)

func init() {
rootCmd.AddCommand(apiCmd)

apiCmd.Flags().StringVarP(&apiData,
"data", "d", "",
"data to send only for post and patch requests",
)
}

func runApiCommand(cmd *cobra.Command, args []string) error {
switch args[0] {
case "post", "patch":
if apiData == "" {
return fmt.Errorf("missing '--data' parameter for post or patch requests")
}
case "delete", "get":
if apiData != "" {
return fmt.Errorf("use '--data' only for post and patch requests")
}
}

lacework, err := api.NewClient(cli.Account,
api.WithApiKeys(cli.KeyID, cli.Secret),
)
if err != nil {
return errors.Wrap(err, "unable to generate Lacework API client")
}

cli.Log.Debugw("api client generated",
"version", lacework.ApiVersion(),
"base_url", lacework.URL(),
)

response := new(map[string]interface{})
err = lacework.RequestDecoder(
strings.ToUpper(args[0]),
strings.TrimPrefix(args[1], "/"),
strings.NewReader(apiData),
response,
)
if err != nil {
return errors.Wrap(err, "unable to send the request")
}

pretty, err := cli.JsonF.Marshal(*response)
if err != nil {
cli.Log.Debugw("api response", "raw", response)
return errors.Wrap(err, "unable to format json response")
}

fmt.Println(string(pretty))
return nil
}

func argsApiValidator(_ *cobra.Command, args []string) error {
if len(args) != 2 {
return errors.New("requires 2 argument. (method and path)")
}
if !array.ContainsStr(validApiMethods, args[0]) {
return fmt.Errorf(
"invalid method specified: '%s' (valid methods are %s)",
args[0], validApiMethods,
)
}
return nil
}
91 changes: 91 additions & 0 deletions cli/cmd/integration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// Author:: Salim Afiune Maya (<[email protected]>)
// Copyright:: Copyright 2020, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cmd

import (
"fmt"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/lacework/go-sdk/api"
)

var (
// integrationCmd represents the integration command
integrationCmd = &cobra.Command{
Use: "integration",
Short: "Manage external integrations",
}

// integrationListCmd represents the list sub-command inside the integration command
instegrationListCmd = &cobra.Command{
Use: "list",
Short: "List all available external integrations",
RunE: func(cmd *cobra.Command, args []string) error {
lacework, err := api.NewClient(cli.Account,
api.WithApiKeys(cli.KeyID, cli.Secret),
)
if err != nil {
return errors.Wrap(err, "unable to generate Lacework API client")
}

cli.Log.Debugw("api client generated",
"version", lacework.ApiVersion(),
"base_url", lacework.URL(),
)

integrations, err := lacework.Integrations.List()
if err != nil {
return errors.Wrap(err, "unable to get integrations")
}

fmt.Println(integrations.String())
return nil
},
}

// integrationCreateCmd represents the create sub-command inside the integration command
instegrationCreateCmd = &cobra.Command{
Use: "create",
Short: "Create an external integrations",
RunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}

// integrationDeleteCmd represents the delete sub-command inside the integration command
instegrationDeleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete an external integrations",
RunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
)

func init() {
// add the integration command
rootCmd.AddCommand(integrationCmd)

// add sub-commands to the integration command
integrationCmd.AddCommand(instegrationListCmd)
integrationCmd.AddCommand(instegrationCreateCmd)
integrationCmd.AddCommand(instegrationDeleteCmd)
}
Loading