Browse Source

Switch to oslo privsep

Please reference here:
https://docs.openstack.org/oslo.privsep/latest/user/index.html#converting-from-rootwrap-to-privsep

Change-Id: I5db0e64ec38d912f907b4ad483562120d030d726
changes/98/656098/2
zhurong 1 month ago
parent
commit
bd0d5a8a27

+ 5
- 0
ceilometer/cmd/polling.py View File

@@ -14,13 +14,17 @@
14 14
 # License for the specific language governing permissions and limitations
15 15
 # under the License.
16 16
 
17
+import shlex
18
+
17 19
 import cotyledon
18 20
 from cotyledon import oslo_config_glue
19 21
 from oslo_config import cfg
20 22
 from oslo_log import log
23
+from oslo_privsep import priv_context
21 24
 
22 25
 from ceilometer.polling import manager
23 26
 from ceilometer import service
27
+from ceilometer import utils
24 28
 
25 29
 LOG = log.getLogger(__name__)
26 30
 
@@ -78,6 +82,7 @@ def main():
78 82
     conf = cfg.ConfigOpts()
79 83
     conf.register_cli_opts(CLI_OPTS)
80 84
     service.prepare_service(conf=conf)
85
+    priv_context.init(root_helper=shlex.split(utils._get_root_helper()))
81 86
     sm = cotyledon.ServiceManager()
82 87
     sm.add(create_polling_service, args=(conf,))
83 88
     oslo_config_glue.setup(sm, conf)

+ 3
- 2
ceilometer/ipmi/platform/ipmitool.py View File

@@ -17,7 +17,8 @@ from oslo_concurrency import processutils
17 17
 
18 18
 from ceilometer.i18n import _
19 19
 from ceilometer.ipmi.platform import exception as ipmiexcept
20
-from ceilometer import utils
20
+
21
+import ceilometer.privsep.ipmitool
21 22
 
22 23
 
23 24
 # Following 2 functions are copied from ironic project to handle ipmitool's
@@ -123,7 +124,7 @@ def execute_ipmi_cmd(template=None):
123 124
             command = f(self, **kwargs)
124 125
             args.extend(command.split(" "))
125 126
             try:
126
-                (out, __) = utils.execute(*args, run_as_root=True)
127
+                (out, __) = ceilometer.privsep.ipmitool.ipmi(*args)
127 128
             except processutils.ProcessExecutionError:
128 129
                 raise ipmiexcept.IPMIException(_("running ipmitool failure"))
129 130
             return _parse_output(out, template)

+ 29
- 0
ceilometer/privsep/__init__.py View File

@@ -0,0 +1,29 @@
1
+#
2
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+#    not use this file except in compliance with the License. You may obtain
4
+#    a copy of the License at
5
+#
6
+#         http://www.apache.org/licenses/LICENSE-2.0
7
+#
8
+#    Unless required by applicable law or agreed to in writing, software
9
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+#    License for the specific language governing permissions and limitations
12
+#    under the License.
13
+
14
+"""Setup privsep decorator."""
15
+
16
+from oslo_privsep import capabilities
17
+from oslo_privsep import priv_context
18
+
19
+sys_admin_pctxt = priv_context.PrivContext(
20
+    'ceilometer',
21
+    cfg_section='ceilometer_sys_admin',
22
+    pypath=__name__ + '.sys_admin_pctxt',
23
+    capabilities=[capabilities.CAP_CHOWN,
24
+                  capabilities.CAP_DAC_OVERRIDE,
25
+                  capabilities.CAP_DAC_READ_SEARCH,
26
+                  capabilities.CAP_FOWNER,
27
+                  capabilities.CAP_NET_ADMIN,
28
+                  capabilities.CAP_SYS_ADMIN],
29
+)

+ 25
- 0
ceilometer/privsep/ipmitool.py View File

@@ -0,0 +1,25 @@
1
+#
2
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+#    not use this file except in compliance with the License. You may obtain
4
+#    a copy of the License at
5
+#
6
+#         http://www.apache.org/licenses/LICENSE-2.0
7
+#
8
+#    Unless required by applicable law or agreed to in writing, software
9
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+#    License for the specific language governing permissions and limitations
12
+#    under the License.
13
+
14
+"""
15
+Helpers for impi related routines.
16
+"""
17
+
18
+from oslo_concurrency import processutils
19
+
20
+import ceilometer.privsep
21
+
22
+
23
+@ceilometer.privsep.sys_admin_pctxt.entrypoint
24
+def ipmi(*cmd):
25
+    processutils.execute(*cmd)

+ 4
- 4
ceilometer/tests/unit/ipmi/platform/test_intel_node_manager.py View File

@@ -20,9 +20,9 @@ from oslotest import base
20 20
 import six
21 21
 
22 22
 from ceilometer.ipmi.platform import intel_node_manager as node_manager
23
+from ceilometer.privsep import ipmitool
23 24
 from ceilometer import service
24 25
 from ceilometer.tests.unit.ipmi.platform import fake_utils
25
-from ceilometer import utils
26 26
 
27 27
 
28 28
 @six.add_metaclass(abc.ABCMeta)
@@ -56,7 +56,7 @@ class _Base(base.BaseTestCase):
56 56
 class TestNodeManagerV3(_Base):
57 57
 
58 58
     def init_test_engine(self):
59
-        utils.execute = mock.Mock(side_effect=fake_utils.execute_with_nm_v3)
59
+        ipmitool.ipmi = mock.Mock(side_effect=fake_utils.execute_with_nm_v3)
60 60
 
61 61
     def test_read_airflow(self):
62 62
         airflow = self.nm.read_airflow()
@@ -110,7 +110,7 @@ class TestNodeManagerV3(_Base):
110 110
 class TestNodeManager(_Base):
111 111
 
112 112
     def init_test_engine(self):
113
-        utils.execute = mock.Mock(side_effect=fake_utils.execute_with_nm_v2)
113
+        ipmitool.ipmi = mock.Mock(side_effect=fake_utils.execute_with_nm_v2)
114 114
 
115 115
     def test_read_power_all(self):
116 116
         power = self.nm.read_power_all()
@@ -162,7 +162,7 @@ class TestNodeManager(_Base):
162 162
 class TestNonNodeManager(_Base):
163 163
 
164 164
     def init_test_engine(self):
165
-        utils.execute = mock.Mock(side_effect=fake_utils.execute_without_nm)
165
+        ipmitool.ipmi = mock.Mock(side_effect=fake_utils.execute_without_nm)
166 166
 
167 167
     def test_read_power_all(self):
168 168
         # no NM support

+ 3
- 3
ceilometer/tests/unit/ipmi/platform/test_ipmi_sensor.py View File

@@ -16,8 +16,8 @@ import mock
16 16
 from oslotest import base
17 17
 
18 18
 from ceilometer.ipmi.platform import ipmi_sensor
19
+from ceilometer.privsep import ipmitool
19 20
 from ceilometer.tests.unit.ipmi.platform import fake_utils
20
-from ceilometer import utils
21 21
 
22 22
 
23 23
 class TestIPMISensor(base.BaseTestCase):
@@ -25,7 +25,7 @@ class TestIPMISensor(base.BaseTestCase):
25 25
     def setUp(self):
26 26
         super(TestIPMISensor, self).setUp()
27 27
 
28
-        utils.execute = mock.Mock(side_effect=fake_utils.execute_with_nm_v2)
28
+        ipmitool.ipmi = mock.Mock(side_effect=fake_utils.execute_with_nm_v2)
29 29
         self.ipmi = ipmi_sensor.IPMISensor()
30 30
 
31 31
     @classmethod
@@ -93,7 +93,7 @@ class TestNonIPMISensor(base.BaseTestCase):
93 93
     def setUp(self):
94 94
         super(TestNonIPMISensor, self).setUp()
95 95
 
96
-        utils.execute = mock.Mock(side_effect=fake_utils.execute_without_ipmi)
96
+        ipmitool.ipmi = mock.Mock(side_effect=fake_utils.execute_without_ipmi)
97 97
         self.ipmi = ipmi_sensor.IPMISensor()
98 98
 
99 99
     @classmethod

+ 0
- 8
ceilometer/utils.py View File

@@ -20,7 +20,6 @@
20 20
 
21 21
 import threading
22 22
 
23
-from oslo_concurrency import processutils
24 23
 from oslo_config import cfg
25 24
 
26 25
 ROOTWRAP_CONF = "/etc/ceilometer/rootwrap.conf"
@@ -43,13 +42,6 @@ def setup_root_helper(conf):
43 42
     ROOTWRAP_CONF = conf.rootwrap_config
44 43
 
45 44
 
46
-def execute(*cmd, **kwargs):
47
-    """Convenience wrapper around oslo's execute() method."""
48
-    if 'run_as_root' in kwargs and 'root_helper' not in kwargs:
49
-        kwargs['root_helper'] = _get_root_helper()
50
-    return processutils.execute(*cmd, **kwargs)
51
-
52
-
53 45
 def spawn_thread(target, *args, **kwargs):
54 46
     t = threading.Thread(target=target, args=args, kwargs=kwargs)
55 47
     t.daemon = True

+ 1
- 3
etc/ceilometer/rootwrap.d/ipmi.filters View File

@@ -2,6 +2,4 @@
2 2
 # This file should be owned by (and only-writeable by) the root user
3 3
 
4 4
 [Filters]
5
-# ceilometer/ipmi/platform/ipmitool.py: 'ipmitool'
6
-ipmitool: CommandFilter, ipmitool, root
7
-
5
+privsep-rootwrap-sys_admin: RegExpFilter, privsep-helper, root, privsep-helper, --config-file, /etc/(?!\.\.).*, --privsep_context, ceilometer.privsep.sys_admin_pctxt, --privsep_sock_path, /tmp/.*

+ 1
- 0
lower-constraints.txt View File

@@ -21,6 +21,7 @@ oslo.i18n==3.15.3
21 21
 oslo.log==3.36.0
22 22
 oslo.messaging==6.2.0
23 23
 oslo.messaging[kafka]==6.2.0
24
+oslo.privsep==1.32.0
24 25
 oslo.reports==1.18.0
25 26
 oslo.rootwrap==2.0.0
26 27
 oslo.utils==3.37.0

+ 15
- 0
releasenotes/notes/switch-to-oslo-privsep-b58f20a279f31bc0.yaml View File

@@ -0,0 +1,15 @@
1
+---
2
+security:
3
+  - |
4
+    Privsep transitions. Ceilometer is transitioning from using the older
5
+    style rootwrap privilege escalation path to the new style Oslo privsep
6
+    path. This should improve performance and security of Ceilometer
7
+    in the long term.
8
+  - |
9
+    Privsep daemons are now started by Ceilometer when required. These
10
+    daemons can be started via rootwrap if required. rootwrap configs
11
+    therefore need to be updated to include new privsep daemon invocations.
12
+upgrade:
13
+  - |
14
+    The following commands are no longer required to be listed in your rootwrap
15
+    configuration: ipmitool.

+ 1
- 0
requirements.txt View File

@@ -19,6 +19,7 @@ oslo.rootwrap>=2.0.0 # Apache-2.0
19 19
 pbr>=2.0.0 # Apache-2.0
20 20
 oslo.messaging>=6.2.0 # Apache-2.0
21 21
 oslo.utils>=3.37.0 # Apache-2.0
22
+oslo.privsep>=1.32.0 # Apache-2.0
22 23
 pysnmp<5.0.0,>=4.2.3 # BSD
23 24
 python-glanceclient>=2.8.0 # Apache-2.0
24 25
 python-keystoneclient>=3.15.0 # Apache-2.0

Loading…
Cancel
Save