Merge "gnocchi: fix alarms for unpriviledged user"

This commit is contained in:
Jenkins 2017-06-21 17:24:59 +00:00 committed by Gerrit Code Review
commit e2403f02c7
4 changed files with 71 additions and 8 deletions

View File

@ -18,6 +18,8 @@ import threading
import cachetools
from gnocchiclient import client
from gnocchiclient import exceptions
from keystoneauth1 import exceptions as ka_exceptions
from oslo_config import cfg
from oslo_serialization import jsonutils
import pecan
import wsme
@ -28,6 +30,14 @@ from aodh.api.controllers.v2 import utils as v2_utils
from aodh import keystone_client
GNOCCHI_OPTS = [
cfg.StrOpt('gnocchi_external_project_owner',
default="service",
help='Project name of resources creator in Gnocchi. '
'(For example the Ceilometer project name'),
]
class GnocchiUnavailable(Exception):
code = 503
@ -122,6 +132,20 @@ class AggregationMetricByResourcesLookupRule(AlarmGnocchiThresholdRule):
'resource_type'])
return rule
cache = cachetools.TTLCache(maxsize=1, ttl=3600)
lock = threading.RLock()
@staticmethod
@cachetools.cached(cache, lock=lock)
def get_external_project_owner():
kc = keystone_client.get_client(pecan.request.cfg)
project_name = pecan.request.cfg.api.gnocchi_external_project_owner
try:
project = kc.projects.find(name=project_name)
return project.id
except ka_exceptions.NotFound:
return None
@classmethod
def validate_alarm(cls, alarm):
super(AggregationMetricByResourcesLookupRule,
@ -135,14 +159,27 @@ class AggregationMetricByResourcesLookupRule(AlarmGnocchiThresholdRule):
except ValueError:
raise wsme.exc.InvalidInput('rule/query', rule.query)
conf = pecan.request.cfg
# Scope the alarm to the project id if needed
auth_project = v2_utils.get_auth_project(alarm.project_id)
if auth_project:
query = {"and": [{"=": {"created_by_project_id": auth_project}},
query]}
perms_filter = {"=": {"created_by_project_id": auth_project}}
external_project_owner = cls.get_external_project_owner()
if external_project_owner:
perms_filter = {"or": [
perms_filter,
{"and": [
{"=": {"created_by_project_id":
external_project_owner}},
{"=": {"project_id": auth_project}}]}
]}
query = {"and": [perms_filter, query]}
rule.query = jsonutils.dumps(query)
conf = pecan.request.cfg
gnocchi_client = client.Client(
'1', keystone_client.get_session(conf),
interface=conf.service_credentials.interface,

View File

@ -16,6 +16,7 @@ import itertools
from keystoneauth1 import loading
import aodh.api
import aodh.api.controllers.v2.alarm_rules.gnocchi
import aodh.api.controllers.v2.alarms
import aodh.coordination
import aodh.evaluator
@ -42,6 +43,7 @@ def list_opts():
('api',
itertools.chain(
aodh.api.OPTS,
aodh.api.controllers.v2.alarm_rules.gnocchi.GNOCCHI_OPTS,
aodh.api.controllers.v2.alarms.ALARM_API_OPTS)),
('coordination', aodh.coordination.OPTS),
('database', aodh.storage.OPTS),

View File

@ -2607,7 +2607,9 @@ class TestAlarmsRuleGnocchi(TestAlarmsBase):
self.assertEqual(1, len(alarms))
self._verify_alarm(json, alarms[0])
def test_post_gnocchi_aggregation_alarm_project_constraint(self):
@mock.patch('aodh.keystone_client.get_client')
def test_post_gnocchi_aggregation_alarm_project_constraint(self,
get_client):
json = {
'enabled': False,
'name': 'project_constraint',
@ -2630,10 +2632,21 @@ class TestAlarmsRuleGnocchi(TestAlarmsBase):
}
}
expected_query = {"and": [{"=": {"created_by_project_id":
self.auth_headers['X-Project-Id']}},
{"=": {"server_group":
"my_autoscaling_group"}}]}
expected_query = {"and": [
{"or": [
{"=": {"created_by_project_id":
self.auth_headers['X-Project-Id']}},
{"and": [
{"=": {"created_by_project_id": "<my-uuid>"}},
{"=": {"project_id": self.auth_headers['X-Project-Id']}}
]},
]},
{"=": {"server_group": "my_autoscaling_group"}},
]}
ks_client = mock.Mock()
ks_client.projects.find.return_value = mock.Mock(id='<my-uuid>')
get_client.return_value = ks_client
with mock.patch('aodh.api.controllers.v2.alarm_rules.'
'gnocchi.client') as clientlib:

View File

@ -0,0 +1,11 @@
---
fixes:
- |
When an unprivileged user want to access to Gnocchi resources created by
Ceilometer, that doesn't work because the filter scope the Gnocchi query to
resource owner to the user. To fix we introduce a new configuration option
"gnocchi_external_project_owner" set by default to "service". The new
filter now allow two kind of Gnocchi resources:
* owned by the user project
* owned by "gnocchi_external_project_owner" and the orignal project_id of
the resource is the user project.