Skip to content

Commit

Permalink
Merge pull request #91 from DopplerHQ/tom_warning
Browse files Browse the repository at this point in the history
Print invalid JSON responses in debug mode
  • Loading branch information
Piccirello committed May 15, 2020
2 parents 377f486 + 358c152 commit f943ee6
Show file tree
Hide file tree
Showing 19 changed files with 73 additions and 41 deletions.
19 changes: 19 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,22 @@ Flags:
You can download all binaries and release artifacts from the [Releases](https://github.com/DopplerHQ/cli/releases/latest) page. Binaries are built for macOS, Linux, Windows, FreeBSD, OpenBSD, and NetBSD, and for 32-bit, 64-bit, armv6/armv7, and armv6/armv7 64-bit architectures.

You can also directly download the generated `.deb` and `.rpm` packages. If a binary does not yet exist for the OS/architecture you use, please open a GitHub Issue.

# Verify Signature

You can verify the integrity and authenticity of any released artifact using Doppler's public GPG key. The signatures of all release artifacts are placed in checksums.txt, which itself is then signed.

```sh
# fetch Doppler's signing key
gpg --keyserver keyserver.ubuntu.com --recv D3D593D50EE79DEC
# verify content of checksums.txt against signature
gpg --verify checksums.txt.sig checksums.txt
# verify checksum of cli binary (downloaded file name must match download page)
sha256sum --check --strict --ignore-missing checksums.txt
```

If the signature matches, you'll see output like this:
```sh
$ sha256sum --check --ignore-missing --strict checksums.txt
doppler_3.3.2_linux_amd64.deb: OK
```
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The Doppler CLI is the official tool for interacting with your Enclave secrets a

The Doppler CLI is available in several popular package managers. It's also [available](https://github.com/DopplerHQ/cli/releases/latest) as a standalone binary.

For more info, including instructions on verifying binary signatures, see the [Install](INSTALL.md) page.

### macOS

Using [brew](https://brew.sh/) is recommended:
Expand Down Expand Up @@ -105,6 +107,8 @@ Note: The release will automatically fail if the tag and HEAD have diverged:

` ⨯ release failed after 0.13s error=git tag v0.0.2 was not made against commit c9c6950d18790c17db11fedae331a226f8f12c6b`

Note: In the goreleaser output, it will state that artifact signing is disabled. This is due to the custom args we pass goreleaser (so that we can specify our GPG key). You can verify that signing works by the presence of a `checksums.txt.sig` file.

### Help

**Issue**: `gpg: signing failed: Inappropriate ioctl for device`
Expand Down
7 changes: 2 additions & 5 deletions pkg/cmd/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package cmd

import (
"errors"
"fmt"
"sort"
"strings"

Expand Down Expand Up @@ -58,9 +59,7 @@ and your config file. Flags have the highest priority; config file has the least
Run: func(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON

if !jsonFlag {
color.Green.Printf("Configuration file: %s\n\n", configuration.UserConfigFile)
}
utils.Log(fmt.Sprintf("%s %s", color.Green.Render("Configuration file:"), configuration.UserConfigFile))

config := configuration.LocalConfig(cmd)
printer.ScopedConfigSource(config, jsonFlag, true)
Expand Down Expand Up @@ -208,10 +207,8 @@ func init() {
configureGetCmd.Flags().Bool("copy", false, "copy the value(s) to your clipboard")
configureCmd.AddCommand(configureGetCmd)

configureSetCmd.Flags().Bool("silent", false, "disable text output")
configureCmd.AddCommand(configureSetCmd)

configureUnsetCmd.Flags().Bool("silent", false, "disable text output")
configureCmd.AddCommand(configureUnsetCmd)

configureCmd.Flags().Bool("all", false, "print all saved options")
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/enclave_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,21 +191,18 @@ func init() {
configsCreateCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
configsCreateCmd.Flags().String("name", "", "config name")
configsCreateCmd.Flags().StringP("environment", "e", "", "config environment")
configsCreateCmd.Flags().Bool("silent", false, "disable text output")
configsCmd.AddCommand(configsCreateCmd)

configsUpdateCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
configsUpdateCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
configsUpdateCmd.Flags().String("name", "", "config name")
configsUpdateCmd.Flags().Bool("silent", false, "disable text output")
if err := configsUpdateCmd.MarkFlagRequired("name"); err != nil {
utils.HandleError(err)
}
configsCmd.AddCommand(configsUpdateCmd)

configsDeleteCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
configsDeleteCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
configsDeleteCmd.Flags().Bool("silent", false, "disable text output")
configsDeleteCmd.Flags().Bool("yes", false, "proceed without confirmation")
configsCmd.AddCommand(configsDeleteCmd)

Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/enclave_configs_logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,5 @@ func init() {
configsLogsRollbackCmd.Flags().String("log", "", "audit log id")
configsLogsRollbackCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
configsLogsRollbackCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
configsLogsRollbackCmd.Flags().Bool("silent", false, "disable text output")
configsLogsCmd.AddCommand(configsLogsRollbackCmd)
}
1 change: 0 additions & 1 deletion pkg/cmd/enclave_configs_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,5 @@ func init() {
configsTokensRevokeCmd.Flags().String("slug", "", "service token slug")
configsTokensRevokeCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
configsTokensRevokeCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
configsTokensRevokeCmd.Flags().Bool("silent", false, "disable text output")
configsTokensCmd.AddCommand(configsTokensRevokeCmd)
}
3 changes: 0 additions & 3 deletions pkg/cmd/enclave_projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,14 @@ func init() {
projectsGetCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
projectsCmd.AddCommand(projectsGetCmd)

projectsCreateCmd.Flags().Bool("silent", false, "disable text output")
projectsCreateCmd.Flags().String("name", "", "project name")
projectsCreateCmd.Flags().String("description", "", "project description")
projectsCmd.AddCommand(projectsCreateCmd)

projectsDeleteCmd.Flags().Bool("silent", false, "disable text output")
projectsDeleteCmd.Flags().Bool("yes", false, "proceed without confirmation")
projectsDeleteCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
projectsCmd.AddCommand(projectsDeleteCmd)

projectsUpdateCmd.Flags().Bool("silent", false, "disable text output")
projectsUpdateCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
projectsUpdateCmd.Flags().String("name", "", "project name")
projectsUpdateCmd.Flags().String("description", "", "project description")
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/enclave_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,11 @@ func init() {
secretsSetCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
secretsSetCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
secretsSetCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables")
secretsSetCmd.Flags().Bool("silent", false, "disable text output")
secretsCmd.AddCommand(secretsSetCmd)

secretsDeleteCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
secretsDeleteCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
secretsDeleteCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables")
secretsDeleteCmd.Flags().Bool("silent", false, "disable text output")
secretsDeleteCmd.Flags().Bool("yes", false, "proceed without confirmation")
secretsCmd.AddCommand(secretsDeleteCmd)

Expand All @@ -296,7 +294,6 @@ func init() {
secretsDownloadCmd.Flags().String("format", "json", "output format. one of [json, env]")
secretsDownloadCmd.Flags().String("passphrase", "", "passphrase to use for encrypting the secrets file. the default passphrase is `$token:$project:$config`.")
secretsDownloadCmd.Flags().Bool("no-file", false, "print the response to stdout")
secretsDownloadCmd.Flags().Bool("silent", false, "disable text output")
secretsCmd.AddCommand(secretsDownloadCmd)

enclaveCmd.AddCommand(secretsCmd)
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/enclave_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ func valueFromEnvironmentNotice(name string) string {
func init() {
setupCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)")
setupCmd.Flags().StringP("config", "c", "", "enclave config (e.g. dev)")
setupCmd.Flags().Bool("silent", false, "disable text output")
setupCmd.Flags().Bool("no-prompt", false, "do not prompt for information. if the project or config is not specified, an error will be thrown.")
setupCmd.Flags().Bool("no-save-token", false, "do not save the token to the config when passed via flag or environment variable.")
enclaveCmd.AddCommand(setupCmd)
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,13 @@ This is an alias of the "logout" command.`,
}

func init() {
loginCmd.Flags().Bool("silent", false, "disable text output")
loginCmd.Flags().Bool("no-copy", false, "do not copy the auth code to the clipboard")
loginCmd.Flags().String("scope", "*", "the directory to scope your token to")

loginRollCmd.Flags().Bool("silent", false, "disable text output")
loginRollCmd.Flags().String("scope", "*", "the directory to scope your token to")
loginRollCmd.Flags().Bool("no-update-config", false, "do not update the rolled token in the config file")
loginCmd.AddCommand(loginRollCmd)

loginRevokeCmd.Flags().Bool("silent", false, "disable text output")
loginRevokeCmd.Flags().String("scope", "*", "the directory to scope your token to")
loginRevokeCmd.Flags().Bool("no-update-config", false, "do not remove the revoked token from the config file")
loginRevokeCmd.Flags().Bool("yes", false, "proceed without confirmation")
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func revokeToken(cmd *cobra.Command, args []string) {
}

func init() {
logoutCmd.Flags().Bool("silent", false, "disable text output")
logoutCmd.Flags().String("scope", "*", "the directory to scope your token to")
logoutCmd.Flags().Bool("no-update-config", false, "do not remove the revoked token from the config file")
logoutCmd.Flags().Bool("yes", false, "proceed without confirmation")
Expand Down
20 changes: 14 additions & 6 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,22 @@ var rootCmd = &cobra.Command{
configuration.LoadConfig()

if utils.Debug {
silent := utils.GetBoolFlagIfChanged(cmd, "silent", false)
if silent {
utils.LogWarning("--silent has no effect when used with --debug")
}

utils.LogDebug("Active configuration")
printer.ScopedConfigSource(configuration.LocalConfig(cmd), false, true)
fmt.Println("")
}

silent := utils.GetBoolFlagIfChanged(cmd, "silent", false)
plain := utils.GetBoolFlagIfChanged(cmd, "plain", false)
canPrintResults := utils.Debug || (!silent && !plain && !utils.OutputJSON)
checkVersion(cmd.CalledAs(), silent, canPrintResults)
// only run version check if we can print the results
// --plain doesn't normally affect logging output, but due to legacy reasons it does here
if utils.CanLogInfo() && !plain {
checkVersion(cmd.CalledAs())
}
},
Run: func(cmd *cobra.Command, args []string) {
err := cmd.Usage()
Expand All @@ -58,13 +65,13 @@ var rootCmd = &cobra.Command{
},
}

func checkVersion(command string, silent bool, print bool) {
func checkVersion(command string) {
// disable version checking on the "run" command and "enclave secrets download" command
if command == "run" || command == "download" {
return
}

if !version.PerformVersionCheck || !print || version.IsDevelopment() {
if !version.PerformVersionCheck || version.IsDevelopment() {
return
}

Expand All @@ -74,7 +81,7 @@ func checkVersion(command string, silent bool, print bool) {
return
}

versionCheck := http.CheckCLIVersion(prevVersionCheck, silent, utils.OutputJSON, utils.Debug)
versionCheck := http.CheckCLIVersion(prevVersionCheck)
if versionCheck == (models.VersionCheck{}) {
return
}
Expand Down Expand Up @@ -133,4 +140,5 @@ func init() {
rootCmd.PersistentFlags().String("configuration", configuration.UserConfigFile, "config file")
rootCmd.PersistentFlags().Bool("json", false, "output json")
rootCmd.PersistentFlags().Bool("debug", false, "output additional information when encountering errors")
rootCmd.PersistentFlags().Bool("silent", false, "disable output of info messages")
}
4 changes: 1 addition & 3 deletions pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ doppler run --command "YOUR_COMMAND && YOUR_OTHER_COMMAND"`,
flags := []string{"fallback", "fallback-only", "fallback-readonly", "no-exit-on-write-failure", "passphrase"}
for _, flag := range flags {
if cmd.Flags().Changed(flag) {
utils.Log(fmt.Sprintf("Warning: --%s has no effect when the fallback file is disabled", flag))
utils.LogWarning(fmt.Sprintf("--%s has no effect when the fallback file is disabled", flag))
}
}
}
Expand Down Expand Up @@ -364,12 +364,10 @@ func init() {
runCmd.Flags().Bool("fallback-readonly", false, "disable modifying the fallback file. secrets can still be read from the file.")
runCmd.Flags().Bool("fallback-only", false, "read all secrets directly from the fallback file, without contacting Doppler. secrets will not be updated. (implies --fallback-readonly)")
runCmd.Flags().Bool("no-exit-on-write-failure", false, "do not exit if unable to write the fallback file")
runCmd.Flags().Bool("silent", false, "disable output of info messages")
runCmd.Flags().Bool("silent-exit", false, "disable error output if the supplied command exits non-zero")
rootCmd.AddCommand(runCmd)

runCleanCmd.Flags().Duration("max-age", defaultFallbackFileMaxAge, "delete fallback files that exceed this age")
runCleanCmd.Flags().Bool("silent", false, "disable output of info messages")
runCleanCmd.Flags().Bool("dry-run", false, "do not delete anything, print what would have happened")
runCmd.AddCommand(runCleanCmd)
}
1 change: 0 additions & 1 deletion pkg/cmd/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ var settingsUpdateCmd = &cobra.Command{
func init() {
settingsUpdateCmd.Flags().String("name", "", "set the workplace's name")
settingsUpdateCmd.Flags().String("email", "", "set the workplace's billing email")
settingsUpdateCmd.Flags().Bool("silent", false, "disable text output")
settingsCmd.AddCommand(settingsUpdateCmd)

rootCmd.AddCommand(settingsCmd)
Expand Down
8 changes: 7 additions & 1 deletion pkg/crypto/aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"time"

"github.com/DopplerHQ/cli/pkg/utils"
"golang.org/x/crypto/pbkdf2"
)

Expand All @@ -43,13 +46,16 @@ func deriveKey(passphrase string, salt []byte) ([]byte, []byte, error) {
return pbkdf2.Key([]byte(passphrase), salt, 50000, 32, sha256.New), salt, nil
}

// Encrypt plaintext with a passphrase; uses pbkdf2 for key deriv and aes-gcm for encryption
// Encrypt plaintext with a passphrase; uses pbkdf2 for key deriv and aes-256-gcm for encryption
func Encrypt(passphrase string, plaintext []byte) (string, error) {
now := time.Now()
key, salt, err := deriveKey(passphrase, nil)
if err != nil {
return "", err
}

utils.LogDebug(fmt.Sprintf("PBKDF2 key derivation took %d ms", time.Now().Sub(now).Milliseconds()))

iv := make([]byte, 12)
// http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
// Section 8.2
Expand Down
2 changes: 1 addition & 1 deletion pkg/http/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func getLatestVersion() (string, error) {
}

// CheckCLIVersion check for updates to the CLI
func CheckCLIVersion(versionCheck models.VersionCheck, silent bool, json bool, debug bool) models.VersionCheck {
func CheckCLIVersion(versionCheck models.VersionCheck) models.VersionCheck {
utils.LogDebug("Checking for latest version of the CLI")
tag, err := getLatestVersion()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func performRequest(req *http.Request, verifyTLS bool, params []queryParam) (int
var errResponse errorResponse
err = json.Unmarshal(body, &errResponse)
if err != nil {
utils.LogDebug(fmt.Sprintf("Unable to parse response body: \n%s", string(body)))
return response.StatusCode, nil, err
}

Expand Down
30 changes: 23 additions & 7 deletions pkg/utils/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,52 @@ import (
"gopkg.in/gookit/color.v1"
)

// Log info to stdout
// Log info message to stdout
func Log(info string) {
silent := Silent || OutputJSON
if Debug || !silent {
if CanLogInfo() {
fmt.Println(info)
}
}

// LogWarning message to stdout
func LogWarning(s string) {
if CanLogInfo() {
fmt.Println(color.Yellow.Render("Warning:"), s)
}
}

// LogError prints an error message to stderr
func LogError(e error) {
silent := Silent || OutputJSON
if Debug || !silent {
if CanLogInfo() {
printError(e)
}
}

// CanLogInfo messages to stdout
func CanLogInfo() bool {
silent := Silent || OutputJSON
return Debug || !silent
}

// LogDebug prints a debug message to stdout
func LogDebug(s string) {
if Debug {
if CanLogDebug() {
fmt.Println(color.Blue.Render("Debug:"), s)
}
}

// LogDebugError prints an error message to stderr when in debug mode
func LogDebugError(e error) {
if Debug {
if CanLogDebug() {
printError(e)
}
}

// CanLogDebug messages to stdout
func CanLogDebug() bool {
return Debug
}

// HandleError prints the error and exits with code 1
func HandleError(e error, messages ...string) {
ErrExit(e, 1, messages...)
Expand Down
2 changes: 1 addition & 1 deletion test/deb.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN apt-get update \
&& apt-get dist-upgrade -y \
&& apt-get install -y sudo gnupg apt-transport-https ca-certificates

RUN sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-keys 379CE192D401AB61 \
RUN sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61 \
&& echo "deb https://dl.bintray.com/dopplerhq/doppler-deb stable main" | sudo tee -a /etc/apt/sources.list \
&& sudo apt-get update \
&& sudo apt-get install -y doppler
Expand Down

0 comments on commit f943ee6

Please sign in to comment.