github.com/kjdelisle/consul@v1.4.5/command/acl/policy/create/policy_create.go (about) 1 package policycreate 2 3 import ( 4 "flag" 5 "fmt" 6 "io" 7 8 "github.com/hashicorp/consul/acl" 9 "github.com/hashicorp/consul/api" 10 aclhelpers "github.com/hashicorp/consul/command/acl" 11 "github.com/hashicorp/consul/command/flags" 12 "github.com/hashicorp/consul/command/helpers" 13 "github.com/mitchellh/cli" 14 ) 15 16 func New(ui cli.Ui) *cmd { 17 c := &cmd{UI: ui} 18 c.init() 19 return c 20 } 21 22 type cmd struct { 23 UI cli.Ui 24 flags *flag.FlagSet 25 http *flags.HTTPFlags 26 help string 27 28 name string 29 description string 30 datacenters []string 31 rules string 32 33 fromToken string 34 tokenIsSecret bool 35 showMeta bool 36 37 testStdin io.Reader 38 } 39 40 func (c *cmd) init() { 41 c.flags = flag.NewFlagSet("", flag.ContinueOnError) 42 c.flags.BoolVar(&c.showMeta, "meta", false, "Indicates that policy metadata such "+ 43 "as the content hash and raft indices should be shown for each entry") 44 c.flags.StringVar(&c.name, "name", "", "The new policy's name. This flag is required.") 45 c.flags.StringVar(&c.description, "description", "", "A description of the policy") 46 c.flags.Var((*flags.AppendSliceValue)(&c.datacenters), "valid-datacenter", "Datacenter "+ 47 "that the policy should be valid within. This flag may be specified multiple times") 48 c.flags.StringVar(&c.rules, "rules", "", "The policy rules. May be prefixed with '@' "+ 49 "to indicate that the value is a file path to load the rules from. '-' may also be "+ 50 "given to indicate that the rules are available on stdin") 51 c.flags.StringVar(&c.fromToken, "from-token", "", "The legacy token to retrieve the rules "+ 52 "for when creating this policy. When this is specified no other rules should be given. "+ 53 "Similar to the -rules option the token to use can be loaded from stdin or from a file") 54 c.flags.BoolVar(&c.tokenIsSecret, "token-secret", false, "Indicates the token provided with "+ 55 "-from-token is a SecretID and not an AccessorID") 56 57 c.http = &flags.HTTPFlags{} 58 flags.Merge(c.flags, c.http.ClientFlags()) 59 flags.Merge(c.flags, c.http.ServerFlags()) 60 c.help = flags.Usage(help, c.flags) 61 } 62 63 func (c *cmd) getRules(client *api.Client) (string, error) { 64 if c.fromToken != "" && c.rules != "" { 65 return "", fmt.Errorf("Cannot specify both -rules and -from-token") 66 } 67 68 if c.fromToken != "" { 69 tokenID, err := helpers.LoadDataSource(c.fromToken, c.testStdin) 70 if err != nil { 71 return "", fmt.Errorf("Invalid -from-token value: %v", err) 72 } 73 74 rules, err := aclhelpers.GetRulesFromLegacyToken(client, tokenID, c.tokenIsSecret) 75 if err != nil { 76 return "", err 77 } 78 79 translated, err := acl.TranslateLegacyRules([]byte(rules)) 80 return string(translated), err 81 } 82 83 return helpers.LoadDataSource(c.rules, c.testStdin) 84 } 85 86 func (c *cmd) Run(args []string) int { 87 if err := c.flags.Parse(args); err != nil { 88 return 1 89 } 90 91 if c.name == "" { 92 c.UI.Error(fmt.Sprintf("Missing require '-name' flag")) 93 c.UI.Error(c.Help()) 94 return 1 95 } 96 97 client, err := c.http.APIClient() 98 if err != nil { 99 c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) 100 return 1 101 } 102 103 rules, err := c.getRules(client) 104 if err != nil { 105 c.UI.Error(fmt.Sprintf("Error loading rules: %v", err)) 106 return 1 107 } 108 109 newPolicy := &api.ACLPolicy{ 110 Name: c.name, 111 Description: c.description, 112 Datacenters: c.datacenters, 113 Rules: rules, 114 } 115 116 policy, _, err := client.ACL().PolicyCreate(newPolicy, nil) 117 if err != nil { 118 c.UI.Error(fmt.Sprintf("Failed to create new policy: %v", err)) 119 return 1 120 } 121 122 aclhelpers.PrintPolicy(policy, c.UI, c.showMeta) 123 return 0 124 } 125 126 func (c *cmd) Synopsis() string { 127 return synopsis 128 } 129 130 func (c *cmd) Help() string { 131 return flags.Usage(c.help, nil) 132 } 133 134 const synopsis = "Create an ACL Policy" 135 const help = ` 136 Usage: consul acl policy create -name NAME [options] 137 138 Both the -rules and -from-token option values allow loading the value 139 from stdin, a file or the raw value. To use stdin pass '-' as the value. 140 To load the value from a file prefix the value with an '@'. Any other 141 values will be used directly. 142 143 Create a new policy: 144 145 $ consul acl policy create -name "new-policy" \ 146 -description "This is an example policy" \ 147 -datacenter "dc1" \ 148 -datacenter "dc2" \ 149 -rules @rules.hcl 150 151 Creation a policy from a legacy token: 152 153 $ consul acl policy create -name "legacy-policy" \ 154 -description "Token Converted to Policy" \ 155 -from-token "c1e34113-e7ab-4451-b1a6-336ddcc58fc6" 156 `