| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 1 | import logging | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 2 |  | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 3 | logger = logging.getLogger(__name__) | 
 | 4 |  | 
 | 5 | set_ldap_groovy = """\ | 
 | 6 | import jenkins.model.* | 
 | 7 | import hudson.security.* | 
 | 8 | import org.jenkinsci.plugins.* | 
 | 9 |  | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 10 | def server = '${server}' | 
 | 11 | def rootDN = '${rootDN}' | 
 | 12 | def userSearchBase = '${userSearchBase}' | 
 | 13 | def userSearch = '${userSearch}' | 
 | 14 | def groupSearchBase = '${groupSearchBase}' | 
 | 15 | def managerDN = '${managerDN}' | 
 | 16 | def managerPassword = '${managerPassword}' | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 17 | boolean inhibitInferRootDN = {inhibitInferRootDN} | 
 | 18 |  | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 19 | try{ | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 20 | ldapRealm = Class.forName("hudson.security.LDAPSecurityRealm").getConstructor(String.class, String.class, String.class, String.class, String.class, String.class, String.class, Boolean.TYPE) | 
 | 21 | .newInstance(server, rootDN, userSearchBase, userSearch, groupSearchBase, managerDN, managerPassword, inhibitInferRootDN)  | 
 | 22 | Jenkins.instance.setSecurityRealm(ldapRealm) | 
 | 23 | Jenkins.instance.save() | 
 | 24 | print("SUCCESS") | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 25 | }catch(ClassNotFoundException e){ | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 26 |     print("Cannot instantiate LDAPSecurityRealm, maybe ldap plugin not installed") | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 27 | } | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 28 | """  # noqa | 
 | 29 |  | 
 | 30 | set_matrix_groovy = """\ | 
 | 31 | import jenkins.model.* | 
 | 32 | import hudson.security.* | 
 | 33 | import com.cloudbees.plugins.credentials.* | 
 | 34 |  | 
 | 35 | def instance = Jenkins.getInstance() | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 36 | try{ | 
 | 37 | def strategy = Class.forName("hudson.security.${matrix_class}").newInstance() | 
 | 38 | ${strategies} | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 39 | instance.setAuthorizationStrategy(strategy) | 
 | 40 | instance.save() | 
 | 41 | print("SUCCESS") | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 42 | }catch(ClassNotFoundException e){ | 
 | 43 |     print("Cannot instantiate ${matrix_class}, maybe auth-matrix plugin not installed") | 
 | 44 | } | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 45 | """  # noqa | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 46 |  | 
 | 47 |  | 
| Ilya Kharin | 3d8bffe | 2017-06-22 17:40:31 +0400 | [diff] [blame] | 48 | def __virtual__(): | 
 | 49 |     ''' | 
 | 50 |     Only load if jenkins_common module exist. | 
 | 51 |     ''' | 
 | 52 |     if 'jenkins_common.call_groovy_script' not in __salt__: | 
 | 53 |         return ( | 
 | 54 |             False, | 
 | 55 |             'The jenkins_security state module cannot be loaded: ' | 
 | 56 |             'jenkins_common not found') | 
 | 57 |     return True | 
 | 58 |  | 
 | 59 |  | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 60 | def ldap(name, server, root_dn, user_search_base, manager_dn, manager_password, | 
 | 61 |          user_search="", group_search_base="", inhibit_infer_root_dn=False): | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 62 |     """ | 
 | 63 |     Jenkins ldap state method | 
 | 64 |  | 
 | 65 |     :param name: ldap state name | 
| Andrey | 6606be0 | 2017-08-02 17:09:42 -0500 | [diff] [blame] | 66 |     :param server: ldap server host | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 67 |     :param root_dn: root domain names | 
 | 68 |     :param user_search_base: | 
 | 69 |     :param manager_dn: | 
 | 70 |     :param manager_password: | 
 | 71 |     :param user_search: optional, default empty string | 
 | 72 |     :param group_search_base: optional, default empty string | 
 | 73 |     :param inhibit_infer_root_dn: optional, default false | 
 | 74 |     :returns: salt-specified state dict | 
 | 75 |     """ | 
 | 76 |     test = __opts__['test']  # noqa | 
 | 77 |     ret = { | 
 | 78 |         'name': name, | 
 | 79 |         'changes': {}, | 
 | 80 |         'result': False, | 
 | 81 |         'comment': '', | 
 | 82 |     } | 
 | 83 |     result = False | 
| Andrey | 6606be0 | 2017-08-02 17:09:42 -0500 | [diff] [blame] | 84 |     if not server.startswith("ldap:") and not server.startswith("ldaps:"): | 
 | 85 |         server = "ldap://{server}".format(server=server) | 
 | 86 |  | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 87 |     if test: | 
 | 88 |         status = 'CREATED' | 
 | 89 |         ret['changes'][name] = status | 
 | 90 |         ret['comment'] = 'LDAP setup %s %s' % (name, status.lower()) | 
 | 91 |     else: | 
 | 92 |         call_result = __salt__['jenkins_common.call_groovy_script']( | 
 | 93 |             set_ldap_groovy, {"name": name, "server": server, "rootDN": root_dn, | 
| Jakub Josef | 95ad980 | 2017-01-17 15:59:00 +0100 | [diff] [blame] | 94 |                               "userSearchBase": user_search_base if user_search_base else "", | 
 | 95 |                               "managerDN": manager_dn if manager_dn else "", | 
 | 96 |                               "managerPassword": manager_password if manager_password else "", | 
 | 97 |                               "userSearch": user_search if user_search else "", | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 98 |                               "groupSearchBase": group_search_base if group_search_base else "", | 
| Jakub Josef | 95ad980 | 2017-01-17 15:59:00 +0100 | [diff] [blame] | 99 |                               "inhibitInferRootDN": "true" if inhibit_infer_root_dn else "false"}) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 100 |         if call_result["code"] == 200 and call_result["msg"] == "SUCCESS": | 
 | 101 |             status = call_result["msg"] | 
 | 102 |             ret['changes'][name] = status | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 103 |             ret['comment'] = 'Jenkins LDAP setting %s %s' % ( | 
 | 104 |                 name, status.lower()) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 105 |             result = True | 
 | 106 |         else: | 
 | 107 |             status = 'FAILED' | 
 | 108 |             logger.error( | 
 | 109 |                 "Jenkins security API call failure: %s", call_result["msg"]) | 
 | 110 |             ret['comment'] = 'Jenkins security API call failure: %s' % (call_result[ | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 111 |                 "msg"]) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 112 |     ret['result'] = None if test else result | 
 | 113 |     return ret | 
 | 114 |  | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 115 |  | 
 | 116 | def matrix(name, strategies, project_based=False): | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 117 |     """ | 
 | 118 |     Jenkins matrix security state method | 
 | 119 |  | 
 | 120 |     :param name: ldap state name | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 121 |     :param strategies: dict with matrix strategies | 
 | 122 |     :param procect_based: flag if we configuring | 
 | 123 |         GlobalMatrix security or ProjectMatrix security | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 124 |     :returns: salt-specified state dict | 
 | 125 |     """ | 
 | 126 |     test = __opts__['test']  # noqa | 
 | 127 |     ret = { | 
 | 128 |         'name': name, | 
 | 129 |         'changes': {}, | 
 | 130 |         'result': False, | 
 | 131 |         'comment': '', | 
 | 132 |     } | 
 | 133 |     result = False | 
 | 134 |     if test: | 
 | 135 |         status = 'CREATED' | 
 | 136 |         ret['changes'][name] = status | 
 | 137 |         ret['comment'] = 'LDAP setup %s %s' % (name, status.lower()) | 
 | 138 |     else: | 
 | 139 |         call_result = __salt__['jenkins_common.call_groovy_script']( | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 140 |             set_matrix_groovy, {"strategies": _build_strategies(strategies), | 
 | 141 |                                 "matrix_class": "ProjectMatrixAuthorizationStrategy" if project_based else "GlobalMatrixAuthorizationStrategy"}) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 142 |         if call_result["code"] == 200 and call_result["msg"] == "SUCCESS": | 
 | 143 |             status = call_result["msg"] | 
 | 144 |             ret['changes'][name] = status | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 145 |             ret['comment'] = 'Jenkins Matrix security setting %s %s' % ( | 
 | 146 |                 name, status.lower()) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 147 |             result = True | 
 | 148 |         else: | 
 | 149 |             status = 'FAILED' | 
 | 150 |             logger.error( | 
 | 151 |                 "Jenkins security API call failure: %s", call_result["msg"]) | 
 | 152 |             ret['comment'] = 'Jenkins security API call failure: %s' % (call_result[ | 
| Jakub Josef | 0ee470e | 2017-01-17 11:46:58 +0100 | [diff] [blame] | 153 |                 "msg"]) | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 154 |     ret['result'] = None if test else result | 
 | 155 |     return ret | 
 | 156 |  | 
 | 157 |  | 
 | 158 | def _build_strategies(permissions): | 
 | 159 |     strategies_str = "" | 
| Adam Tengler | 70763e0 | 2017-08-21 16:50:32 +0000 | [diff] [blame^] | 160 |     for strategy in _to_strategies_list( | 
 | 161 |             "strategy.add({},\"{}\")", _to_one_dict(permissions, "")): | 
| Jakub Josef | 063a753 | 2017-01-11 15:48:01 +0100 | [diff] [blame] | 162 |         strategies_str += "{}\n".format(strategy) | 
 | 163 |     return strategies_str | 
 | 164 |  | 
 | 165 |  | 
 | 166 | def _to_strategies_list(strategy_format, strategy_dict): | 
 | 167 |     res = [] | 
 | 168 |     for key, value in strategy_dict.items(): | 
 | 169 |         if isinstance(value, list): | 
 | 170 |             for user in value: | 
 | 171 |                 res.append(strategy_format.format(key, user)) | 
 | 172 |         else: | 
 | 173 |             res.append(strategy_format.format(key, value)) | 
 | 174 |     return res | 
 | 175 |  | 
 | 176 |  | 
 | 177 | def _to_one_dict(input_dict, input_key): | 
 | 178 |     res = {} | 
 | 179 |     for key, value in input_dict.items(): | 
 | 180 |         new_key = key if input_key == "" else "{}.{}".format(input_key, key) | 
 | 181 |         if isinstance(value, dict): | 
 | 182 |             res.update(_to_one_dict(value, new_key)) | 
 | 183 |         else: | 
 | 184 |             res[new_key] = value | 
 | 185 |     return res |