-
-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Knut Ahlers <knut@ahlers.me>
- Loading branch information
Showing
6 changed files
with
291 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"mime" | ||
"os" | ||
"path" | ||
|
||
"github.com/Luzifer/ots/pkg/client" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var createCmd = &cobra.Command{ | ||
Use: "create [-f file]... [--instance url] [--secret-from file]", | ||
Short: "Create a new encrypted secret in the given OTS instance", | ||
Long: "", | ||
Example: `echo "I'm a very secret secret" | ots-cli create`, | ||
Args: cobra.NoArgs, | ||
RunE: createRunE, | ||
} | ||
|
||
func init() { | ||
createCmd.Flags().Duration("expire", 0, "When to expire the secret (0 to use server-default)") | ||
createCmd.Flags().String("instance", "https://ots.fyi/", "Instance to create the secret with") | ||
createCmd.Flags().StringSliceP("file", "f", nil, "File(s) to attach to the secret") | ||
createCmd.Flags().String("secret-from", "-", `File to read the secret content from ("-" for STDIN)`) | ||
rootCmd.AddCommand(createCmd) | ||
} | ||
|
||
func createRunE(cmd *cobra.Command, _ []string) error { | ||
var secret client.Secret | ||
|
||
// Read the secret content | ||
logrus.Info("reading secret content...") | ||
secretSourceName, err := cmd.Flags().GetString("secret-from") | ||
if err != nil { | ||
return fmt.Errorf("getting secret-from flag: %w", err) | ||
} | ||
|
||
var secretSource io.Reader | ||
if secretSourceName == "-" { | ||
secretSource = os.Stdin | ||
} else { | ||
f, err := os.Open(secretSourceName) | ||
if err != nil { | ||
return fmt.Errorf("opening secret-from file: %w", err) | ||
} | ||
defer f.Close() | ||
secretSource = f | ||
} | ||
|
||
secretContent, err := io.ReadAll(secretSource) | ||
if err != nil { | ||
return fmt.Errorf("reading secret content: %w", err) | ||
} | ||
secret.Secret = string(secretContent) | ||
|
||
// Attach any file given | ||
files, err := cmd.Flags().GetStringSlice("file") | ||
if err != nil { | ||
return fmt.Errorf("getting file flag: %w", err) | ||
} | ||
for _, f := range files { | ||
logrus.WithField("file", f).Info("attaching file...") | ||
content, err := os.ReadFile(f) | ||
if err != nil { | ||
return fmt.Errorf("reading attachment %q: %w", f, err) | ||
} | ||
|
||
secret.Attachments = append(secret.Attachments, client.SecretAttachment{ | ||
Name: f, | ||
Type: mime.TypeByExtension(path.Ext(f)), | ||
Content: content, | ||
}) | ||
} | ||
|
||
// Create the secret | ||
logrus.Info("creating the secret...") | ||
instanceURL, err := cmd.Flags().GetString("instance") | ||
if err != nil { | ||
return fmt.Errorf("getting instance flag: %w", err) | ||
} | ||
|
||
expire, err := cmd.Flags().GetDuration("expire") | ||
if err != nil { | ||
return fmt.Errorf("getting expire flag: %w", err) | ||
} | ||
|
||
secretURL, expiresAt, err := client.Create(instanceURL, secret, expire) | ||
if err != nil { | ||
return fmt.Errorf("creating secret: %w", err) | ||
} | ||
|
||
// Tell them where to find the secret | ||
if expiresAt.IsZero() { | ||
logrus.Info("secret created, see URL below") | ||
} else { | ||
logrus.WithField("expires-at", expiresAt).Info("secret created, see URL below") | ||
} | ||
fmt.Println(secretURL) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io/fs" | ||
"os" | ||
"path" | ||
"strings" | ||
|
||
"github.com/Luzifer/ots/pkg/client" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const storeFileMode = 0o600 // We assume the attached file to be a secret | ||
|
||
var fetchCmd = &cobra.Command{ | ||
Use: "fetch url", | ||
Short: "Retrieves a secret from the instance by its URL", | ||
Long: "", | ||
Args: cobra.ExactArgs(1), | ||
RunE: fetchRunE, | ||
} | ||
|
||
func init() { | ||
fetchCmd.Flags().String("file-dir", ".", "Where to put files attached to the secret") | ||
rootCmd.AddCommand(fetchCmd) | ||
} | ||
|
||
func checkDirWritable(dir string) error { | ||
tmpFile := path.Join(dir, ".ots-cli.tmp") | ||
if err := os.WriteFile(tmpFile, []byte(""), storeFileMode); err != nil { | ||
return fmt.Errorf("writing tmp-file: %w", err) | ||
} | ||
defer os.Remove(tmpFile) | ||
|
||
return nil | ||
} | ||
|
||
func fetchRunE(cmd *cobra.Command, args []string) error { | ||
fileDir, err := cmd.Flags().GetString("file-dir") | ||
if err != nil { | ||
return fmt.Errorf("getting file-dir parameter: %w", err) | ||
} | ||
|
||
// First lets check whether we potentially can write files | ||
if err := checkDirWritable(fileDir); err != nil { | ||
return fmt.Errorf("checking for directory write: %w", err) | ||
} | ||
|
||
logrus.Info("fetching secret...") | ||
secret, err := client.Fetch(args[0]) | ||
if err != nil { | ||
return fmt.Errorf("fetching secret") | ||
} | ||
|
||
for _, f := range secret.Attachments { | ||
logrus.WithField("file", f.Name).Info("storing file...") | ||
if err = storeAttachment(fileDir, f); err != nil { | ||
return fmt.Errorf("saving file to disk: %w", err) | ||
} | ||
} | ||
|
||
fmt.Println(secret.Secret) | ||
|
||
return nil | ||
} | ||
|
||
func storeAttachment(dir string, f client.SecretAttachment) error { | ||
// First lets find a free file name to save the file as | ||
var ( | ||
fileNameFragments = strings.SplitN(f.Name, ".", 2) | ||
i int | ||
storeName = path.Join(dir, f.Name) | ||
storeNameTpl string | ||
) | ||
|
||
if len(fileNameFragments) == 1 { | ||
storeNameTpl = fmt.Sprintf("%s (%%d)", fileNameFragments[0]) | ||
} else { | ||
storeNameTpl = fmt.Sprintf("%s (%%d).%s", fileNameFragments[0], fileNameFragments[1]) | ||
} | ||
|
||
for _, err := os.Stat(storeName); !errors.Is(err, fs.ErrNotExist); _, err = os.Stat(storeName) { | ||
i++ | ||
storeName = fmt.Sprintf(storeNameTpl, i) | ||
} | ||
|
||
// So we finally found a filename we can use | ||
if err := os.WriteFile(storeName, f.Content, storeFileMode); err != nil { | ||
return fmt.Errorf("writing file: %w", err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var rootCmd = &cobra.Command{ | ||
Short: "Utility to interact with encrypted secrets in an OTS instance", | ||
PersistentPreRunE: rootPersistentPreRunE, | ||
} | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().String("log-level", "info", "Level to use for logging (trace, debug, info, warn, error, fatal)") | ||
} | ||
|
||
func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { | ||
sll, err := cmd.Flags().GetString("log-level") | ||
if err != nil { | ||
return fmt.Errorf("getting log-level: %w", err) | ||
} | ||
|
||
ll, err := logrus.ParseLevel(sll) | ||
if err != nil { | ||
return fmt.Errorf("parsing log-level: %w", err) | ||
} | ||
logrus.SetLevel(ll) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module github.com/Luzifer/ots/cmd/ots-cli | ||
|
||
go 1.21.1 | ||
|
||
replace github.com/Luzifer/ots/pkg/client => ../../pkg/client | ||
|
||
require ( | ||
github.com/Luzifer/ots/pkg/client v0.0.0-00010101000000-000000000000 | ||
github.com/sirupsen/logrus v1.9.3 | ||
github.com/spf13/cobra v1.7.0 | ||
) | ||
|
||
require ( | ||
github.com/Luzifer/go-openssl/v4 v4.2.1 // indirect | ||
github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
golang.org/x/crypto v0.12.0 // indirect | ||
golang.org/x/sys v0.11.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
github.com/Luzifer/go-openssl/v4 v4.2.1 h1:0+/gaQ5TcBhGmVqGrfyA21eujlbbaNwj0VlOA3nh4ts= | ||
github.com/Luzifer/go-openssl/v4 v4.2.1/go.mod h1:CZZZWY0buCtkxrkqDPQYigC4Kn55UuO97TEoV+hwz2s= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= | ||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | ||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= | ||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= | ||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= | ||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= | ||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= | ||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package main | ||
|
||
import "os" | ||
|
||
func main() { | ||
if err := rootCmd.Execute(); err != nil { | ||
os.Exit(1) | ||
} | ||
} |