Skip to content

Commit

Permalink
setting envar export as default and adding quotes; updating secret pu…
Browse files Browse the repository at this point in the history
…t command with interactive inputs; adding sample operatory deploy yaml and sample vault yaml to public site; updating readme files and adding ascii art
  • Loading branch information
shibme committed Feb 27, 2024
1 parent bbf7636 commit 3fcf364
Show file tree
Hide file tree
Showing 13 changed files with 377 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:

slv:
release:
runs-on: ubuntu-latest
steps:
- name: Setting SLV Version
Expand Down
2 changes: 1 addition & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ builds:
main: ./cli/main
env:
- CGO_ENABLED=0
ldflags: "-X savesecrets.org/slv.Version={{.Version}}"
ldflags: "-X savesecrets.org/slv.Version={{.Version}} -X savesecrets.org/slv.BuildDate={{.Date}} -X savesecrets.org/slv.Commit={{.Commit}}"
targets:
- darwin_amd64
- darwin_arm64
Expand Down
77 changes: 72 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,79 @@
Secure Local Vault - SLV (a.k.a Secrets Launch Vehicle 🔐🚀) is a tool to manage secrets locally in a secure manner. It is designed to be used by developers to manage secrets along with their code so that they can be shared with other developers and services in a secure manner.

SLV is designed based on the following **key principles**
- Anyone can add or update secrets, however will not be allowed to read them unless they have access to the vault
- An environment should have a single key that will give access to all necessary secrets irrespective of the number of vaults shared with it
- Anyone can add or update secrets, however will not be able to read them unless they have access to the vault
- An environment should have a single identity that will give access to all necessary secrets from any vault shared with it

## How to install
SLV can be installed using brew using the following command
## Installation
Download the latest SLV binary from the [releases](https://github.com/savesecrets/slv/releases/latest) page and add it to your path.

SLV can also be installed with brew using the following command
```zsh
brew install savesecrets/tap/slv
```
Alternatively, you can download the SLV binary from the [releases](https://github.com/savesecrets/slv/releases/latest) page and add it to your path.

## Usage

#### Create a new profile
```sh
$ slv profile new -n amagi

Created profile: amagi
```

#### Create a new environment
```sh
$ slv env new -n alice -e alice@example.com --add

ID (Public Key): SLV_EPK_AEAUKAELRTIL2YIXNP7NYTYQMHUX77BWK2LXSKXN4GHSUECDNEJ7XFECLE
Name: alice
Email: alice@example.com
Tags: []

Env Data: SLV_EDS_AF4JYNGKIFVYGMAYQDQ774U5MUDRSBDSTK5G7UZFBPMYYW5ECRETKSBAKFISVFOS75PKJ5HY6I7FPEHHSN3S3MY3KAUPSX4DSI2QSJQVJOIP7KUCY522DBJEUJLPLT3XLZUUFUT7CZZV2MRNLY77HMWC5RO6AF6RD6MHDBAIQQERMKAY55NAWELAGDHD766NLZGJRPD5NHD3BP3BKXN3J26FZ3V4GK6TF5AA7RYI4Q6K5LVTOPVINTQNHVIIBWZ5AAAP775I7Q3QS

Secret Key: SLV_ESK_AEAEKAHBIONE3QIIWFXFRNJPE6A6AYL527QW4OF4HWWFDOE5E4XR5LO2WI
```

#### Create a vault
- To create a vault and share it with the environment `alice`, use the following command
```sh
$ slv vault new -v test.slv -s alice

Created vault: test.slv
```
- To create a K8s compatible vault, use the following command
```sh
$ slv vault new -v test.slv.yaml -s alice --k8s production

Created vault: test.slv.yaml
```

#### Add secrets to the vault
```sh
$ slv secret put -v test.slv -n db_password -s "super_secret_pwd"

Added secret: db_password to vault: test.slv
```

#### Get secrets from the vault
Set the environment variable `SLV_ENV_SECRET_KEY` to the secret key generated in the previous step
```sh
$ export SLV_ENV_SECRET_KEY=SLV_ESK_AEAEKAHBIONE3QIIWFXFRNJPE6A6AYL527QW4OF4HWWFDOE5E4XR5LO2WI
$ slv secret get -v test.slv -n db_password

super_secret_pwd
```

#### Share the vault with other environments
Ensure that the current environment has access to the vault in order to share it with other environments
```sh
$ slv vault share -v test.slv -s bob

Shared vault: test.slv
```
Once shared, the other environments can access the vault using their respective secret keys

## Integrations
Some of the integrations that SLV supports currently are:
- [Kubernetes Operator](/operator/README.md)
9 changes: 9 additions & 0 deletions cli/internal/commands/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ package commands
import (
"fmt"
"os"
"syscall"

"github.com/fatih/color"
"golang.org/x/term"
)

func getHiddenInputFromUser(prompt string) ([]byte, error) {
fmt.Print(prompt)
input, err := term.ReadPassword(int(syscall.Stdin))
fmt.Println()
return input, err
}

func exitOnError(err error) {
fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
erroredExit()
Expand Down
38 changes: 27 additions & 11 deletions cli/internal/commands/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,35 @@ func secretPutCommand() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
vaultFile := cmd.Flag(vaultFileFlag.name).Value.String()
name := cmd.Flag(secretNameFlag.name).Value.String()
secret := cmd.Flag(secretValueFlag.name).Value.String()
secretStr := cmd.Flag(secretValueFlag.name).Value.String()
vault, err := getVault(vaultFile)
if err != nil {
exitOnError(err)
}
forceUpdate, _ := cmd.Flags().GetBool(secretForceUpdateFlag.name)
if !forceUpdate && vault.SecretExists(name) {
exitOnErrorWithMessage("secret already exists. please use the --" + secretForceUpdateFlag.name + " flag to overwrite it.")
fmt.Print("Secret already exists. Do you wish to overwrite it? (y/n): ")
var confirmation string
fmt.Scanln(&confirmation)
if confirmation != "y" {
fmt.Println(color.YellowString("Operation aborted"))
safeExit()
}
}
var secret []byte
if secretStr == "" {
secret, err = getHiddenInputFromUser("Enter the secret value for " + name + ": ")
if err != nil {
exitOnError(err)
}
} else {
secret = []byte(secretStr)
}
err = vault.PutSecret(name, []byte(secret))
err = vault.PutSecret(name, secret)
if err != nil {
exitOnError(err)
}
fmt.Println("Added secret: ", color.GreenString(name), " to vault: ", color.GreenString(vaultFile))
fmt.Println("Updated secret: ", color.GreenString(name), " to vault: ", color.GreenString(vaultFile))
safeExit()
},
}
Expand All @@ -73,7 +88,6 @@ func secretPutCommand() *cobra.Command {
secretPutCmd.Flags().Bool(secretForceUpdateFlag.name, false, secretForceUpdateFlag.usage)
secretPutCmd.MarkFlagRequired(vaultFileFlag.name)
secretPutCmd.MarkFlagRequired(secretNameFlag.name)
secretPutCmd.MarkFlagRequired(secretValueFlag.name)
return secretPutCmd
}

Expand Down Expand Up @@ -156,11 +170,11 @@ func secretExportCommand() *cobra.Command {
secretOutputMap[name] = string(secret)
}
}
listFormat := cmd.Flag(secretListFormatFlag.name).Value.String()
if listFormat == "" {
listFormat = "table"
exportFormat := cmd.Flag(secretListFormatFlag.name).Value.String()
if exportFormat == "" {
exportFormat = "env"
}
switch listFormat {
switch exportFormat {
case "table":
tw := tabwriter.NewWriter(os.Stdout, 0, 8, 2, ' ', 0)
for key, value := range secretOutputMap {
Expand All @@ -181,10 +195,12 @@ func secretExportCommand() *cobra.Command {
fmt.Println(string(yamlData))
case "envars", "envar", "env":
for key, value := range secretOutputMap {
fmt.Printf("%s=%s\n", key, value)
value = strings.ReplaceAll(value, "\\", "\\\\")
value = strings.ReplaceAll(value, "\"", "\\\"")
fmt.Printf("%s=\"%s\"\n", key, value)
}
default:
exitOnErrorWithMessage("invalid format: " + listFormat)
exitOnErrorWithMessage("invalid format: " + exportFormat)
}
safeExit()
},
Expand Down
17 changes: 16 additions & 1 deletion cli/internal/commands/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,29 @@ package commands

import (
"fmt"
"runtime"
"time"

"github.com/spf13/cobra"
"savesecrets.org/slv"
"savesecrets.org/slv/core/config"
)

func showVersionInfo() {
fmt.Println(config.AppNameUpperCase, slv.Version)
buildAt := "unknown"
if builtAtTime, err := time.Parse(time.RFC3339, slv.BuildDate); err == nil {
builtAtLocalTime := builtAtTime.Local()
buildAt = builtAtLocalTime.Format("02 Jan 2006 03:04:05 PM MST")
}
fmt.Println(config.Art)
fmt.Println(config.AppNameUpperCase + ": " + config.Description)
fmt.Println("-------------------------------------------------")
fmt.Printf("Version : %s\n", slv.Version)
fmt.Printf("Built At : %s\n", buildAt)
fmt.Printf("Git Commit : %s\n", slv.Commit)
fmt.Printf("Web : %s\n", config.Website)
fmt.Printf("Platform : %s\n", runtime.GOOS+"/"+runtime.GOARCH)
fmt.Printf("Go Version : %s\n", runtime.Version())
}

func versionCommand() *cobra.Command {
Expand Down
7 changes: 2 additions & 5 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import (
"savesecrets.org/slv/core/crypto"
)

const (
// AppName = config.AppName
Prefix = "SLV"
)

var (
Version = "dev"
Commit = "none"
BuildDate = ""
secretKey *crypto.SecretKey
errEnvironmentAccessNotFound = errors.New("environment doesn't have access. please set the required environment variables")
)
9 changes: 9 additions & 0 deletions core/config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ const (

AppNameLowerCase = "slv"
AppNameUpperCase = "SLV"
Description = "Secure Local Vault | Secrets Launch Vehicle"
Website = "https://savesecrets.org/slv"
Art = `
____ _ __ __
/ ___|| |\ \ / /
\___ \| | \ \ / /
___) | |__\ V /
|____/|_____\_/
`
)

var (
Expand Down
Loading

0 comments on commit 3fcf364

Please sign in to comment.