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