Skip to content

Commit

Permalink
Merge pull request #3 from chroju/0.2.0
Browse files Browse the repository at this point in the history
0.2.0
  • Loading branch information
chroju authored Feb 14, 2021
2 parents b0f88ef + d9c048c commit 1667fea
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 130 deletions.
26 changes: 13 additions & 13 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ jobs:
name: Test Parade
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup go
uses: actions/setup-go@v1
with:
go-version: "1.13.1"
- name: Test all
env:
GO111MODULE: on
run: |
export PATH=$PATH:$(go env GOPATH)/bin
go get golang.org/x/lint/golint
make test
- name: Checkout
uses: actions/checkout@master
- name: Setup go
uses: actions/setup-go@v1
with:
go-version: "1.15.6"
- name: Test all
env:
GO111MODULE: on
run: |
export PATH=$PATH:$(go env GOPATH)/bin
go get golang.org/x/lint/golint
make test
28 changes: 14 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ jobs:
name: Release Parade
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup go
uses: actions/setup-go@v1
with:
go-version: "1.13.1"
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v1
env:
GO111MODULE: on
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version: latest
args: release --rm-dist
- name: Checkout
uses: actions/checkout@master
- name: Setup go
uses: actions/setup-go@v2
with:
go-version: "1.15"
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v2
env:
GO111MODULE: on
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version: latest
args: release --rm-dist
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# CHANGELOG

## 0.2.0 (2021/02/15)

* Add `version` subcommand
* Improve `keys` subcommand
* Display the parameter types.
* Improve `get` subcommand
* Instead of displaying encrypted values as they are, display them as `(encrypted)` string.
* For multi-line values, display the line feed code as a string of `\n`.
* Improve `set` subcommand
* Add confirmation prompt before overwriting existing value.
* Add `--force` option.
* Improve `del` subcommand
* Add confirmation prompt before deleting.
* Add `--force` option.
* Support `AWS_DEFAULT_REGION` environment variable
* Add `--region` option
* Add `--profile` option
* Fix some bugs.

## 0.1.0 (2019/10/13)

* Initial version
58 changes: 40 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Parade is a simple CLI tool for AWS SSM parameter store. Easy to read and write
Install
-------

### Homebrew

```bash
$ brew install chroju/tap/parade
```

### Download binary

Download the latest binary from [here](https://github.com/chroju/parade/releases) and put it in your `$PATH` directory.
Expand All @@ -27,23 +33,34 @@ Authenticate
Parade requires your AWS IAM user authentications. The same authentication method as [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) is available. Tools like [aws-vault](https://github.com/99designs/aws-vault) can be used as well.

```
# with command line options
$ parade --profile YOUR_PROFILE
# with aws-vault
$ aws-vault exec YOUR_PROFILE -- parade
```

Parade uses the following AWS API. If you are dealing with SecureString, you will also need permission to access the kms key.

* ssm:DeleteParameter
* ssm:DescribeParameters
* ssm:GetParameter
* ssm:PutParameter

Usage
-----

Simple four sub commands. It is similar to redis-cli.
There are Simple 4 sub commands. It is similar to redis-cli.

### keys

Display keys that match partial search.
Display keys that match partial search. If no argument is given, all keys will be retrieved.

```
$ parade keys dev
/service1/dev/key1
/service1/dev/key2
/service1/dev/key3
/service1/dev/key1 Type: String
/service1/dev/key2 Type: String
/service1/dev/key3 Type: SecureString
```

### get
Expand All @@ -64,42 +81,47 @@ $ parade get dev --ambiguous
/service1/dev/key3 value3
```

The `--decrypt` or `-d` option is required to decrypt SecureString.

```
$ parade get /service1/dev/password
/service1/dev/password (encrypted)
$ parade get /service1/dev/password -d
/service1/dev/password 1234password
```

### set

Set new key value.
Set new key and value.

```
$ parade set /service1/dev/key4 value4
done.
```

Use `--force` flag if you want to overwrite.
If the specified key already exists, you can choose to overwrite it. Use `--force` flag if you want to force overwriting.

```
$ parade set /service1/dev/key4 value5
ParameterAlreadyExists: The parameter already exists. To overwrite this value, set the overwrite option in the request to true.
status code: 400, request id: ae21f5d5-XXXX-XXXX-XXXX-XXXXXXXXXXXX
WARN: `/service1/dev/key4` already exists.
Overwrite `/service1/dev/key4` (value: value4) ? (Y/n)
$ parade set /service1/dev/key4 value5 --force
done.
```

The value is stored as `String` type by default. It also supports `SecureString` type with the default AWS KMS key and can be specified with the `--encrypt` flag. `StringList` type is not supported.


### del

Delete a key value.
Delete key and value. Use `--force` flag if you want to force deletion.

```
$ parade del /service1/dev/key4
done.
```
Delete `/service1/dev/key4` (value: value5) ? (Y/n)
Author
----

[chroju](https://github.com/chroju)
$ parade del /service1/dev/key4 --force
```

LICENSE
----
Expand Down
40 changes: 30 additions & 10 deletions cmd/del.go
Original file line number Diff line number Diff line change
@@ -1,41 +1,61 @@
package cmd

import (
"bufio"
"fmt"
"os"

"github.com/chroju/parade/ssmctl"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

var (
isForceDelete bool
// DelCommand is the command to delete key value
DelCommand = &cobra.Command{
Use: "del",
Short: "Delete key value",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
del(args)
RunE: func(cmd *cobra.Command, args []string) error {
return del(args)
},
}
)

func del(args []string) {
func del(args []string) error {
key := args[0]

ssmManager, err := ssmctl.New()
param, err := ssmManager.GetParameter(key, false)
if err != nil {
fmt.Fprintln(ErrWriter, err)
os.Exit(1)
fmt.Fprintln(ErrWriter, color.YellowString(fmt.Sprintf("WARN: `%s` is not found. Nothing to do.", key)))
return nil
}

if !isForceDelete {
fmt.Fprintf(ErrWriter, "Delete `%s` (value: %s) ? (Y/n)\n", key, param.Value)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
yn := scanner.Text()

if yn == "Y" || yn == "y" {
break
} else if yn == "N" || yn == "n" {
return nil
} else {
fmt.Fprint(ErrWriter, "(Y/n) ?")
}
}
}

if err = ssmManager.DeleteParameter(key); err != nil {
if err := ssmManager.DeleteParameter(key); err != nil {
fmt.Fprintln(ErrWriter, color.RedString(ErrMsgDeleteParameter))
fmt.Fprintln(ErrWriter, err)
os.Exit(1)
return err
}

fmt.Fprintln(ErrWriter, "done.")
return nil
}

func init() {
DelCommand.PersistentFlags().BoolVarP(&isForceDelete, "force", "f", false, "Force deletion of key and value")
}
63 changes: 32 additions & 31 deletions cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package cmd

import (
"fmt"
"github.com/chroju/parade/ssmctl"
"github.com/fatih/color"
"github.com/spf13/cobra"
"strings"
"text/tabwriter"

"github.com/fatih/color"
"github.com/spf13/cobra"
)

var (
Expand All @@ -18,57 +18,58 @@ var (
Use: "get",
Short: "Get key value",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
get(args)
RunE: func(cmd *cobra.Command, args []string) error {
return get(args)
},
}
)

func get(args []string) {
func get(args []string) error {
w := tabwriter.NewWriter(StdWriter, 0, 2, 2, ' ', 0)
query := args[0]
ssmManager, err := ssmctl.New()
if err != nil {
fmt.Fprintln(ErrWriter, err)
}

if isAmbiguous {
resp, err := ssmManager.DescribeParameters()
resp, err := ssmManager.DescribeParameters(query)
if err != nil {
fmt.Fprintln(ErrWriter, color.RedString(ErrMsgDescribeParameters))
fmt.Fprintln(ErrWriter, err)
return err
}

for _, v := range resp {
index := strings.Index(*v.Name, query)
if index >= 0 {
resp, err := ssmManager.GetParameter(*v.Name, isDecryption)
if err != nil {
fmt.Fprintln(ErrWriter, err)
}
printValuesWithColor(w, ssmManager, *v.Name, *resp.Value, index, index+len(query))
index := strings.Index(v.Name, query)
if err = getAndPrintParameter(w, v.Name, index, index+len(query)); err != nil {
fmt.Fprintln(ErrWriter, color.RedString(ErrMsgGetParameter))
fmt.Fprintln(ErrWriter, err)
break
}
}
} else {
resp, err := ssmManager.GetParameter(query, isDecryption)
if err != nil {
return
getAndPrintParameter(w, query, 0, 0)
if err := getAndPrintParameter(w, query, 0, 0); err != nil {
fmt.Fprintln(ErrWriter, color.RedString(ErrMsgGetParameter))
fmt.Fprintln(ErrWriter, err)
}
printValue(w, query, *resp.Value)
}
}

func printValue(w *tabwriter.Writer, key string, value string) {
fmt.Fprintf(w, "%s\t%s\n", key, value)
w.Flush()

return nil
}

func printValuesWithColor(w *tabwriter.Writer, s *ssmctl.SSMManager, key string, value string, begin int, end int) {
func getAndPrintParameter(w *tabwriter.Writer, key string, begin int, end int) error {
resp, err := ssmManager.GetParameter(key, isDecryption)
if err != nil {
return err
}

coloredKey := key[0:begin] + color.RedString(key[begin:end]) + key[end:]
printValue(w, coloredKey, value)
w.Flush()
value := strings.ReplaceAll(resp.Value, "\n", color.YellowString("\\n"))
fmt.Fprintf(w, "%s\t%s\n", coloredKey, value)

return nil
}

func init() {
GetCommand.PersistentFlags().BoolVarP(&isAmbiguous, "ambiguous", "a", false, "get all values of the keys partial match")
GetCommand.PersistentFlags().BoolVarP(&isDecryption, "decrypt", "d", false, "get keys with decription")
GetCommand.PersistentFlags().BoolVarP(&isAmbiguous, "ambiguous", "a", false, "Get all values that partially match the specified key")
GetCommand.PersistentFlags().BoolVarP(&isDecryption, "decrypt", "d", false, "Get the value by decrypting it")
}
Loading

0 comments on commit 1667fea

Please sign in to comment.