diff --git a/Makefile b/Makefile
index 34df2b7ab..9f28c47fe 100644
--- a/Makefile
+++ b/Makefile
@@ -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
@@ -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))
@@ -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
diff --git a/README.md b/README.md
index 4d352415c..fc03d4bb5 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/cli/README.md b/cli/README.md
new file mode 100644
index 000000000..f5cd1091e
--- /dev/null
+++ b/cli/README.md
@@ -0,0 +1,80 @@
+
+
+# `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. `.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.
+```
diff --git a/cli/install.ps1 b/cli/install.ps1
new file mode 100644
index 000000000..73c977c85
--- /dev/null
+++ b/cli/install.ps1
@@ -0,0 +1,13 @@
+<#
+.SYNOPSIS
+Installs the 'lacework-cli' tool.
+
+.Parameter Version
+Specifies a version (ex: 0.1.0)
+#>
+
+$ErrorActionPreference="stop"
+
+Set-Variable GithubReleasesRootUrl -Option ReadOnly -value "https://github.com/lacework/go-sdk/releases"
+
+Write-Host "Comming soon! (Installatiohn of the 'lacework-cli' tool)"
diff --git a/cli/install.sh b/cli/install.sh
new file mode 100755
index 000000000..8ef0baeda
--- /dev/null
+++ b/cli/install.sh
@@ -0,0 +1,230 @@
+#!/bin/bash
+#
+set -eou pipefail
+
+# If the variable $LW_DEBUG is set, print all shell commands executed
+if [ -n "${LW_DEBUG:-}" ]; then set -x; fi
+
+readonly github_releases="https://github.com/lacework/go-sdk/releases"
+
+usage() {
+ local _cmd
+ _cmd="$(basename "${0}")"
+ cat <&2
+ usage >&2
+ exit_with "Invalid option" 1
+ ;;
+ esac
+ done
+
+ log "Installing the 'lacewor-cli' tool"
+ create_workdir
+ check_platform
+ download_archive "$version" "$target"
+ verify_archive
+ extract_archive
+ install_cli
+ print_cli_version
+ log "The 'lacework-cli' tool has been successfully installed."
+}
+
+create_workdir() {
+ if [ -d /var/tmp ]; then
+ local _tmp=/var/tmp
+ else
+ local _tmp=/tmp
+ fi
+
+ workdir="$(mktemp -d -p "$_tmp" 2> /dev/null || mktemp -d "${_tmp}/lacework.XXXX")"
+ # add a trap to clean up work directory
+ trap 'code=$?; rm -rf $workdir; exit $code' INT TERM EXIT
+ cd "${workdir}"
+}
+
+check_platform() {
+ local _ostype
+ _ostype="$(uname -s)"
+
+ case "${_ostype}" in
+ Darwin|Linux)
+ sys="$(uname -s | tr '[:upper:]' '[:lower:]')"
+ arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
+ ;;
+ *)
+ exit_with "unable to determine OS platform type: ${_ostype}" 2
+ ;;
+ esac
+
+ case "${sys}" in
+ darwin)
+ ext=zip
+ shasum_cmd="shasum -a 256"
+ ;;
+ linux)
+ ext=tar.gz
+ shasum_cmd="sha256sum"
+ ;;
+ *)
+ exit_with "unable to determine system type, perhaps is not supported: ${sys}" 3
+ ;;
+ esac
+
+ # The following architectures match our cross-platform build process
+ # https://golang.org/doc/install/source#environment
+ case "${arch}" in
+ x86_64)
+ arch=amd64
+ ;;
+ i686)
+ arch=386
+ ;;
+ *)
+ exit_with "architecture not supported: ${arch}" 3
+ ;;
+ esac
+
+ if [ -z "${target:-}" ]; then
+ target="${sys}-${arch}"
+ fi
+}
+
+download_archive() {
+ local _version="${1:-latest}"
+ local -r _target="${2:?}"
+ local url
+
+ if [ "$_version" == "latest" ]; then
+ url="${github_releases}/latest/download/lacework-cli-${_target}.${ext}"
+ else
+ url="${github_releases}/download/${_version}/lacework-cli-${_target}.${ext}"
+ fi
+
+ download_file "${url}" "${workdir}/lacework-cli-${_version}.${ext}"
+ download_file "${url}.sha256sum" "${workdir}/lacework-cli-${_version}.${ext}.sha256sum"
+
+ archive="lacework-cli-${_target}.${ext}"
+ sha_file="lacework-cli-${_target}.${ext}.sha256sum"
+
+ mv -v "${workdir}/lacework-cli-${_version}.${ext}" "${archive}"
+ mv -v "${workdir}/lacework-cli-${_version}.${ext}.sha256sum" "${sha_file}"
+}
+
+verify_archive() {
+ log "Verifying the shasum digest matches the downloaded archive"
+ ${shasum_cmd} -c "${sha_file}"
+}
+
+extract_archive() {
+ log "Extracting ${archive}"
+ case "${ext}" in
+ tar.gz)
+ archive_dir="${archive%.tar.gz}"
+ mkdir "${archive_dir}"
+ zcat "${archive}" | tar --extract --directory "${archive_dir}" --strip-components=1
+
+ ;;
+ zip)
+ archive_dir="${archive%.zip}"
+ unzip -j "${archive}" -d "${archive_dir}"
+ ;;
+ *)
+ exit_with "[extract] Unknown file extension: ${ext}" 4
+ ;;
+ esac
+}
+
+install_cli() {
+ log "Installing lacework-cli into /usr/local/bin"
+ mkdir -pv /usr/local/bin
+ binary="lacework-cli-${target}"
+ install -v "${archive_dir}/lacework-cli-"* /usr/local/bin/lacework-cli
+}
+
+print_cli_version() {
+ info "Verifying installed lacework-cli version"
+ lacework-cli version
+}
+
+download_file() {
+ local _url="${1}"
+ local _dst="${2}"
+ local _code
+ local _wget_extra_args=""
+ local _curl_extra_args=""
+
+ # try to download with wget
+ if command -v wget > /dev/null; then
+ log "Downloading via wget: ${_url}"
+
+ wget -q -O "${_dst}" "${_url}"
+ _code="$?"
+
+ if [ $_code -eq 0 ]; then
+ return 0
+ else
+ warn "wget failed to download file, trying to download with curl"
+ fi
+ fi
+
+ # try to download with curl
+ if command -v curl > /dev/null; then
+ log "Downloading via curl: ${_url}"
+
+ curl -sSfL "${_url}" -o "${_dst}"
+ _code="$?"
+
+ if [ $_code -eq 0 ]; then
+ return 0
+ else
+ warn "curl failed to download file"
+ fi
+ fi
+
+ # wget and curl have failed, inform the user
+ exit_with "Required: SSL-enabled 'curl' or 'wget' on PATH with" 6
+}
+
+log() {
+ echo "--> install: $1"
+}
+
+warn() {
+ echo "xxx install: $1" >&2
+}
+
+exit_with() {
+ warn "$1"
+ exit "${2:-10}"
+}
+
+main "$@" || exit 99
diff --git a/scripts/lacework_cli_release.sh b/scripts/lacework_cli_release.sh
new file mode 100755
index 000000000..1485d16fb
--- /dev/null
+++ b/scripts/lacework_cli_release.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+#
+# Name:: lacework_cli_release.sh
+# Description:: Use this script to prepare a new release on Github,
+# the automation will build cross-platform binaries,
+# compress all generated targets, generate shasum
+# hashes, and create a GH tag like v0.1.0 (using the
+# VERSION file inside the cli/ directory)
+# Author:: Salim Afiune Maya ()
+#
+set -eou pipefail
+
+CLINAME=lacework-cli
+VERSION=$(cat cli/VERSION)
+TARGETS=(
+ ${CLINAME}-darwin-386
+ ${CLINAME}-darwin-amd64
+ ${CLINAME}-windows-386.exe
+ ${CLINAME}-windows-amd64.exe
+ ${CLINAME}-linux-386
+ ${CLINAME}-linux-amd64
+)
+
+main() {
+ log "Preparing release v$VERSION"
+ prerequisites
+ build_cli_cross_platform
+ compress_targets
+ generate_shasums
+ create_git_tag
+}
+
+create_git_tag() {
+ local _tag="v$VERSION"
+ log "Creating github tag: $_tag"
+ git tag "$_tag"
+ git push origin "$_tag"
+ log "Go to https://github.com/lacework/go-sdk/releases and upload all files from 'bin/'"
+}
+
+prerequisites() {
+ if ! command -v "gox" > /dev/null 2>&1; then
+ warn "Required command 'gox' not found on PATH"
+ warn "Try running 'make prepare'"
+ exit 127
+ fi
+
+ local _branch=$(git rev-parse --abbrev-ref HEAD)
+ if [ "$_branch" != "master" ]; then
+ warn "Releases must be generated from the 'master' branch. (current $_branch)"
+ warn "Switch to the master branch and try again."
+ exit 127
+ fi
+}
+
+clean_cache() {
+ rm -rf bin/*
+}
+
+build_cli_cross_platform() {
+ clean_cache
+ make build-cli-cross-platform
+}
+
+generate_shasums() {
+ ( cd bin/
+ local _compressed
+ log "Generating sha256sum Hashes"
+ for target in ${TARGETS[*]}; do
+
+ if [[ "$target" =~ /linux/ ]]; then
+ _compressed="$target.tar.gz"
+ else
+ _compressed="$target.zip"
+ fi
+
+ log "bin/$_compressed.sha256sum"
+ shasum -a 256 $_compressed > $_compressed.sha256sum
+
+ done
+ )
+}
+
+# compress_targets will compress all targets and remove the raw
+# binaries (already compressed), this is a release so we don't
+# need the raw binaries anymore.
+compress_targets() {
+ log "Compressing target binaries"
+ for target in ${TARGETS[*]}; do
+ if [[ "$target" =~ /linux/ ]]; then
+ tar -czvf "bin/${target}.tar.gz" "bin/${target}"
+ else
+ zip "bin/${target}.zip" "bin/${target}"
+ fi
+ rm -f "bin/${target}"
+ done
+}
+
+log() {
+ echo "--> ${CLINAME}: $1"
+}
+
+warn() {
+ echo "xxx ${CLINAME}: $1" >&2
+}
+
+main || exit 99