Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #383 from secrethub/release/v0.42.1
Browse files Browse the repository at this point in the history
Release v0.42.1
  • Loading branch information
SimonBarendse authored May 3, 2021
2 parents 3ebaa66 + cfef938 commit 00f0ba6
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 104 deletions.
20 changes: 14 additions & 6 deletions internals/secrethub/clear_clipboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"golang.org/x/crypto/bcrypt"
)

// defaultClearClipboardAfter defines the default TTL for data written to the clipboard.
const defaultClearClipboardAfter = 45 * time.Second
// clearClipboardAfter defines the TTL for data written to the clipboard.
const clearClipboardAfter = 45 * time.Second

// ClearClipboardCommand is a command to clear the contents of the clipboard after some time passed.
type ClearClipboardCommand struct {
Expand Down Expand Up @@ -62,21 +62,29 @@ func (cmd *ClearClipboardCommand) Run() error {
return nil
}

// WriteClipboardAutoClear writes data to the clipboard and clears it after the timeout.
func WriteClipboardAutoClear(data []byte, timeout time.Duration, clipper clip.Clipper) error {
type ClipboardWriter interface {
Write(data []byte) error
}

type ClipboardWriterAutoClear struct {
clipper clip.Clipper
}

// Write writes data to the clipboard and clears it after the timeout.
func (clipWriter *ClipboardWriterAutoClear) Write(data []byte) error {
hash, err := bcrypt.GenerateFromPassword(data, bcrypt.DefaultCost)
if err != nil {
return err
}

err = clipper.WriteAll(data)
err = clipWriter.clipper.WriteAll(data)
if err != nil {
return err
}

err = cloneproc.Spawn(
"clipboard-clear", hex.EncodeToString(hash),
"--timeout", timeout.String())
"--timeout", clearClipboardAfter.String())

return err
}
12 changes: 12 additions & 0 deletions internals/secrethub/clear_clipboard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package secrethub

import "bytes"

type FakeClipboardWriter struct {
Buffer bytes.Buffer
}

func (clipWriter *FakeClipboardWriter) Write(data []byte) error {
_, err := clipWriter.Buffer.Write(data)
return err
}
41 changes: 20 additions & 21 deletions internals/secrethub/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"
"strconv"
"strings"
"time"

"github.com/secrethub/secrethub-cli/internals/cli"
"github.com/secrethub/secrethub-cli/internals/cli/clip"
Expand Down Expand Up @@ -35,28 +34,28 @@ const defaultLength = 22

// GenerateSecretCommand generates a new secret and writes to the output path.
type GenerateSecretCommand struct {
symbolsFlag bool
generator randchar.Generator
io ui.IO
lengthFlag intValue
firstArg cli.StringValue
secondArg cli.StringValue
lengthArg intValue
charsetFlag charsetValue
mins minRuleValue
copyToClipboard bool
clearClipboardAfter time.Duration
clipper clip.Clipper
newClient newClientFunc
symbolsFlag bool
generator randchar.Generator
io ui.IO
lengthFlag intValue
firstArg cli.StringValue
secondArg cli.StringValue
lengthArg intValue
charsetFlag charsetValue
mins minRuleValue
copyToClipboard bool
newClient newClientFunc
clipWriter ClipboardWriter
}

// NewGenerateSecretCommand creates a new GenerateSecretCommand.
func NewGenerateSecretCommand(io ui.IO, newClient newClientFunc) *GenerateSecretCommand {
return &GenerateSecretCommand{
io: io,
newClient: newClient,
clearClipboardAfter: defaultClearClipboardAfter,
clipper: clip.NewClipboard(),
io: io,
newClient: newClient,
clipWriter: &ClipboardWriterAutoClear{
clipper: clip.NewClipboard(),
},
}
}

Expand All @@ -66,7 +65,7 @@ func (cmd *GenerateSecretCommand) Register(r cli.Registerer) {
clause.Flags().VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret.")
clause.Cmd.Flag("length").DefValue = strconv.Itoa(defaultLength)
clause.Flags().Var(&cmd.mins, "min", "<charset>:<n> Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.")
clause.Flags().BoolVarP(&cmd.copyToClipboard, "clip", "c", false, "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".")
clause.Flags().BoolVarP(&cmd.copyToClipboard, "clip", "c", false, "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(clearClipboardAfter)+".")
_ = cmd.charsetFlag.Set("alphanumeric")
clause.Flags().Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list.")
clause.Cmd.Flag("charset").DefValue = "alphanumeric"
Expand Down Expand Up @@ -147,15 +146,15 @@ func (cmd *GenerateSecretCommand) run() error {
fmt.Fprintf(cmd.io.Output(), "A randomly generated secret has been written to %s:%d.\n", path, version.Version)

if cmd.copyToClipboard {
err = WriteClipboardAutoClear(data, cmd.clearClipboardAfter, cmd.clipper)
err = cmd.clipWriter.Write(data)
if err != nil {
return err
}

fmt.Fprintf(
cmd.io.Output(),
"The generated value has been copied to the clipboard. It will be cleared after %s.\n",
units.HumanDuration(cmd.clearClipboardAfter),
units.HumanDuration(clearClipboardAfter),
)
}

Expand Down
22 changes: 5 additions & 17 deletions internals/secrethub/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/secrethub/secrethub-cli/internals/cli"
"github.com/secrethub/secrethub-cli/internals/cli/clip/fakeclip"
"github.com/secrethub/secrethub-cli/internals/cli/ui/fakeui"

"github.com/secrethub/secrethub-go/internals/api"
Expand Down Expand Up @@ -42,7 +41,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
Err: nil,
},
firstArg: cli.StringValue{Value: testPath},
clipper: fakeclip.New(),
},
writeFunc: func(path string, data []byte) (*api.SecretVersion, error) {
return &api.SecretVersion{Version: 1}, nil
Expand All @@ -60,7 +58,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
},
firstArg: cli.StringValue{Value: testPath},
copyToClipboard: true,
clipper: fakeclip.New(),
},
writeFunc: func(path string, data []byte) (*api.SecretVersion, error) {
return &api.SecretVersion{Version: 1}, nil
Expand All @@ -69,7 +66,7 @@ func TestGenerateSecretCommand_run(t *testing.T) {
data: testData,
expectedClip: testData,
expectedOut: "A randomly generated secret has been written to namespace/repo/secret:1.\n" +
"The generated value has been copied to the clipboard. It will be cleared after Less than a second.\n",
"The generated value has been copied to the clipboard. It will be cleared after 45 seconds.\n",
},
"length flag": {
cmd: GenerateSecretCommand{
Expand All @@ -79,7 +76,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
},
firstArg: cli.StringValue{Value: testPath},
lengthFlag: newIntValue(24),
clipper: fakeclip.New(),
},
writeFunc: func(path string, data []byte) (*api.SecretVersion, error) {
return &api.SecretVersion{Version: 1}, nil
Expand All @@ -99,7 +95,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
secondArg: cli.StringValue{Value: testPath},
lengthFlag: newIntValue(24),
lengthArg: newIntValue(24),
clipper: fakeclip.New(),
},
expectedErr: ErrCannotUseLengthArgAndFlag,
},
Expand All @@ -112,7 +107,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
firstArg: cli.StringValue{Value: "rand"},
secondArg: cli.StringValue{Value: testPath},
lengthArg: newIntValue(23),
clipper: fakeclip.New(),
},
writeFunc: func(path string, data []byte) (*api.SecretVersion, error) {
return &api.SecretVersion{Version: 1}, nil
Expand All @@ -127,7 +121,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
firstArg: cli.StringValue{Value: "rand"},
secondArg: cli.StringValue{Value: testPath},
lengthArg: newIntValue(0),
clipper: fakeclip.New(),
},
expectedErr: ErrInvalidRandLength,
expectedOut: "",
Expand All @@ -137,7 +130,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
firstArg: cli.StringValue{Value: "rand"},
secondArg: cli.StringValue{Value: testPath},
lengthArg: newIntValue(-1),
clipper: fakeclip.New(),
},
expectedErr: ErrInvalidRandLength,
expectedOut: "",
Expand All @@ -147,7 +139,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
cmd: GenerateSecretCommand{
firstArg: cli.StringValue{Value: testPath},
lengthArg: newIntValue(24),
clipper: fakeclip.New(),
},
expectedErr: errors.New("unexpected 24"),
},
Expand All @@ -156,7 +147,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
cmd: GenerateSecretCommand{
firstArg: cli.StringValue{Value: testPath},
secondArg: cli.StringValue{Value: "namespace/repo/secret2"},
clipper: fakeclip.New(),
},
expectedErr: errors.New("unexpected namespace/repo/secret2"),
},
Expand All @@ -167,7 +157,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
Err: testErr,
},
firstArg: cli.StringValue{Value: testPath},
clipper: fakeclip.New(),
},
expectedErr: testErr,
},
Expand All @@ -178,7 +167,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
Err: nil,
},
firstArg: cli.StringValue{Value: testPath},
clipper: fakeclip.New(),
},
newClientErr: testErr,
expectedErr: testErr,
Expand All @@ -190,7 +178,6 @@ func TestGenerateSecretCommand_run(t *testing.T) {
Err: nil,
},
firstArg: cli.StringValue{Value: testPath},
clipper: fakeclip.New(),
},
writeFunc: func(path string, data []byte) (*api.SecretVersion, error) {
return nil, testErr
Expand All @@ -210,6 +197,9 @@ func TestGenerateSecretCommand_run(t *testing.T) {
testIO := fakeui.NewIO(t)
tc.cmd.io = testIO

clipWriter := &FakeClipboardWriter{}
tc.cmd.clipWriter = clipWriter

tc.cmd.newClient = func() (secrethub.ClientInterface, error) {
return fakeclient.Client{
SecretService: &fakeclient.SecretService{
Expand All @@ -224,14 +214,12 @@ func TestGenerateSecretCommand_run(t *testing.T) {

// Act
err := tc.cmd.run()
resClip, clipErr := tc.cmd.clipper.ReadAll()

// Assert
assert.OK(t, clipErr)
assert.Equal(t, err, tc.expectedErr)
assert.Equal(t, argPath, tc.path)
assert.Equal(t, argData, tc.data)
assert.Equal(t, resClip, tc.expectedClip)
assert.Equal(t, clipWriter.Buffer.Bytes(), tc.expectedClip)
assert.Equal(t, testIO.Out.String(), tc.expectedOut)
})
}
Expand Down
25 changes: 12 additions & 13 deletions internals/secrethub/inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"time"

"github.com/secrethub/secrethub-cli/internals/cli"
"github.com/secrethub/secrethub-cli/internals/cli/clip"
Expand All @@ -31,8 +30,7 @@ type InjectCommand struct {
force bool
io ui.IO
useClipboard bool
clearClipboardAfter time.Duration
clipper clip.Clipper
clipWriter ClipboardWriter
osEnv []string
newClient newClientFunc
templateVars map[string]string
Expand All @@ -43,13 +41,14 @@ type InjectCommand struct {
// NewInjectCommand creates a new InjectCommand.
func NewInjectCommand(io ui.IO, newClient newClientFunc) *InjectCommand {
return &InjectCommand{
clipper: clip.NewClipboard(),
osEnv: os.Environ(),
clearClipboardAfter: defaultClearClipboardAfter,
io: io,
newClient: newClient,
templateVars: make(map[string]string),
fileMode: filemode.New(0600),
clipWriter: &ClipboardWriterAutoClear{
clipper: clip.NewClipboard(),
},
osEnv: os.Environ(),
io: io,
newClient: newClient,
templateVars: make(map[string]string),
fileMode: filemode.New(0600),
}
}

Expand All @@ -61,7 +60,7 @@ func (cmd *InjectCommand) Register(r cli.Registerer) {
"clip", "c", false,
fmt.Sprintf(
"Copy the injected template to the clipboard instead of stdout. The clipboard is automatically cleared after %s.",
units.HumanDuration(cmd.clearClipboardAfter),
units.HumanDuration(clearClipboardAfter),
))
clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "The filename of a template file to inject.")
clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the injected template to a file instead of stdout.")
Expand Down Expand Up @@ -131,12 +130,12 @@ func (cmd *InjectCommand) Run() error {

out := []byte(injected)
if cmd.useClipboard {
err = WriteClipboardAutoClear(out, cmd.clearClipboardAfter, cmd.clipper)
err = cmd.clipWriter.Write(out)
if err != nil {
return err
}

_, err = fmt.Fprintf(cmd.io.Output(), "Copied injected template to clipboard. It will be cleared after %s.\n", units.HumanDuration(cmd.clearClipboardAfter))
_, err = fmt.Fprintf(cmd.io.Output(), "Copied injected template to clipboard. It will be cleared after %s.\n", units.HumanDuration(clearClipboardAfter))
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internals/secrethub/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ func (cmd *MigratePlanCommand) addDirToPlan(client secrethub.ClientInterface, pa
fmt.Fprintf(cmd.io.Output(), "Planning migration for %s\n", path)

tree, err := client.Dirs().GetTree(path, -1, false)
if err == api.ErrForbidden {
fmt.Fprintf(os.Stderr, "WARN: Skipping %s because you do not have read access. ", path)
if err == api.ErrForbidden || api.IsErrNotFound(err) {
fmt.Fprintf(os.Stderr, "WARN: Skipping '%s' because you do not have read access. ", path)
accessLevels, err := client.AccessRules().ListLevels(path)
if err == nil {
var usernames []string
Expand Down
Loading

0 comments on commit 00f0ba6

Please sign in to comment.