Skip to content

Commit 0600c4c

Browse files
authored
[secrets] Implement ls, set, rm secrets (#1713)
## Summary Implements `secrets list`, `secrets set`, and `secrets rm`. Removed dependency on envsec binary. Renamed `envsec` commands to `secrets` TODO: Improve envsec interface to avoid having to use embedded struct. ## How was it tested? ``` devbox secrets list devbox secrets set foo=bar devbox secrets set foo=barprod --environment prod devbox run echo $\foo devbox ls --environment prod ```
1 parent 5814521 commit 0600c4c

File tree

12 files changed

+317
-282
lines changed

12 files changed

+317
-282
lines changed

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ require (
3939
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
4040
github.com/wk8/go-ordered-map/v2 v2.1.8
4141
github.com/zealic/go2node v0.1.0
42-
go.jetpack.io/envsec v0.0.14
43-
go.jetpack.io/pkg v0.0.0-20240105000320-7495266e9298
42+
go.jetpack.io/envsec v0.0.16-0.20240109233012-3e97a7fe973f
43+
go.jetpack.io/pkg v0.0.0-20240108193620-a28b84329d15
4444
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc
4545
golang.org/x/mod v0.14.0
4646
golang.org/x/sync v0.5.0
@@ -76,7 +76,7 @@ require (
7676
github.com/bodgit/windows v1.0.0 // indirect
7777
github.com/buger/jsonparser v1.1.1 // indirect
7878
github.com/charmbracelet/lipgloss v0.9.1 // indirect
79-
github.com/cloudflare/circl v1.3.3 // indirect
79+
github.com/cloudflare/circl v1.3.7 // indirect
8080
github.com/codeclysm/extract/v3 v3.1.1 // indirect
8181
github.com/connesc/cipherio v0.2.1 // indirect
8282
github.com/coreos/go-oidc/v3 v3.7.0 // indirect

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
126126
github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184 h1:8yL+85JpbwrIc6m+7N1iYrjn/22z68jwrTIBOJHNe4k=
127127
github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184/go.mod h1:tGWUZLZp9ajsxUOnHmFFLnqnlKXsCn6GReG4jAD59H0=
128128
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
129-
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
130-
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
129+
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
130+
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
131131
github.com/codeclysm/extract/v3 v3.1.1 h1:iHZtdEAwSTqPrd+1n4jfhr1qBhUWtHlMTjT90+fJVXg=
132132
github.com/codeclysm/extract/v3 v3.1.1/go.mod h1:ZJi80UG2JtfHqJI+lgJSCACttZi++dHxfWuPaMhlOfQ=
133133
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
@@ -378,10 +378,10 @@ github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBU
378378
github.com/zaffka/mongodb-boltdb-mock v0.0.0-20221014194232-b4bb03fbe3a0/go.mod h1:GsDD1qsG+86MeeCG7ndi6Ei3iGthKL3wQ7PTFigDfNY=
379379
github.com/zealic/go2node v0.1.0 h1:ofxpve08cmLJBwFdI0lPCk9jfwGWOSD+s6216x0oAaA=
380380
github.com/zealic/go2node v0.1.0/go.mod h1:GrkFr+HctXwP7vzcU9RsgtAeJjTQ6Ud0IPCQAqpTfBg=
381-
go.jetpack.io/envsec v0.0.14 h1:lUrCQzqqxPxvju1vJzk4XVX7ZEkvJC39CGDOMD7R+U0=
382-
go.jetpack.io/envsec v0.0.14/go.mod h1:1/39qYH1kaYUEFCt0E6ZdbKZCCbipzdbl/N9MTNvS+0=
383-
go.jetpack.io/pkg v0.0.0-20240105000320-7495266e9298 h1:gVrmcVJ2MPKrjnZHJ/Zx4jFpebhze1+EHxSBgMy9JnU=
384-
go.jetpack.io/pkg v0.0.0-20240105000320-7495266e9298/go.mod h1:3bunF5jJUIXf8vWXvu4PHWfHuDj3hgzOyhTXeoBH8Dk=
381+
go.jetpack.io/envsec v0.0.16-0.20240109233012-3e97a7fe973f h1:ELgyeQw+eZn0BSSlhLnBkC7wTrYbluTsYx6vPa0YTds=
382+
go.jetpack.io/envsec v0.0.16-0.20240109233012-3e97a7fe973f/go.mod h1:8U0fUaXMaoNRqz8J7VaV8kP7N7hayJ9tqOd9OS0epEQ=
383+
go.jetpack.io/pkg v0.0.0-20240108193620-a28b84329d15 h1:ztX3CydpNKLePPMRmWgdi4HcxE/AXY6HViOJOmmYNiA=
384+
go.jetpack.io/pkg v0.0.0-20240108193620-a28b84329d15/go.mod h1:kGUL8aZ7ddvoGro0AQxXos9GKn5Qw0J18qW7d5FP4Ws=
385385
go.jetpack.io/typeid v1.0.0 h1:8gQ+iYGdyiQ0Pr40ydSB/PzMOIwlXX5DTojp1CBeSPQ=
386386
go.jetpack.io/typeid v1.0.0/go.mod h1:+UPEaECUgFxgAjFPn5Yf9eO/3ft/3xZ98Eahv9JW/GQ=
387387
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=

internal/boxcli/auth.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import (
1010

1111
"github.com/spf13/cobra"
1212
"go.jetpack.io/devbox/internal/build"
13-
"go.jetpack.io/devbox/internal/integrations/envsec"
13+
"go.jetpack.io/devbox/internal/devbox"
14+
"go.jetpack.io/devbox/internal/devbox/devopt"
1415
"go.jetpack.io/pkg/auth"
1516
"go.jetpack.io/pkg/auth/session"
1617
)
@@ -84,8 +85,15 @@ func whoAmICmd() *cobra.Command {
8485
if err != nil {
8586
return err
8687
}
87-
return envsec.DefaultEnvsec(cmd.ErrOrStderr(), wd).
88-
WhoAmI(cmd.Context(), cmd.OutOrStdout(), false)
88+
box, err := devbox.Open(&devopt.Opts{Dir: wd, Stderr: cmd.ErrOrStderr()})
89+
if err != nil {
90+
return err
91+
}
92+
secrets, err := box.Secrets(cmd.Context())
93+
if err != nil {
94+
return err
95+
}
96+
return secrets.WhoAmI(cmd.Context(), cmd.OutOrStdout(), false)
8997
},
9098
}
9199

internal/boxcli/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func (flags *configFlags) register(cmd *cobra.Command) {
1818
&flags.path, "config", "c", "", "path to directory containing a devbox.json config file",
1919
)
2020
cmd.Flags().StringVar(
21-
&flags.environment, "environment", "dev", "environment to use, when supported (e.g. envsec supports dev, prod, preview.)",
21+
&flags.environment, "environment", "dev", "environment to use, when supported (e.g.secrets support dev, prod, preview.)",
2222
)
2323
}
2424

@@ -27,7 +27,7 @@ func (flags *configFlags) registerPersistent(cmd *cobra.Command) {
2727
&flags.path, "config", "c", "", "path to directory containing a devbox.json config file",
2828
)
2929
cmd.PersistentFlags().StringVar(
30-
&flags.environment, "environment", "dev", "environment to use, when supported (e.g. envsec supports dev, prod, preview.)",
30+
&flags.environment, "environment", "dev", "environment to use, when supported (e.g. secrets support dev, prod, preview.)",
3131
)
3232
}
3333

internal/boxcli/envsec.go

Lines changed: 0 additions & 67 deletions
This file was deleted.

internal/boxcli/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func RootCmd() *cobra.Command {
6161
command.AddCommand(authCmd())
6262
}
6363
command.AddCommand(createCmd())
64-
command.AddCommand(envsecCmd())
64+
command.AddCommand(secretsCmd())
6565
command.AddCommand(generateCmd())
6666
command.AddCommand(globalCmd())
6767
command.AddCommand(infoCmd())

internal/boxcli/secrets.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
2+
// Use of this source code is governed by the license in the LICENSE file.
3+
4+
package boxcli
5+
6+
import (
7+
"github.com/pkg/errors"
8+
"github.com/spf13/cobra"
9+
"go.jetpack.io/devbox/internal/devbox"
10+
"go.jetpack.io/devbox/internal/devbox/devopt"
11+
"go.jetpack.io/envsec/pkg/envsec"
12+
)
13+
14+
type secretsFlags struct {
15+
config configFlags
16+
}
17+
18+
type secretsInitCmdFlags struct {
19+
force bool
20+
}
21+
22+
type secretsListFlags struct {
23+
show bool
24+
format string
25+
}
26+
27+
func secretsCmd() *cobra.Command {
28+
flags := &secretsFlags{}
29+
cmd := &cobra.Command{
30+
Use: "secrets",
31+
Aliases: []string{"envsec"},
32+
Short: "Interact with devbox secrets in jetpack cloud.",
33+
PersistentPreRunE: ensureNixInstalled,
34+
}
35+
cmd.AddCommand(secretsInitCmd(flags))
36+
cmd.AddCommand(secretsListCmd(flags))
37+
cmd.AddCommand(secretsRemoveCmd(flags))
38+
cmd.AddCommand(secretsSetCmd(flags))
39+
cmd.Hidden = true
40+
41+
flags.config.registerPersistent(cmd)
42+
43+
return cmd
44+
}
45+
46+
func secretsInitCmd(secretsFlags *secretsFlags) *cobra.Command {
47+
flags := secretsInitCmdFlags{}
48+
cmd := &cobra.Command{
49+
Use: "init",
50+
Short: "Initialize secrets management with jetpack cloud",
51+
Args: cobra.ExactArgs(0),
52+
RunE: func(cmd *cobra.Command, args []string) error {
53+
return secretsInitFunc(cmd, flags, secretsFlags)
54+
},
55+
}
56+
57+
cmd.Flags().BoolVarP(
58+
&flags.force,
59+
"force",
60+
"f",
61+
false,
62+
"Force initialization even if already initialized",
63+
)
64+
65+
return cmd
66+
}
67+
68+
func secretsSetCmd(flags *secretsFlags) *cobra.Command {
69+
return &cobra.Command{
70+
Use: "set <NAME1>=<value1> [<NAME2>=<value2>]...",
71+
Short: "Securely store one or more environment variables",
72+
Long: "Securely store one or more environment variables. To test contents of a file as a secret use set=@<file>",
73+
Args: cobra.MinimumNArgs(1),
74+
PreRunE: func(cmd *cobra.Command, args []string) error {
75+
return envsec.ValidateSetArgs(args)
76+
},
77+
RunE: func(cmd *cobra.Command, args []string) error {
78+
ctx := cmd.Context()
79+
box, err := devbox.Open(&devopt.Opts{
80+
Dir: flags.config.path,
81+
Environment: flags.config.environment,
82+
Stderr: cmd.ErrOrStderr(),
83+
})
84+
if err != nil {
85+
return errors.WithStack(err)
86+
}
87+
88+
secrets, err := box.Secrets(ctx)
89+
if err != nil {
90+
return errors.WithStack(err)
91+
}
92+
93+
envID, err := secrets.EnvID()
94+
if err != nil {
95+
return errors.WithStack(err)
96+
}
97+
98+
return secrets.SetFromArgs(ctx, envID, args)
99+
},
100+
}
101+
}
102+
103+
func secretsRemoveCmd(flags *secretsFlags) *cobra.Command {
104+
return &cobra.Command{
105+
Use: "remove <NAME1> [<NAME2>]...",
106+
Short: "Remove one or more environment variables",
107+
Aliases: []string{"rm"},
108+
Args: cobra.MinimumNArgs(1),
109+
RunE: func(cmd *cobra.Command, args []string) error {
110+
ctx := cmd.Context()
111+
box, err := devbox.Open(&devopt.Opts{
112+
Dir: flags.config.path,
113+
Environment: flags.config.environment,
114+
Stderr: cmd.ErrOrStderr(),
115+
})
116+
if err != nil {
117+
return errors.WithStack(err)
118+
}
119+
120+
secrets, err := box.Secrets(ctx)
121+
if err != nil {
122+
return errors.WithStack(err)
123+
}
124+
125+
envID, err := secrets.EnvID()
126+
if err != nil {
127+
return errors.WithStack(err)
128+
}
129+
130+
return secrets.DeleteAll(ctx, envID, args...)
131+
},
132+
}
133+
}
134+
135+
func secretsListCmd(commonFlags *secretsFlags) *cobra.Command {
136+
flags := secretsListFlags{}
137+
cmd := &cobra.Command{
138+
Use: "list",
139+
Aliases: []string{"ls"},
140+
Short: "List all secrets",
141+
Args: cobra.ExactArgs(0),
142+
RunE: func(cmd *cobra.Command, args []string) error {
143+
ctx := cmd.Context()
144+
box, err := devbox.Open(&devopt.Opts{
145+
Dir: commonFlags.config.path,
146+
Environment: commonFlags.config.environment,
147+
Stderr: cmd.ErrOrStderr(),
148+
})
149+
if err != nil {
150+
return errors.WithStack(err)
151+
}
152+
153+
secrets, err := box.Secrets(ctx)
154+
if err != nil {
155+
return errors.WithStack(err)
156+
}
157+
158+
envID, err := secrets.EnvID()
159+
if err != nil {
160+
return errors.WithStack(err)
161+
}
162+
163+
vars, err := secrets.List(ctx, envID)
164+
if err != nil {
165+
return err
166+
}
167+
168+
return envsec.PrintEnvVars(
169+
vars, cmd.OutOrStdout(), flags.show, flags.format)
170+
},
171+
}
172+
173+
cmd.Flags().BoolVarP(
174+
&flags.show,
175+
"show",
176+
"s",
177+
false,
178+
"Display secret values in plaintext",
179+
)
180+
cmd.Flags().StringVarP(
181+
&flags.format,
182+
"format",
183+
"f",
184+
"table",
185+
"Display the key values of each secret in the specified format, one of: table | dotenv | json.",
186+
)
187+
return cmd
188+
}
189+
190+
func secretsInitFunc(
191+
cmd *cobra.Command,
192+
flags secretsInitCmdFlags,
193+
secretsFlags *secretsFlags,
194+
) error {
195+
ctx := cmd.Context()
196+
box, err := devbox.Open(&devopt.Opts{
197+
Dir: secretsFlags.config.path,
198+
Stderr: cmd.ErrOrStderr(),
199+
})
200+
if err != nil {
201+
return errors.WithStack(err)
202+
}
203+
secrets, err := box.Secrets(ctx)
204+
if err != nil {
205+
return errors.WithStack(err)
206+
}
207+
if err := secrets.NewProject(ctx, flags.force); err != nil {
208+
return errors.WithStack(err)
209+
}
210+
box.Config().SetStringField("EnvFrom", "envsec")
211+
return box.Config().SaveTo(box.ProjectDir())
212+
}

0 commit comments

Comments
 (0)