编写 HTTP 检查规则

oslo.policy 已经支持以下语法一段时间了

http:<target URL>, which delegates the check to a remote server

从 1.29 版本开始,oslo.policy 也将支持 https URL(s)

https:<target URL>, which delegates the check to a remote server

Both httphttps 的支持都以自定义检查规则的形式实现。如果您查看 oslo.policy 的 setup.cfg,您会看到以下入口点

oslo.policy.rule_checks =
    http = oslo_policy._external:HttpCheck
    https = oslo_policy._external:HttpsCheck

当策略被评估时,当引擎遇到 https 像下面的代码片段一样

{
       ...
       "target 1" : "https://foo.bar/baz",
       ...
}

引擎将在 rule_checks 入口点中查找名为 https 的插件,并尝试调用该 stevedore 插件。

这种机制允许任何人编写自己的代码,在自己的库中使用自己的基于 stevedore 的规则检查插件,并可以用自定义检查来增强他们的策略。例如,这对于与内部策略服务器集成会很有用。

示例代码 - HttpCheck

注意

完整源代码位于 _external.py

 1class HttpCheck(_checks.Check):
 2    """Check ``http:`` rules by calling to a remote server.
 3
 4    This example implementation simply verifies that the response
 5    is exactly ``True``.
 6    """
 7
 8    def __call__(self, target, creds, enforcer, current_rule=None):
 9        timeout = enforcer.conf.oslo_policy.remote_timeout
10
11        url = ('http:' + self.match) % target
12        data, json = self._construct_payload(creds, current_rule,
13                                             enforcer, target)
14        try:
15            with contextlib.closing(
16                    requests.post(url, json=json, data=data, timeout=timeout)
17            ) as r:
18                return r.text.lstrip('"').rstrip('"') == 'True'
19        except Timeout:
20            raise RuntimeError("Timeout in REST API call")
21
22    @staticmethod
23    def _construct_payload(creds, current_rule, enforcer, target):
24        # Convert instances of object() in target temporarily to
25        # empty dict to avoid circular reference detection
26        # errors in jsonutils.dumps().
27        temp_target = copy.deepcopy(target)
28        for key in target.keys():
29            element = target.get(key)
30            if type(element) is object:
31                temp_target[key] = {}
32        data = json = None
33        if (enforcer.conf.oslo_policy.remote_content_type ==
34                'application/x-www-form-urlencoded'):
35            data = {'rule': jsonutils.dumps(current_rule),
36                    'target': jsonutils.dumps(temp_target),
37                    'credentials': jsonutils.dumps(creds)}