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  }