138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/mitchellh/cli"
|
|
"github.com/posener/complete"
|
|
)
|
|
|
|
var (
|
|
_ cli.Command = (*PolicyWriteCommand)(nil)
|
|
_ cli.CommandAutocomplete = (*PolicyWriteCommand)(nil)
|
|
)
|
|
|
|
type PolicyWriteCommand struct {
|
|
*BaseCommand
|
|
|
|
testStdin io.Reader // for tests
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) Synopsis() string {
|
|
return "Uploads a named policy from a file"
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) Help() string {
|
|
helpText := `
|
|
Usage: vault policy write [options] NAME PATH
|
|
|
|
Uploads a policy with name NAME from the contents of a local file PATH or
|
|
stdin. If PATH is "-", the policy is read from stdin. Otherwise, it is
|
|
loaded from the file at the given path on the local disk.
|
|
|
|
Upload a policy named "my-policy" from "/tmp/policy.hcl" on the local disk:
|
|
|
|
$ vault policy write my-policy /tmp/policy.hcl
|
|
|
|
Upload a policy from stdin:
|
|
|
|
$ cat my-policy.hcl | vault policy write my-policy -
|
|
|
|
` + c.Flags().Help()
|
|
|
|
return strings.TrimSpace(helpText)
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) Flags() *FlagSets {
|
|
return c.flagSet(FlagSetHTTP)
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) AutocompleteArgs() complete.Predictor {
|
|
return complete.PredictFunc(func(args complete.Args) []string {
|
|
// Predict the LAST argument hcl files - we don't want to predict the
|
|
// name argument as a filepath.
|
|
if len(args.All) == 3 {
|
|
return complete.PredictFiles("*.hcl").Predict(args)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) AutocompleteFlags() complete.Flags {
|
|
return c.Flags().Completions()
|
|
}
|
|
|
|
func (c *PolicyWriteCommand) Run(args []string) int {
|
|
f := c.Flags()
|
|
|
|
if err := f.Parse(args); err != nil {
|
|
c.UI.Error(err.Error())
|
|
return 1
|
|
}
|
|
|
|
args = f.Args()
|
|
switch {
|
|
case len(args) < 2:
|
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", len(args)))
|
|
return 1
|
|
case len(args) > 2:
|
|
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", len(args)))
|
|
return 1
|
|
}
|
|
|
|
client, err := c.Client()
|
|
if err != nil {
|
|
c.UI.Error(err.Error())
|
|
return 2
|
|
}
|
|
|
|
// Policies are normalized to lowercase
|
|
policyName := args[0]
|
|
formattedName := strings.TrimSpace(strings.ToLower(policyName))
|
|
path := strings.TrimSpace(args[1])
|
|
|
|
// Get the policy contents, either from stdin of a file
|
|
var reader io.Reader
|
|
if path == "-" {
|
|
reader = os.Stdin
|
|
if c.testStdin != nil {
|
|
reader = c.testStdin
|
|
}
|
|
} else {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error opening policy file: %s", err))
|
|
return 2
|
|
}
|
|
defer file.Close()
|
|
reader = file
|
|
}
|
|
|
|
// Read the policy
|
|
var buf bytes.Buffer
|
|
if _, err := io.Copy(&buf, reader); err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error reading policy: %s", err))
|
|
return 2
|
|
}
|
|
rules := buf.String()
|
|
|
|
if err := client.Sys().PutPolicy(formattedName, rules); err != nil {
|
|
c.UI.Error(fmt.Sprintf("Error uploading policy: %s", err))
|
|
return 2
|
|
}
|
|
|
|
if policyName != formattedName {
|
|
c.UI.Warn(fmt.Sprintf("Policy name was converted from \"%s\" to \"%s\"", policyName, formattedName))
|
|
}
|
|
|
|
c.UI.Output(fmt.Sprintf("Success! Uploaded policy: %s", formattedName))
|
|
return 0
|
|
}
|