module ChefZero::ChefData::AclPath
Manages translations between REST and ACL data paths and parent paths.
Suggestions
-
make /organizations/ORG/_acl and deprecate organization/_acl and organizations/_acl
-
add endpoints for /containers/(users|organizations|containers)(/_acl)
-
add PUT for */_acl
-
add endpoints for /organizations/ORG/data/containers and /organizations/ORG/cookbooks/containers
-
sane, fully documented ACL model
-
sane inheritance / override model: if actors or groups are explicitly specified on X, they are not inherited from X's parent
-
stop adding pivotal to acls (he already has access to what he needs)
Constants
- ORG_DATA_TYPES
- TOP_DATA_TYPES
Public Class Methods
This method takes a Chef REST path and returns the chef-zero path used to look up the ACL. If an object does not have an ACL directly, it will return nil. Paths like /organizations/ORG/data/bag/item will return nil, because it is the parent path (data/bag) that has an ACL.
# File lib/chef_zero/chef_data/acl_path.rb, line 43 def self.get_acl_data_path(path) # Things under organizations have their own acls hierarchy if path[0] == "organizations" && path.size >= 2 under_org = partition_acl_data_path(path[2..-1], ORG_DATA_TYPES) if under_org path[0..1] + under_org end else partition_acl_data_path(path, TOP_DATA_TYPES) end end
Reverse transform from acl_data_path to path. /acls/root -> / /acls/** -> /** /organizations/ORG/acls/root -> /organizations/ORG /organizations/ORG/acls/** -> /organizations/ORG/**
This means that /acls/containers/nodes maps to /containers/nodes, not /nodes.
# File lib/chef_zero/chef_data/acl_path.rb, line 65 def self.get_object_path(acl_data_path) if acl_data_path[0] == "acls" if acl_data_path[1] == "root" [] else acl_data_path[1..-1] end elsif acl_data_path[0] == "organizations" && acl_data_path[2] == "acls" if acl_data_path[3] == "root" acl_data_path[0..1] else acl_data_path[0..1] + acl_data_path[3..-1] end end end
Method assumes acl_data_path is valid. /organizations/BLAH's parent is /organizations
An example traversal up the whole tree: /organizations/foo/acls/nodes/mario -> /organizations/foo/acls/containers/nodes -> /organizations/foo/acls/containers/containers -> /organizations/foo/acls/root -> /acls/containers/organizations -> /acls/containers/containers -> /acls/root -> nil
# File lib/chef_zero/chef_data/acl_path.rb, line 93 def self.parent_acl_data_path(acl_data_path) if acl_data_path[0] == "organizations" under_org = partition_parent_acl_data_path(acl_data_path[2..-1]) if under_org acl_data_path[0..1] + under_org else # ACL data path is /organizations/X/acls/root; therefore parent is "/organizations" %w{acls containers organizations} end else partition_parent_acl_data_path(acl_data_path) end end
Private Class Methods
# File lib/chef_zero/chef_data/acl_path.rb, line 127 def self.partition_acl_data_path(path, data_types) if path.size == 0 %w{acls root} elsif data_types.include?(path[0]) if path.size == 0 [ "acls", "containers", path[0] ] elsif path.size == 2 [ "acls", path[0], path[1] ] end end end
/acls/root -> nil /acls/containers/containers -> /acls/root /acls/TYPE/X -> /acls/containers/TYPE
Method assumes acl_data_path is valid. Returns nil if the path is /acls/root
# File lib/chef_zero/chef_data/acl_path.rb, line 114 def self.partition_parent_acl_data_path(acl_data_path) if acl_data_path.size == 3 if acl_data_path == %w{acls containers containers} %w{acls root} else [ "acls", "containers", acl_data_path[1]] end else nil end end