github.com/go-chef/chef@v0.30.1/acl.go (about) 1 package chef 2 3 // TODO: Add a call to retrive all ACLs. 4 5 import ( 6 "errors" 7 "fmt" 8 ) 9 10 const adminUser = "pivotal" 11 12 type ACLService struct { 13 client *Client 14 } 15 16 // ACL represents the native Go version of the deserialized ACL type 17 // The key string will be one of: 18 // 19 // create, delete, grant, read, update 20 // 21 // indicating the type of access granted to an accessor in the ACLitems lists 22 type ACL map[string]ACLitems 23 24 // ACLitems 25 // 26 // Newer versions of the Chef server split Actors into Users and Clients. 27 type ACLitems struct { 28 Actors ACLitem `json:"actors"` 29 Clients ACLitem `json:"clients"` 30 Groups ACLitem `json:"groups"` 31 Users ACLitem `json:"users"` 32 } 33 34 // ACLitem 35 // A list of a specific type of accessor. In ACLitems the group ACLitem consists of a list of groups. 36 type ACLitem []string 37 38 func NewACL(acltype string, actors ACLitem, groups ACLitem, users ACLitem, clients ACLitem) *ACL { 39 return &ACL{ 40 acltype: *NewACLItems(actors, groups, users, clients), 41 } 42 } 43 44 func NewACLItems(actors ACLitem, groups ACLitem, users ACLitem, clients ACLitem) *ACLitems { 45 return &ACLitems{ 46 Actors: actors, 47 Clients: clients, 48 Groups: groups, 49 Users: users, 50 } 51 } 52 53 // ACLAdminAccess 54 // Verify that pivotal is in the Users access list for each type of ACL access 55 func ACLAdminAccess(acl *ACL) (err error) { 56 err = errors.New("pivotal was not in a Users access list") 57 // For each type of access in the acl 58 // Verify that "pivotal" is listed in the Users list 59 for _, item := range *acl { 60 // See if "pivotal" is in the list of Users 61 foundUser := false 62 for _, user := range item.Users { 63 if user == adminUser { 64 // done with this item in the acl 65 foundUser = true 66 break 67 } 68 } 69 if foundUser { 70 // this item checks out, verify the next 71 continue 72 } else { 73 return err 74 } 75 } 76 return nil 77 } 78 79 // Get gets an ACL from the Chef server. 80 // 81 // Warning: This API is not included in the Chef documentation and thus probably not officially supported. 82 // Package documentation is based on the `knife` source code and packet capture. 83 // It could be wrong or change in future Chef server updates. 84 // 85 // Subkind can be one of: clients, containers, cookbook_artifacts, cookbooks, data, environments, groups, nodes, roles, policies, policy_groups. 86 // 87 // * 88 // map[create:{Groups:[admins clients users] Actors:[] Users:[pivotal] Clients:[]} 89 // 90 // delete:{Groups:[admins users] Actors:[] Users:[pivotal] Clients:[]} 91 // grant:{Groups:[admins] Actors:[] Users:[pivotal] Clients:[]} 92 // read:{Groups:[admins clients users] Actors:[] Users:[pivotal] Clients:[]} 93 // update:{Groups:[admins users] Actors:[] Users:[pivotal] Clients:[]}] 94 // 95 // * 96 // Returns the ACL for multiple perms (create, read, update, delete, grant). 97 // Older versions of the Chef server only include ACLs for "groups" and "actors." 98 // If you're using a more recent version then the contents of "actors" is split up in "users" and "clients." 99 func (a *ACLService) Get(subkind string, name string) (acl ACL, err error) { 100 url := fmt.Sprintf("%s/%s/_acl?detail=granular", subkind, name) 101 err = a.client.magicRequestDecoder("GET", url, nil, &acl) 102 return 103 } 104 105 // Put updates an ACL on the Chef server. 106 // 107 // Warning: This API is not included in the Chef documentation and thus probably not officially supported. 108 // Package documentation is based on the `knife` source code and packet capture. 109 // It could be wrong or change in future Chef server updates. 110 // 111 // To change an ACL you have to fetch it from the Chef server first, as it expects the PUT request to 112 // contain the same elements as the GET response. While the GET response returns ACLs for all perms, you have 113 // to update each one separately. 114 // 115 // On newer versions of the Chef server you may need to replace "actors" with an empty list. Looks like the 116 // actors list is only included for backwards compatibility but can't be in the PUT request. 117 func (a *ACLService) Put(subkind, name string, perm string, item *ACL) (err error) { 118 url := fmt.Sprintf("%s/%s/_acl/%s", subkind, name, perm) 119 err = ACLAdminAccess(item) 120 if err != nil { 121 return 122 } 123 body, err := JSONReader(item) 124 if err != nil { 125 return 126 } 127 128 err = a.client.magicRequestDecoder("PUT", url, body, nil) 129 return 130 }