blob: 72967025b638cae31f8c4859e6adf92cfbfeb772 [file] [log] [blame]
Robert Kroeger90104522014-11-11 15:29:17 -08001package main
2
3// Commands to get/set ACLs.
4
5import (
6 "fmt"
Robert Kroeger90104522014-11-11 15:29:17 -08007
Jiri Simsabc26d692014-11-19 18:30:55 -08008 "veyron.io/lib/cmdline"
Robert Kroeger1e4721a2014-11-12 17:59:46 -08009 "veyron.io/veyron/veyron2/security"
Robert Kroeger90104522014-11-11 15:29:17 -080010 "veyron.io/veyron/veyron2/services/mgmt/node"
Robert Kroeger1e4721a2014-11-12 17:59:46 -080011 "veyron.io/veyron/veyron2/services/security/access"
12 "veyron.io/veyron/veyron2/verror"
Robert Kroeger90104522014-11-11 15:29:17 -080013)
14
15var cmdGet = &cmdline.Command{
16 Run: runGet,
17 Name: "get",
18 Short: "Get ACLs for the given target.",
Robert Kroeger2c25fcf2014-11-17 09:44:59 -080019 Long: "Get ACLs for the given target.",
Robert Kroeger90104522014-11-11 15:29:17 -080020 ArgsName: "<node manager name>",
21 ArgsLong: `
22<node manager name> can be a Vanadium name for a node manager,
23application installation or instance.`,
24}
25
Robert Kroeger90104522014-11-11 15:29:17 -080026func runGet(cmd *cmdline.Command, args []string) error {
Robert Kroeger90104522014-11-11 15:29:17 -080027 if expected, got := 1, len(args); expected != got {
Robert Kroeger2c25fcf2014-11-17 09:44:59 -080028 return cmd.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
Robert Kroeger90104522014-11-11 15:29:17 -080029 }
30
31 vanaName := args[0]
Matt Rosencrantz5180d162014-12-03 13:48:40 -080032 objACL, _, err := node.ApplicationClient(vanaName).GetACL(runtime.NewContext())
Robert Kroeger90104522014-11-11 15:29:17 -080033 if err != nil {
34 return fmt.Errorf("GetACL on %s failed: %v", vanaName, err)
35 }
Asim Shankar68885192014-11-26 12:48:35 -080036 // Convert objACL (TaggedACLMap) into aclEntries for pretty printing.
37 entries := make(aclEntries)
38 for tag, acl := range objACL {
39 for _, p := range acl.In {
40 entries.Tags(string(p))[tag] = false
41 }
42 for _, b := range acl.NotIn {
43 entries.Tags(b)[tag] = true
44 }
Robert Kroeger90104522014-11-11 15:29:17 -080045 }
Asim Shankar68885192014-11-26 12:48:35 -080046 fmt.Fprintf(cmd.Stdout(), "%v", entries)
Robert Kroeger90104522014-11-11 15:29:17 -080047 return nil
48}
49
Robert Kroeger1e4721a2014-11-12 17:59:46 -080050var cmdSet = &cmdline.Command{
51 Run: runSet,
52 Name: "set",
53 Short: "Set ACLs for the given target.",
54 Long: "Set ACLs for the given target",
Asim Shankar68885192014-11-26 12:48:35 -080055 ArgsName: "<node manager name> (<blessing> [!]<tag>(,[!]<tag>)*",
Robert Kroeger1e4721a2014-11-12 17:59:46 -080056 ArgsLong: `
57<node manager name> can be a Vanadium name for a node manager,
58application installation or instance.
59
60<blessing> is a blessing pattern.
Asim Shankar68885192014-11-26 12:48:35 -080061If the same pattern is repeated multiple times in the command, then
62the only the last occurrence will be honored.
Robert Kroeger1e4721a2014-11-12 17:59:46 -080063
Asim Shankar68885192014-11-26 12:48:35 -080064<tag> is a subset of defined access types ("Admin", "Read", "Write" etc.).
65If the access right is prefixed with a '!' then <blessing> is added to the
66NotIn list for that right. Using "^" as a "tag" causes all occurrences of
67<blessing> in the current ACL to be cleared.
Robert Kroeger1e4721a2014-11-12 17:59:46 -080068
Asim Shankar68885192014-11-26 12:48:35 -080069Examples:
70set root/self ^
71will remove "root/self" from the In and NotIn lists for all access rights.
Robert Kroeger1e4721a2014-11-12 17:59:46 -080072
Asim Shankar68885192014-11-26 12:48:35 -080073set root/self Read,!Write
74will add "root/self" to the In list for Read access and the NotIn list
75for Write access (and remove "root/self" from both the In and NotIn
76lists of all other access rights)`,
Robert Kroeger1e4721a2014-11-12 17:59:46 -080077}
78
79func runSet(cmd *cmdline.Command, args []string) error {
80 if got := len(args); !((got%2) == 1 && got >= 3) {
81 return cmd.UsageErrorf("set: incorrect number of arguments %d, must be 1 + 2n", got)
82 }
83
84 vanaName := args[0]
85 pairs := args[1:]
86
Asim Shankar68885192014-11-26 12:48:35 -080087 entries := make(aclEntries)
Robert Kroeger1e4721a2014-11-12 17:59:46 -080088 for i := 0; i < len(pairs); i += 2 {
Asim Shankar68885192014-11-26 12:48:35 -080089 blessing := pairs[i]
90 tags, err := parseAccessTags(pairs[i+1])
91 if err != nil {
92 return cmd.UsageErrorf("failed to parse access tags for %q: %v", blessing, err)
Robert Kroeger1e4721a2014-11-12 17:59:46 -080093 }
Asim Shankar68885192014-11-26 12:48:35 -080094 entries[blessing] = tags
Robert Kroeger1e4721a2014-11-12 17:59:46 -080095 }
96
Asim Shankar68885192014-11-26 12:48:35 -080097 // Set the ACLs on the specified names.
Matt Rosencrantz5180d162014-12-03 13:48:40 -080098 ctx := runtime.NewContext()
Robert Kroeger1e4721a2014-11-12 17:59:46 -080099 for {
Matt Rosencrantz5180d162014-12-03 13:48:40 -0800100 objACL, etag, err := node.ApplicationClient(vanaName).GetACL(ctx)
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800101 if err != nil {
102 return cmd.UsageErrorf("GetACL(%s) failed: %v", vanaName, err)
103 }
Asim Shankar68885192014-11-26 12:48:35 -0800104 for blessingOrPattern, tags := range entries {
105 objACL.Clear(blessingOrPattern) // Clear out any existing references
106 for tag, blacklist := range tags {
107 if blacklist {
108 objACL.Blacklist(blessingOrPattern, tag)
109 } else {
110 objACL.Add(security.BlessingPattern(blessingOrPattern), tag)
111 }
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800112 }
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800113 }
Matt Rosencrantz5180d162014-12-03 13:48:40 -0800114 switch err := node.ApplicationClient(vanaName).SetACL(ctx, objACL, etag); {
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800115 case err != nil && !verror.Is(err, access.ErrBadEtag):
116 return cmd.UsageErrorf("SetACL(%s) failed: %v", vanaName, err)
117 case err == nil:
118 return nil
119 }
120 fmt.Fprintf(cmd.Stderr(), "WARNING: trying again because of asynchronous change\n")
121 }
122 return nil
123}
Robert Kroeger90104522014-11-11 15:29:17 -0800124
125func aclRoot() *cmdline.Command {
126 return &cmdline.Command{
127 Name: "acl",
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800128 Short: "Tool for setting node manager ACLs",
Robert Kroeger90104522014-11-11 15:29:17 -0800129 Long: `
Robert Kroeger2c25fcf2014-11-17 09:44:59 -0800130The acl tool manages ACLs on the node manger, installations and instances.
Robert Kroeger90104522014-11-11 15:29:17 -0800131`,
Robert Kroeger1e4721a2014-11-12 17:59:46 -0800132 Children: []*cmdline.Command{cmdGet, cmdSet},
Robert Kroeger90104522014-11-11 15:29:17 -0800133 }
134}