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

feat: support pass cred store #1070

Open
wants to merge 1 commit into
base: linux
Choose a base branch
from
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/finch/main_native.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ var newApp = func(
newVersionCommand(ncc, logger, stdOut),
newSupportBundleCommand(logger, supportBundleBuilder, ncc),
newGenDocsCommand(rootCmd, logger, fs, system.NewStdLib()),
newPlatformCommand(ncc, logger),
)

rootCmd.AddCommand(allCommands...)
Expand Down
1 change: 1 addition & 0 deletions cmd/finch/main_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ var newApp = func(
virtualMachineCommands(logger, fp, ncc, ecc, fs, fc, home, finchRootPath),
newSupportBundleCommand(logger, supportBundleBuilder, ncc),
newGenDocsCommand(rootCmd, logger, fs, system.NewStdLib()),
newPlatformCommand(ncc, logger),
)

rootCmd.AddCommand(allCommands...)
Expand Down
2 changes: 1 addition & 1 deletion cmd/finch/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func TestNewApp(t *testing.T) {
assert.Equal(t, cmd.SilenceUsage, true)
assert.Equal(t, cmd.SilenceErrors, true)
// confirm the number of command, comprised of nerdctl commands + finch commands
assert.Equal(t, len(cmd.Commands()), len(nerdctlCmds)+4)
assert.Equal(t, len(cmd.Commands()), len(nerdctlCmds)+5)

// PersistentPreRunE should set logger level to debug if the debug flag exists.
mockCmd := &cobra.Command{}
Expand Down
25 changes: 25 additions & 0 deletions cmd/finch/pass_init_native.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//go:build linux

package main

import (
"github.com/gopasspw/gopass/pkg/pwgen"
"github.com/runfinch/finch/pkg/command"
)

func (pia *passInitAction) initGpgKey() command.Command {
passphrase := pwgen.GeneratePassword(passphraseLength, true)
Copy link
Member

Choose a reason for hiding this comment

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

Since we're not even asking users to enter a passphrase, can't we do this behind the scenes? Should we instead have a mechanism that initializes the cred store whenever a user modifies their creds_helpers to include pass?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

deletion is problematic,
i would prefer not taking responsibility of key management, if its done with a command customer has responsibility to manage key lifecycle.

Copy link
Member

Choose a reason for hiding this comment

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

We can still have the commands, but if the commands require 0 user input, I don't see the harm in doing it for them

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i still feel if we create it the lifecycle is on us to manage for example key rotation etc. if it is automatically done finch has to won the management of the key.

Copy link
Member

Choose a reason for hiding this comment

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

What's the purpose of key rotation for a key where we don't even care about the password?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if the key is compromised, we probably want to rotate it, and having set time to rotate it probably makes it harder to breach within certain time period.

ecc := command.NewExecCmdCreator()
cmd := ecc.Create(
"gpg2", "--batch", "--passphrase", passphrase, "--quick-gen-key", "finch")
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this key expire after some default period?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

key doesnt expire, the key creation is owned by the customer so they would need to remove it.

return cmd
}

func (pia *passInitAction) passInit() command.Command {
ecc := command.NewExecCmdCreator()
cmd := ecc.Create("pass", "init", "finch")
return cmd
}
21 changes: 21 additions & 0 deletions cmd/finch/pass_init_remote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//go:build darwin || windows

package main

import (
"github.com/gopasspw/gopass/pkg/pwgen"
"github.com/runfinch/finch/pkg/command"
)

func (pia *passInitAction) initGpgKey() command.Command {
passphrase := pwgen.GeneratePassword(passphraseLength, true)
return pia.creator.CreateWithoutStdio("shell", limaInstanceName, "sudo", "-E",
"gpg2", "--batch", "--passphrase", passphrase, "--quick-gen-key", "finch")
}

func (pia *passInitAction) passInit() command.Command {
return pia.creator.CreateWithoutStdio("shell", limaInstanceName, "sudo", "-E", "pass", "init", "finch")
}
22 changes: 22 additions & 0 deletions cmd/finch/platform.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"github.com/spf13/cobra"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/flog"
)

func newPlatformCommand(
limaCmdCreator command.NerdctlCmdCreator,
logger flog.Logger,
) *cobra.Command {
systemCommand := &cobra.Command{
Use: "platform",
Short: "Manage platform settings",
}
systemCommand.AddCommand(newPassInit(limaCmdCreator, logger),
newPassDelete(limaCmdCreator, logger))

return systemCommand
}
50 changes: 50 additions & 0 deletions cmd/finch/platform_init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"github.com/spf13/cobra"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/flog"
)

func newPassInit(limaCmdCreator command.NerdctlCmdCreator, logger flog.Logger) *cobra.Command {
passInitCommand := &cobra.Command{
Use: "pass-init",
Short: "Initialize the pass",
RunE: newPassInitAction(limaCmdCreator, logger).runAdapter,
}

return passInitCommand
}

const passphraseLength = 16

type passInitAction struct {
creator command.NerdctlCmdCreator
logger flog.Logger
}

func newPassInitAction(creator command.NerdctlCmdCreator, logger flog.Logger) *passInitAction {
return &passInitAction{creator: creator, logger: logger}
}

func (pia *passInitAction) runAdapter(_ *cobra.Command, _ []string) error {
return pia.run()
}

func (pia *passInitAction) run() error {
return pia.init()
}

func (pia *passInitAction) init() error {
cmd := pia.initGpgKey()
err := cmd.Run()
if err != nil {
return err
}
cmd = pia.passInit()
return cmd.Run()
}
47 changes: 47 additions & 0 deletions cmd/finch/platform_pass_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"github.com/spf13/cobra"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/flog"
)

func newPassDelete(limaCmdCreator command.NerdctlCmdCreator, logger flog.Logger) *cobra.Command {
passDeleteCommand := &cobra.Command{
Use: "pass-delete",
Short: "Delete the pass key",
RunE: newPassDeleteAction(limaCmdCreator, logger).runAdapter,
}
return passDeleteCommand
}

type passDeleteAction struct {
creator command.NerdctlCmdCreator
logger flog.Logger
}

func newPassDeleteAction(creator command.NerdctlCmdCreator, logger flog.Logger) *passDeleteAction {
return &passDeleteAction{creator: creator, logger: logger}
}

func (pda *passDeleteAction) runAdapter(_ *cobra.Command, _ []string) error {
return pda.run()
}

func (pda *passDeleteAction) run() error {
return pda.delete()
}

func (pda *passDeleteAction) delete() error {
cmd := pda.removePass()
err := cmd.Run()
if err != nil {
pda.logger.Warnf("cannot perform pass remove action")
}
cmd = pda.removePassKey()
return cmd.Run()
}
30 changes: 30 additions & 0 deletions cmd/finch/platform_pass_delete_native.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//go:build linux

package main

import (
"os"

"github.com/runfinch/finch/pkg/command"
)

func (pda *passDeleteAction) removePassKey() command.Command {
ecc := command.NewExecCmdCreator()

cmd := ecc.Create("gpg2", "--yes", "--delete-secret-and-public-key", "finch")
cmd.SetStdin(os.Stdin)
cmd.SetStdout(os.Stdout)
return cmd
}

func (pda *passDeleteAction) removePass() command.Command {
ecc := command.NewExecCmdCreator()

cmd := ecc.Create("pass", "rm", "finch")
cmd.SetStdin(os.Stdin)
cmd.SetStdout(os.Stdout)
return cmd
}
20 changes: 20 additions & 0 deletions cmd/finch/platform_pass_delete_remote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//go:build darwin || windows

package main

import (
"github.com/runfinch/finch/pkg/command"
)

func (pda *passDeleteAction) removePassKey() command.Command {
return pda.creator.Create("shell", limaInstanceName, "sudo", "-E",
"gpg2", "--yes", "--delete-secret-and-public-key", "finch")
}

func (pda *passDeleteAction) removePass() command.Command {
return pda.creator.Create("shell", limaInstanceName, "sudo", "-E",
"pass", "rm", "finch")
}
22 changes: 22 additions & 0 deletions e2e/vm/platform_pass_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package vm

import (
"github.com/onsi/ginkgo/v2"
"github.com/runfinch/common-tests/command"
"github.com/runfinch/common-tests/option"
)

var testPlatform = func(o *option.Option) {
ginkgo.Describe("Platform", func() {
ginkgo.BeforeEach(func() {
command.New(o, "platform", "pass-delete").WithoutCheckingExitCode().WithTimeoutInSeconds(90).Run()
})
ginkgo.It("Pass Init and deletion are Successful", func() {
command.New(o, "platform", "pass-init").Run()
command.New(o, "platform", "pass-delete").Run()
})
})
}
1 change: 1 addition & 0 deletions e2e/vm/vm_darwin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestVM(t *testing.T) {
testSupportBundle(o)
testCredHelper(o, *e2e.Installed, *e2e.Registry)
testSoci(o, *e2e.Installed)
testPlatform(o)
})

gomega.RegisterFailHandler(ginkgo.Fail)
Expand Down
1 change: 1 addition & 0 deletions e2e/vm/vm_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func TestVM(t *testing.T) {
testSupportBundle(o)
testCredHelper(o, *e2e.Installed, *e2e.Registry)
testSoci(o, *e2e.Installed)
testPlatform(o)
})

gomega.RegisterFailHandler(ginkgo.Fail)
Expand Down
15 changes: 10 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
module github.com/runfinch/finch

go 1.22.0
go 1.22.1

toolchain go1.22.5

require (
github.com/aws/aws-sdk-go-v2 v1.30.3
github.com/docker/cli v27.1.0+incompatible
github.com/docker/docker v27.0.3+incompatible
github.com/golang/mock v1.6.0
github.com/google/go-licenses v1.6.1-0.20230903011517-706b9c60edd4
github.com/gopasspw/gopass v1.15.13
github.com/lima-vm/lima v0.22.0
github.com/onsi/ginkgo/v2 v2.19.0
github.com/onsi/gomega v1.33.1
Expand All @@ -22,14 +25,15 @@ require (
github.com/tc-hib/go-winres v0.3.3
github.com/xorcare/pointer v1.2.2
golang.org/x/crypto v0.25.0
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0
golang.org/x/tools v0.23.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/apimachinery v0.30.3
)

require (
github.com/aws/smithy-go v1.20.3 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/containerd/containerd v1.7.16 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
Expand All @@ -40,9 +44,11 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/licenseclassifier/v2 v2.0.0 // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/lima-vm/go-qcow2reader v0.1.1 // indirect
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/muesli/crunchy v0.4.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/opencontainers/image-spec v1.1.0-rc6 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand All @@ -52,8 +58,8 @@ require (
github.com/tc-hib/winres v0.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/urfave/cli/v2 v2.25.7 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/urfave/cli/v2 v2.27.1 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/sync v0.7.0 // indirect
Expand Down Expand Up @@ -86,6 +92,5 @@ require (
golang.org/x/sys v0.22.0
golang.org/x/text v0.16.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
k8s.io/klog/v2 v2.120.1 // indirect
)
Loading