youtubebeat/vendor/github.com/elastic/beats/libbeat/cmd/keystore.go

260 lines
7 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package cmd
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
tml "golang.org/x/crypto/ssh/terminal"
"github.com/elastic/beats/libbeat/cmd/instance"
"github.com/elastic/beats/libbeat/common/cli"
"github.com/elastic/beats/libbeat/common/terminal"
"github.com/elastic/beats/libbeat/keystore"
)
func getKeystore(name, version string) (keystore.Keystore, error) {
b, err := instance.NewBeat(name, "", version)
if err != nil {
return nil, fmt.Errorf("error initializing beat: %s", err)
}
if err = b.Init(); err != nil {
return nil, fmt.Errorf("error initializing beat: %s", err)
}
return b.Keystore(), nil
}
// genKeystoreCmd initialize the Keystore command to manage the Keystore
// with the following subcommands:
// - create
// - add
// - remove
// - list
func genKeystoreCmd(
name, idxPrefix, version string,
runFlags *pflag.FlagSet,
) *cobra.Command {
keystoreCmd := cobra.Command{
Use: "keystore",
Short: "Manage secrets keystore",
}
keystoreCmd.AddCommand(genCreateKeystoreCmd(name, version))
keystoreCmd.AddCommand(genAddKeystoreCmd(name, version))
keystoreCmd.AddCommand(genRemoveKeystoreCmd(name, version))
keystoreCmd.AddCommand(genListKeystoreCmd(name, version))
return &keystoreCmd
}
func genCreateKeystoreCmd(name, version string) *cobra.Command {
var flagForce bool
command := &cobra.Command{
Use: "create",
Short: "Create keystore",
Run: cli.RunWith(func(cmd *cobra.Command, args []string) error {
return createKeystore(name, version, flagForce)
}),
}
command.Flags().BoolVar(&flagForce, "force", false, "override the existing keystore")
return command
}
func genAddKeystoreCmd(name, version string) *cobra.Command {
var flagForce bool
var flagStdin bool
command := &cobra.Command{
Use: "add",
Short: "Add secret",
Run: cli.RunWith(func(cmd *cobra.Command, args []string) error {
store, err := getKeystore(name, version)
if err != nil {
return err
}
return addKey(store, args, flagForce, flagStdin)
}),
}
command.Flags().BoolVar(&flagStdin, "stdin", false, "Use the stdin as the source of the secret")
command.Flags().BoolVar(&flagForce, "force", false, "Override the existing key")
return command
}
func genRemoveKeystoreCmd(name, version string) *cobra.Command {
return &cobra.Command{
Use: "remove",
Short: "remove secret",
Run: cli.RunWith(func(cmd *cobra.Command, args []string) error {
store, err := getKeystore(name, version)
if err != nil {
return err
}
return removeKey(store, args)
}),
}
}
func genListKeystoreCmd(name, version string) *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List keystore",
Run: cli.RunWith(func(cmd *cobra.Command, args []string) error {
store, err := getKeystore(name, version)
if err != nil {
return err
}
return list(store)
}),
}
}
func createKeystore(name, version string, force bool) error {
store, err := getKeystore(name, version)
if err != nil {
return err
}
if store.IsPersisted() == true && force == false {
response := terminal.PromptYesNo("A keystore already exists, Overwrite?", true)
if response == true {
err := store.Create(true)
if err != nil {
return fmt.Errorf("error creating the keystore: %s", err)
}
} else {
fmt.Println("Exiting without creating keystore.")
return nil
}
} else {
err := store.Create(true)
if err != nil {
return fmt.Errorf("Error creating the keystore: %s", err)
}
}
fmt.Printf("Created %s keystore\n", name)
return nil
}
func addKey(store keystore.Keystore, keys []string, force, stdin bool) error {
if len(keys) == 0 {
return errors.New("failed to create the secret: no key provided")
}
if len(keys) > 1 {
return fmt.Errorf("could not create secret for: %s, you can only provide one key per invocation", keys)
}
if store.IsPersisted() == false {
if force == false {
answer := terminal.PromptYesNo("The keystore does not exist. Do you want to create it?", false)
if answer == false {
return errors.New("exiting without creating keystore")
}
}
err := store.Create(true)
if err != nil {
return fmt.Errorf("could not create keystore, error: %s", err)
}
fmt.Println("Created keystore")
}
key := strings.TrimSpace(keys[0])
value, err := store.Retrieve(key)
if value != nil && force == false {
if stdin == true {
return fmt.Errorf("the settings %s already exist in the keystore use `--force` to replace it", key)
}
answer := terminal.PromptYesNo(fmt.Sprintf("Setting %s already exists, Overwrite?", key), false)
if answer == false {
fmt.Println("Exiting without modifying keystore.")
return nil
}
}
var keyValue []byte
if stdin {
reader := bufio.NewReader(os.Stdin)
keyValue, err = ioutil.ReadAll(reader)
if err != nil {
return fmt.Errorf("could not read input from stdin")
}
} else {
fmt.Printf("Enter value for %s: ", key)
keyValue, err = tml.ReadPassword(int(syscall.Stdin))
fmt.Println()
if err != nil {
return fmt.Errorf("could not read value from the input, error: %s", err)
}
}
if err = store.Store(key, keyValue); err != nil {
return fmt.Errorf("could not add the key in the keystore, error: %s", err)
}
if err = store.Save(); err != nil {
return fmt.Errorf("fail to save the keystore: %s", err)
} else {
fmt.Println("Successfully updated the keystore")
}
return nil
}
func removeKey(store keystore.Keystore, keys []string) error {
if len(keys) == 0 {
return errors.New("you must supply at least one key to remove")
}
if store.IsPersisted() == false {
return errors.New("the keystore doesn't exist. Use the 'create' command to create one")
}
for _, key := range keys {
key = strings.TrimSpace(key)
_, err := store.Retrieve(key)
if err != nil {
return fmt.Errorf("could not find key '%v' in the keystore", key)
}
store.Delete(key)
err = store.Save()
if err != nil {
return fmt.Errorf("could not update the keystore with the changes, key: %s, error: %v", key, err)
}
fmt.Printf("successfully removed key: %s\n", key)
}
return nil
}
func list(store keystore.Keystore) error {
keys, err := store.List()
if err != nil {
return fmt.Errorf("could not read values from the keystore, error: %s", err)
}
for _, key := range keys {
fmt.Println(key)
}
return nil
}