Xc@sdZddklZddklZlZlZddklZlZddkl Z l Z l Z l Z ddk lZddklZddklZlZdd klZdd kTdd klZd Zhd eedIeiieiid6d eedJeiieiid6d eedKeiieiid6d eedLeiieiid6d eedMeiieiid6d eedNeii eiid6d eedOeii!eiid6Z"ddddd gZ#dPZ$d%ei%fd&YZ&ei%d'e'd(ei(ei)fZ*d)Z+d*Z,d+Z-d,Z.e/e/d-Z0d.Z1d/Z2d0Z3d1Z4e d2d3d4d5ed6d7ed8d9e$Z5d:efd;YZ6ei7e6d<ei8fd=YZ9ei7e9d>ei:fd?YZ;ei7e;d@ei<fdAYZ=ei7e=dBei>fdCYZ?ei7e?dDei@fdEYZAei7eAdFei<fdGYZBei7eBdHS(Qs Directory Server Access Control Instructions (ACIs) ACIs are used to allow or deny access to information. This module is currently designed to allow, not deny, access. The aci commands are designed to grant permissions that allow updating existing entries or adding or deleting new ones. The goal of the ACIs that ship with IPA is to provide a set of low-level permissions that grant access to special groups called taskgroups. These low-level permissions can be combined into roles that grant broader access. These roles are another type of group, roles. For example, if you have taskgroups that allow adding and modifying users you could create a role, useradmin. You would assign users to the useradmin role to allow them to do the operations defined by the taskgroups. You can create ACIs that delegate permission so users in group A can write attributes on group B. The type option is a map that applies to all entries in the users, groups or host location. It is primarily designed to be used when granting add permissions (to write new entries). An ACI consists of three parts: 1. target 2. permissions 3. bind rules The target is a set of rules that define which LDAP objects are being targeted. This can include a list of attributes, an area of that LDAP tree or an LDAP filter. The targets include: - attrs: list of attributes affected - type: an object type (user, group, host, service, etc) - memberof: members of a group - targetgroup: grant access to modify a specific group. This is primarily designed to enable users to add or remove members of a specific group. - filter: A legal LDAP filter used to narrow the scope of the target. - subtree: Used to apply a rule across an entire set of objects. For example, to allow adding users you need to grant "add" permission to the subtree ldap://uid=*,cn=users,cn=accounts,dc=example,dc=com. The subtree option is a fail-safe for objects that may not be covered by the type option. The permissions define what the ACI is allowed to do, and are one or more of: 1. write - write one or more attributes 2. read - read one or more attributes 3. add - add a new entry to the tree 4. delete - delete an existing entry 5. all - all permissions are granted Note the distinction between attributes and entries. The permissions are independent, so being able to add a user does not mean that the user will be editable. The bind rule defines who this ACI grants permissions to. The LDAP server allows this to be any valid LDAP entry but we encourage the use of taskgroups so that the rights can be easily shared through roles. For a more thorough description of access controls see http://www.redhat.com/docs/manuals/dir-server/ag/8.0/Managing_Access_Control.html EXAMPLES: NOTE: ACIs are now added via the permission plugin. These examples are to demonstrate how the various options work but this is done via the permission command-line now (see last example). Add an ACI so that the group "secretaries" can update the address on any user: ipa group-add --desc="Office secretaries" secretaries ipa aci-add --attrs=streetAddress --memberof=ipausers --group=secretaries --permissions=write --prefix=none "Secretaries write addresses" Show the new ACI: ipa aci-show --prefix=none "Secretaries write addresses" Add an ACI that allows members of the "addusers" permission to add new users: ipa aci-add --type=user --permission=addusers --permissions=add --prefix=none "Add new users" Add an ACI that allows members of the editors manage members of the admins group: ipa aci-add --permissions=write --attrs=member --targetgroup=admins --group=editors --prefix=none "Editors manage admins" Add an ACI that allows members of the admins group to manage the street and zip code of those in the editors group: ipa aci-add --permissions=write --memberof=editors --group=admins --attrs=street,postalcode --prefix=none "admins edit the address of editors" Add an ACI that allows the admins group manage the street and zipcode of those who work for the boss: ipa aci-add --permissions=write --group=admins --attrs=street,postalcode --filter="(manager=uid=boss,cn=users,cn=accounts,dc=example,dc=com)" --prefix=none "Edit the address of those who work for the boss" Add an entirely new kind of record to IPA that isn't covered by any of the --type options, creating a permission: ipa permission-add --permissions=add --subtree="cn=*,cn=orange,cn=accounts,dc=example,dc=com" --desc="Add Orange Entries" add_orange The show command shows the raw 389-ds ACI. IMPORTANT: When modifying the target attributes of an existing ACI you must include all existing attributes as well. When doing an aci-mod the targetattr REPLACES the current attributes, it does not add to them. i(tdeepcopy(tapitcrudterrors(tObjecttCommand(tFlagtInttStrtStrEnum(tACI(toutput(t_tngettext(tgen_pkey_only_option(t*(tDNt:sldap:///tuidRtusertcntgrouptfqdnthostt hostgrouptkrbprincipalnametservicet ipauniqueidtnetgrouptidnsnamet dnsrecordureaduwriteuaddudeleteuallu permissionu delegationu selfserviceunonet ListOfACIcBs)eZeefZedZdZRS(sA list of ACI valuesc Csoxht|D]Z\}}t|tp>tti|i|ii|i|tt ||fq q WdS(N( t enumeratet isinstancetunicodet TypeErrorR temsgtnamet __class__t__name__ttype(tselftcmdtentriestitentry((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pytvalidates   (R't __module__tlistttupleR(R tdocR.(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRs  tresultsA string representing the ACIcCs|djo|S|t|S(s: Given a name and a prefix construct an ACI name. unone(tACI_NAME_PREFIX_SEP(t aciprefixtaciname((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_make_aci_names cCs;|it}|dpd|dfS|d|dfS(sj Parse the raw ACI name and return a tuple containing the ACI prefix and the actual ACI name. iunonei(t partitionR4(R6taciparts((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_parse_aci_names cCsR|id}|djotidi|S|id|}||d|!S(s6 Pull the group name out of a memberOf filter s memberOf=iRt)i (tfindRRtget_dn(tmemberoftstten((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_group_from_memberofs  cCsddddddg}h}x=|D]5}||jo||d(j || Given a name and a set of keywords construct an ACI. R(tfiltertsubtreet targetgrouptattrsR>iR%ttargetterrors<type, filter, subtree and targetgroup are mutually exclusiveR5sACI prefix is requiredisSat least one of: type, filter, subtree, targetgroup, attrs or memberof are requireds*filter and memberof are mutually exclusiveRt permissiontselfacis1group, permission and self are mutually exclusives,One of group, permission or self is requiredtpermission_showR3ttestRtdntreasonsGroup '%s' does not existt permissionssuserdn = "ldap:///self"sgroupdn = "ldap:///%s"s memberOf=%stutinfos empty filters ldap:///%ssldap:///sSyntax Error: %(error)sN(RONu("tNonetFalseRtValidationErrorR tsumt itervaluestTrueRRtNotFoundtgetRtenvtcontainer_permissionRtget_dn_if_existsR R7R%RNt set_bindruletset_target_attrthandle_not_foundRAtset_target_filtertBadSearchFiltert find_entriest _type_mapt set_targett startswitht SyntaxErrortdicttstr(tldaptcurrentR6tkwt checked_argstvalidtargRRHRIt entry_attrstetgroup_dntaRLtgroupdnR+RF((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt _make_acis )" """  "" /)           6c Csh}t|i\|d<|d<|o|St|i|dnXtii| jo|d d|dRBRFR(t(sldap:///ROiRDRCR)RItanyoneRKutestRHR(scnstest(R:R%R1RNRFR0txrangetlenR"RdtsplitRRRRbtkeysRVtreplacetendswithRRYtcontainer_grouptbasedntbindruletattrt get_entryRRWRZ(RhRqRKt pkey_onlyRjR,RFtjunkR>tfoundtkttargetdnRrRLRnRo((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt _aci_to_kw2sn     %    !  cCs[g}xN|D]F}y|it|Wq tj o}tid|q Xq W|S(NsFailed to parse: %s(tappendR Ret root_loggertwarning(tacistrstacisRqRo((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_convert_strings_to_acisyscCsat||i}x)|D]!}|ii|jo|SqWtidtd|dS(NRMsACI with name "%s" not found(R7tlowerR%RRWR (RR5R6R%Rq((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_find_aci_by_names  cCsRg}|id}x6|D].}|ii}|tjo d|SqWdS(Nt,s"%s" is not a valid permission(R{tstripRt_valid_permissions_values(tugettextRNtvalid_permissionstp((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pytvalidate_permissionss cCscg}|id}x>|D]6}|ii}||jo|i|qqWdi|S(NR(R{RRRtjoin(RNRR((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyt_normalize_permissionss R5tcli_nametprefixtlabels ACI prefixR2sPPrefix used to distinguish ACI types (permission, delegation, selfservice, none)tvaluestacicBs*eZdZeZedZeddddeddedd=ed dd ded d eddd>eddddedd eddd?ededddedd eddede dd@eddddedd eddeddAe ddddedd ed d!dBddCed)dd*ded+d ed,ddDed-dd.ded/d ed0ddEed1dd2ded3d ed4ddFed5dd6ded7d ed8ddGe d9dd:ded;d ed<ddHf Z RS(Is ACI object. tACIsR6RR%RsACI namet primary_keytflagstvirtual_attributes permission?RHt PermissionR2sPermission ACI grants access tosgroup?Rs User groupsUser group ACI grants access tos permissions+RNt PermissionssKcomma-separated list of permissions to grant(read, write, add, delete, all)tcsvt normalizersattrs*REt Attributess"Comma-separated list of attributesstype?R(tTypesDtype of IPA object (user, group, host, hostgroup, service, netgroup)Ruuserugroupuhostuserviceu hostgroupunetgroupu dnsrecords memberof?R>s Member ofsMember of a groupsfilter?RBtFilters'Legal LDAP filter (e.g. ou=Engineering)ssubtree?RCtSubtreesSubtree to apply ACI tos targetgroup?RDs Target groupsGroup to apply ACI tosselfaci?R)sTarget your own entry (self)s"Apply ACI to your own entry (self)(R(R(R(R(R(uuserugroupuhostuserviceu hostgroupunetgroupu dnsrecord(R(R(R(R(R(R( R'R/t__doc__RVtNO_CLIR RRRRR Rt takes_params(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRs|                                 taci_addcBsMeZdZeZedZeeddedde fZ dZ RS(s Create new ACI. sCreated ACI "%(value)s"stest?R2s,Test the ACI syntax but don't write anythingtdefaultc KsE|iii}t|d||}|i|iiidg\}}t|i dg}xA|D]9}|i |p|i |i jot i qgqgWt|} |di| |i dtp|i||n|i dtotdt| } nt|||i dt} td| d|S(s Execute the aci-create operation. Returns the entry as it will be created in LDAP. :param aciname: The name of the ACI being added. :param kw: Keyword arguments for the other LDAP attributes. RRKtrawR3tvalueN(RtBackendtldap2RsRQRRYRRRXtisequalR%RtDuplicateEntryR"RRRt update_entryRfR( R)R6RjRhtnewaciRLRnRRqt newaci_strR3((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pytexecutes$ $# ( R'R/RRVRR t msg_summaryt_prefix_optionRRRt takes_optionsR(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRs    taci_delcBs;eZdZeZeiZedZ e fZ dZ RS(s Delete ACI. sDeleted ACI "%(value)s"c Cs|iii}|i|iiidg\}}|idg}t|}t|||}x<|D]4} t | } |i | o|i | PqjqjW||d<|i ||t dtd|S(s Execute the aci-delete operation. :param aciname: The name of the ACI being deleted. :param aciprefix: The ACI prefix. RR3R(RRRRRYRRXRRR RtremoveRRfRV( R)R6R5RhRLRnRRRRqt candidate((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyR7s $     ( R'R/RRVRR tstandard_booleant has_outputR RRRR(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyR-s    taci_modcBsVeZdZeZeddedfZefZ dgZ edZ dZ RS(s Modify ACI. RRR trenamesModified ACI "%(value)s"c Ks|d}|iii}|i|iiidg\}}t|idg}t|||}t ||} t | } | idt ot |d $   ! ( R'R/RRVRRR thas_output_paramsRRtinternal_optionsRR(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRWs    taci_findcBsPeZdZeZedddZeidde e dfZ dZ RS(sX Search for ACIs. Returns a list of ACIs EXAMPLES: To find all ACIs that apply directly to members of the group ipausers: ipa aci-find --memberof=ipausers To find all ACIs that grant add access: ipa aci-find --permissions=add Note that the find command only looks for the given text in the set of ACIs, it does not evaluate the ACIs to see if something would apply. For example, searching on memberof=ipausers will find all ACIs that have ipausers as a memberof. There may be other ACIs that apply to members of that group indirectly. s%(count)d ACI matcheds%(count)d ACIs matchedis aciprefix?trequiredR%c)KsX |iii}|i|iiidg\}}t|idg}g}|oj|i}xK|D]C}|i ii |djo||jo|i |qkqkWt |}n t |}|idoXxE|D]=}t |i \} } | |djo|i|qqWt |}n|idoXxE|D]=}t |i \} } | |djo|i|qMqMWt |}n|idox|D]}d|ijo|i|qntg} |iddD]} | | iq~ } tg}|dD]} || iq)~}tt| t|@t|jo|i|qqWt |}n|idoy|iid |dWntij oq%Xx7|D]/}|idd |jo|i|qqWt |}n|id ozxg|D]_}t|i} t|d }tt| t|@t|jo|i|q<q<Wt |}n|id oyt|d }Wntij oq[Xd |}xb|D]V}d|ijo3|idd}||jo|i|qSq|i|qWn|idox|D]}d|ijo|idd}n|i|qrt}xAtiD]3}t||jo|d|jo t}PqqW|p+y|i|Wq)tj oq)XqrqrWn|idttjoTxQ|D]E}|iddjo+y|i|Wqtj oqXqQqQWn|idox|D]}|id}t|idd}y|dd}Wnt t!fj o d}nX|djp||djo+y|i|Wq]tj oq]XqqWn|idox|D]}t}d|ijo|idd}t|idd}ttii#tii}|i$|oSy|dd}Wnt t!fj o d}nX||djo t}q?qCn|p+y|i|Wqutj oquXq|q|Wn|ido|di%dp t&d|dd|ds (memberOf=%s)RvR(RFRIu ldap:///selfRsldap:///ROiRRDRBRwR;RCRRR3tcountt truncated()RRRRRYRRRXRR%R<RR0R:RRFtsortedRztsetRRRWRRNRARRRbR|RVt ValueErrorRR}t IndexErrortKeyErrorRQRR~RdR"RfR(R)ttermRjRhRLRnRtresultsRqRR%t_[1]tttalist1t_[2]talist2tmemberof_filterRvRFRRRrRRtgroup_container_dnR3R((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRsF$ ,  51) )    "        ( R'R/RRVRR RRt clone_renameRRRRR(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRs taci_showcBsAeZdZeZeddedfZefZ dZ RS(s1 Display a single ACI given an ACI name. RRR c Ks|iii}|i|iiidg\}}t|idg}t||d|}|idt ot dt |}nt ||}t d|d|S(s Execute the aci-show operation. Returns the entry :param uid: The login name of the user to retrieve. :param kw: unused RR5RR3R( RRRRRYRRRXRRRRfR"R( R)R6RjRhRLRnRRR3((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRxs $( R'R/RRVRRR RRRR(((s6/usr/lib/python2.6/site-packages/ipalib/plugins/aci.pyRjs   t aci_renamecBsbeZdZeZeddedfZeeddedfZ edZ dZ RS( s Rename an ACI. RRR tnewnameR2s New ACI namesRenamed ACI to "%(value)s"cKs|iii}|i|iiidg\}}t|idg}t||d|}xP|D]H}t |i \} } t | |d|i jot i qhqhWt||} d| jo| dtjot|dwsj" )))))),  fG      R 4 ' B  ' <