Add monasca api read-only user role
This will allow dashboard/operator users to see but not add data. Change-Id: I16a2329356cc9e7d03d2f3e1394127006d6e487e Implements: blueprint read-only-api-user
This commit is contained in:
parent
9d64d3d124
commit
5f37594fe7
2
AUTHORS
2
AUTHORS
|
@ -14,6 +14,7 @@ Derrick Johnson <johnson.derrick@gmail.com>
|
|||
Dexter Fryar <dexter.fryar@outlook.com>
|
||||
Ghanshyam <ghanshyam.mann@nectechnologies.in>
|
||||
Haiwei Xu <xu-haiwei@mxw.nes.nec.co.jp>
|
||||
Igor Natanael <igornsa@lsd.ufcg.edu.br>
|
||||
Janonymous <janonymous.codevulture@gmail.com>
|
||||
Jeremy Stanley <fungi@yuggoth.org>
|
||||
Joe Keen <joe.keen@hp.com>
|
||||
|
@ -35,6 +36,7 @@ Ryan Brandt <ryan.brandt@hp.com>
|
|||
SamKirsch10 <sam.kirsch@hp.com>
|
||||
Shinya Kawabata <s-kawabata@wx.jp.nec.com>
|
||||
Srinivas Sakhamuri <srini.openstack@gmail.com>
|
||||
Swapnil Kulkarni (coolsvap) <me@coolsvap.net>
|
||||
Thomas Graichen <thomas.graichen@sap.com>
|
||||
Tim Kuhlman <tim.kuhlman@hp.com>
|
||||
Tomasz Trębski <tomasz.trebski@ts.fujitsu.com>
|
||||
|
|
|
@ -42,6 +42,7 @@ For secure operation of the Monasca API, the API must be configured to use Keyst
|
|||
* keystore - The keystore holding the SSL Client certificate if connSSLClientAuth is true
|
||||
* keystorePassword - The password for the keystore
|
||||
* defaultAuthorizedRoles - An array of roles that authorize a user to access the complete Monasca API. User must have at least one of these roles. See below
|
||||
* readOnlyAuthorizedRoles - An array of roles that authorize a user to only GET (but not POST, PUT...) metrics. See Keystone Roles below
|
||||
* agentAuthorizedRoles - An array of roles that authorize only the posting of metrics. See Keystone Roles below
|
||||
* adminAuthMethod - "password" if the Monasca API should adminUser and adminPassword to login to the Keystone server to check the user's token, "token" if the Monasca API should use adminToken
|
||||
* adminUser - Admin user name
|
||||
|
@ -61,6 +62,8 @@ The reason for the "Agent access" level is because the Monasca Agent must be con
|
|||
|
||||
To configure the user to have full access, the user must have a role that is listed in defaultAuthorizedRoles. To configure a user to have only "Agent access", the user must have a role in agentAuthorizedRoles and none of the roles in defaultAuthorizedRoles.
|
||||
|
||||
If you want to give users the ability to only view data, configure one or more roles in the readOnlyAuthorizedRoles list.
|
||||
|
||||
## Design Overview
|
||||
|
||||
### Architectural layers
|
||||
|
|
|
@ -165,7 +165,11 @@ def main(argv):
|
|||
{'username': 'demo',
|
||||
'project': 'demo',
|
||||
'password': 'secretadmin',
|
||||
'role': 'monasca-user'}
|
||||
'role': 'monasca-user'},
|
||||
{'username': 'monasca-read-only-user',
|
||||
'project': 'mini-mon',
|
||||
'password': 'password',
|
||||
'role': 'monasca-read-only-user'}
|
||||
]
|
||||
|
||||
service_host = argv[0]
|
||||
|
|
|
@ -105,6 +105,7 @@ middleware:
|
|||
connRetryTimes: 2
|
||||
connRetryInterval: 50
|
||||
defaultAuthorizedRoles: [user, domainuser, domainadmin, monasca-user, admin]
|
||||
readOnlyAuthorizedRoles: [monasca-read-only-user]
|
||||
agentAuthorizedRoles: [monasca-agent]
|
||||
adminAuthMethod: password
|
||||
adminUser: "admin"
|
||||
|
|
|
@ -31,6 +31,9 @@ default_authorized_roles = user, domainuser, domainadmin, monasca-user
|
|||
# The roles that are allowed to only POST metrics to the API. This role would be used by the Monasca Agent.
|
||||
agent_authorized_roles = monasca-agent
|
||||
|
||||
# The roles that are allowed to only GET metrics from the API.
|
||||
read_only_authorized_roles = monasca-read-only-user
|
||||
|
||||
# The roles that are allowed to access the API on behalf of another tenant.
|
||||
# For example, a service can POST metrics to another tenant if they are a member of the "delegate" role.
|
||||
delegate_authorized_roles = admin
|
||||
|
|
|
@ -31,6 +31,9 @@ default_authorized_roles = user, domainuser, domainadmin, monasca-user
|
|||
# The roles that are allowed to only POST metrics to the API. This role would be used by the Monasca Agent.
|
||||
agent_authorized_roles = monasca-agent
|
||||
|
||||
# The roles that are allowed to only GET metrics from the API.
|
||||
read_only_authorized_roles = monasca-read-only-user
|
||||
|
||||
# The roles that are allowed to access the API on behalf of another tenant.
|
||||
# For example, a service can POST metrics to another tenant if they are a member of the "delegate" role.
|
||||
delegate_authorized_roles = admin
|
||||
|
|
|
@ -82,6 +82,7 @@ middleware:
|
|||
connRetryTimes: 2
|
||||
connRetryInterval: 50
|
||||
defaultAuthorizedRoles: [user, domainuser, domainadmin, monasca-user]
|
||||
readOnlyAuthorizedRoles: [monasca-read-only-user]
|
||||
agentAuthorizedRoles: [monasca-agent]
|
||||
adminAuthMethod: password
|
||||
adminUser: admin
|
||||
|
|
|
@ -212,7 +212,8 @@ public class MonApiApplication extends Application<ApiConfig> {
|
|||
environment.servlets().addFilter(
|
||||
"post-auth",
|
||||
new PostAuthenticationFilter(config.middleware.defaultAuthorizedRoles,
|
||||
config.middleware.agentAuthorizedRoles));
|
||||
config.middleware.agentAuthorizedRoles,
|
||||
config.middleware.readOnlyAuthorizedRoles));
|
||||
postAuthenticationFilter.addMappingForUrlPatterns(null, true, "/");
|
||||
postAuthenticationFilter.addMappingForUrlPatterns(null, true, "/v2.0/*");
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ public class MiddlewareConfiguration {
|
|||
@JsonProperty
|
||||
public List<String> defaultAuthorizedRoles;
|
||||
@JsonProperty
|
||||
public List<String> readOnlyAuthorizedRoles;
|
||||
@JsonProperty
|
||||
public List<String> agentAuthorizedRoles;
|
||||
@JsonProperty
|
||||
public String delegateAuthorizedRole;
|
||||
|
|
|
@ -49,15 +49,27 @@ public class PostAuthenticationFilter implements Filter {
|
|||
|
||||
private final List<String> defaultAuthorizedRoles = new ArrayList<String>();
|
||||
private final List<String> agentAuthorizedRoles = new ArrayList<String>();
|
||||
private final List<String> readOnlyAuthorizedRoles = new ArrayList<String>();
|
||||
|
||||
public PostAuthenticationFilter(List<String> defaultAuthorizedRoles,
|
||||
List<String> agentAuthorizedRoles) {
|
||||
List<String> agentAuthorizedRoles,
|
||||
List<String> readOnlyAuthorizedRoles) {
|
||||
for (String defaultRole : defaultAuthorizedRoles) {
|
||||
this.defaultAuthorizedRoles.add(defaultRole.toLowerCase());
|
||||
}
|
||||
for (String agentRole : agentAuthorizedRoles) {
|
||||
this.agentAuthorizedRoles.add(agentRole.toLowerCase());
|
||||
}
|
||||
|
||||
//
|
||||
// Check for null here so we can support backward compatibility
|
||||
// of not setting readOnlyAuthorizedRoles in the config file.
|
||||
//
|
||||
if (null != readOnlyAuthorizedRoles) {
|
||||
for (String readOnlyRole : readOnlyAuthorizedRoles) {
|
||||
this.readOnlyAuthorizedRoles.add(readOnlyRole.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,6 +138,8 @@ public class PostAuthenticationFilter implements Filter {
|
|||
return false;
|
||||
|
||||
boolean agentUser = false;
|
||||
boolean readOnlyUser = false;
|
||||
|
||||
for (String role : rolesFromKeystone.toString().split(",")) {
|
||||
String lowerCaseRole = role.toLowerCase();
|
||||
if ((defaultAuthorizedRoles != null) && defaultAuthorizedRoles.contains(lowerCaseRole)) {
|
||||
|
@ -134,11 +148,20 @@ public class PostAuthenticationFilter implements Filter {
|
|||
if ((agentAuthorizedRoles != null) && agentAuthorizedRoles.contains(lowerCaseRole)) {
|
||||
agentUser = true;
|
||||
}
|
||||
if ((readOnlyAuthorizedRoles != null) && readOnlyAuthorizedRoles.contains(lowerCaseRole)) {
|
||||
readOnlyUser = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (agentUser) {
|
||||
request.setAttribute(X_MONASCA_AGENT, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (readOnlyUser && request.getMethod().equals("GET")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ middleware:
|
|||
connRetryTimes: 2
|
||||
connRetryInterval: 50
|
||||
defaultAuthorizedRoles: [user, domainuser, domainadmin,heat_stack_owner,_member_]
|
||||
readOnlyAuthorizedRoles: [monasca-read-only-user]
|
||||
agentAuthorizedRoles: [monasca-agent]
|
||||
adminAuthMethod: password
|
||||
adminUser: admin
|
||||
|
|
|
@ -42,6 +42,9 @@ security_opts = [cfg.ListOpt('default_authorized_roles', default=['admin'],
|
|||
cfg.ListOpt('agent_authorized_roles', default=['agent'],
|
||||
help='Roles that are only allowed to POST to '
|
||||
'the API'),
|
||||
cfg.ListOpt('read_only_authorized_roles', default=['monasca-read-only-user'],
|
||||
help='Roles that are only allowed to GET from '
|
||||
'the API'),
|
||||
cfg.ListOpt('delegate_authorized_roles', default=['admin'],
|
||||
help='Roles that are allowed to POST metrics on '
|
||||
'behalf of another tenant')]
|
||||
|
|
|
@ -43,6 +43,9 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API,
|
|||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_alarmdefs_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._alarm_definitions_repo = simport.load(
|
||||
cfg.CONF.repositories.alarm_definitions_driver)()
|
||||
|
||||
|
@ -81,7 +84,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API,
|
|||
|
||||
def on_get(self, req, res, alarm_definition_id=None):
|
||||
if alarm_definition_id is None:
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarmdefs_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
name = helpers.get_query_name(req)
|
||||
dimensions = helpers.get_query_dimensions(req)
|
||||
|
@ -114,7 +117,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API,
|
|||
res.status = falcon.HTTP_200
|
||||
|
||||
else:
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarmdefs_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
|
||||
result = self._alarm_definition_show(tenant_id,
|
||||
|
|
|
@ -39,6 +39,9 @@ class Alarms(alarms_api_v2.AlarmsV2API,
|
|||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_alarms_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._alarms_repo = simport.load(
|
||||
cfg.CONF.repositories.alarms_driver)()
|
||||
|
||||
|
@ -112,7 +115,7 @@ class Alarms(alarms_api_v2.AlarmsV2API,
|
|||
res.status = falcon.HTTP_204
|
||||
|
||||
def on_get(self, req, res, alarm_id=None):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarms_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
|
||||
if alarm_id is None:
|
||||
|
@ -384,8 +387,9 @@ class AlarmsCount(alarms_api_v2.AlarmsCountV2API, alarming.Alarming):
|
|||
try:
|
||||
super(AlarmsCount, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_alarms_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._alarms_repo = simport.load(
|
||||
cfg.CONF.repositories.alarms_driver)()
|
||||
|
||||
|
@ -394,7 +398,7 @@ class AlarmsCount(alarms_api_v2.AlarmsCountV2API, alarming.Alarming):
|
|||
raise exceptions.RepositoryException(ex)
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarms_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
query_parms = falcon.uri.parse_query_string(req.query_string)
|
||||
|
||||
|
@ -487,8 +491,9 @@ class AlarmsStateHistory(alarms_api_v2.AlarmsStateHistoryV2API,
|
|||
try:
|
||||
super(AlarmsStateHistory, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_alarms_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._alarms_repo = simport.load(
|
||||
cfg.CONF.repositories.alarms_driver)()
|
||||
self._metrics_repo = simport.load(
|
||||
|
@ -501,7 +506,7 @@ class AlarmsStateHistory(alarms_api_v2.AlarmsStateHistoryV2API,
|
|||
def on_get(self, req, res, alarm_id=None):
|
||||
|
||||
if alarm_id is None:
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarms_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
start_timestamp = helpers.get_query_starttime_timestamp(req, False)
|
||||
end_timestamp = helpers.get_query_endtime_timestamp(req, False)
|
||||
|
@ -517,7 +522,7 @@ class AlarmsStateHistory(alarms_api_v2.AlarmsStateHistoryV2API,
|
|||
res.status = falcon.HTTP_200
|
||||
|
||||
else:
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_alarms_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
offset = helpers.get_query_param(req, 'offset')
|
||||
limit = helpers.get_limit(req)
|
||||
|
|
|
@ -52,10 +52,11 @@ class Metrics(metrics_api_v2.MetricsV2API):
|
|||
try:
|
||||
super(Metrics, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._delegate_authorized_roles = (
|
||||
cfg.CONF.security.delegate_authorized_roles)
|
||||
self._get_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._post_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.agent_authorized_roles)
|
||||
|
@ -129,7 +130,7 @@ class Metrics(metrics_api_v2.MetricsV2API):
|
|||
res.status = falcon.HTTP_204
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
name = helpers.get_query_name(req)
|
||||
helpers.validate_query_name(name)
|
||||
|
@ -152,10 +153,11 @@ class MetricsMeasurements(metrics_api_v2.MetricsMeasurementsV2API):
|
|||
try:
|
||||
super(MetricsMeasurements, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._delegate_authorized_roles = (
|
||||
cfg.CONF.security.delegate_authorized_roles)
|
||||
self._get_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._post_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.agent_authorized_roles)
|
||||
|
@ -168,7 +170,7 @@ class MetricsMeasurements(metrics_api_v2.MetricsMeasurementsV2API):
|
|||
ex.message)
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
name = helpers.get_query_name(req, True)
|
||||
helpers.validate_query_name(name)
|
||||
|
@ -212,8 +214,9 @@ class MetricsStatistics(metrics_api_v2.MetricsStatisticsV2API):
|
|||
try:
|
||||
super(MetricsStatistics, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._metrics_repo = simport.load(
|
||||
cfg.CONF.repositories.metrics_driver)()
|
||||
|
||||
|
@ -223,7 +226,7 @@ class MetricsStatistics(metrics_api_v2.MetricsStatisticsV2API):
|
|||
ex.message)
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
name = helpers.get_query_name(req, True)
|
||||
helpers.validate_query_name(name)
|
||||
|
@ -270,8 +273,9 @@ class MetricsNames(metrics_api_v2.MetricsNamesV2API):
|
|||
try:
|
||||
super(MetricsNames, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._metrics_repo = simport.load(
|
||||
cfg.CONF.repositories.metrics_driver)()
|
||||
|
||||
|
@ -281,7 +285,7 @@ class MetricsNames(metrics_api_v2.MetricsNamesV2API):
|
|||
ex.message)
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
dimensions = helpers.get_query_dimensions(req)
|
||||
helpers.validate_query_dimensions(dimensions)
|
||||
|
@ -309,8 +313,9 @@ class DimensionValues(metrics_api_v2.DimensionValuesV2API):
|
|||
try:
|
||||
super(DimensionValues, self).__init__()
|
||||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_metrics_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._metrics_repo = simport.load(
|
||||
cfg.CONF.repositories.metrics_driver)()
|
||||
|
||||
|
@ -320,7 +325,7 @@ class DimensionValues(metrics_api_v2.DimensionValuesV2API):
|
|||
ex.message)
|
||||
|
||||
def on_get(self, req, res):
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
metric_name = helpers.get_query_param(req, 'metric_name')
|
||||
dimension_name = helpers.get_query_param(req, 'dimension_name', required=True)
|
||||
|
|
|
@ -37,6 +37,9 @@ class Notifications(notifications_api_v2.NotificationsV2API):
|
|||
self._region = cfg.CONF.region
|
||||
self._default_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles)
|
||||
self._get_notifications_authorized_roles = (
|
||||
cfg.CONF.security.default_authorized_roles +
|
||||
cfg.CONF.security.read_only_authorized_roles)
|
||||
self._notifications_repo = simport.load(
|
||||
cfg.CONF.repositories.notifications_driver)()
|
||||
self._notification_method_type_repo = simport.load(
|
||||
|
@ -206,7 +209,8 @@ class Notifications(notifications_api_v2.NotificationsV2API):
|
|||
|
||||
def on_get(self, req, res, notification_method_id=None):
|
||||
if notification_method_id is None:
|
||||
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||
helpers.validate_authorization(req,
|
||||
self._get_notifications_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
sort_by = helpers.get_query_param(req, 'sort_by', default_val=None)
|
||||
if sort_by is not None:
|
||||
|
@ -226,7 +230,7 @@ class Notifications(notifications_api_v2.NotificationsV2API):
|
|||
res.status = falcon.HTTP_200
|
||||
else:
|
||||
helpers.validate_authorization(req,
|
||||
self._default_authorized_roles)
|
||||
self._get_notifications_authorized_roles)
|
||||
tenant_id = helpers.get_tenant_id(req)
|
||||
result = self._list_notification(tenant_id,
|
||||
notification_method_id,
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from monasca_tempest_tests.tests.api import base
|
||||
from monasca_tempest_tests.tests.api import helpers
|
||||
from tempest import test
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from monasca_tempest_tests import clients
|
||||
|
||||
class TestReadOnlyRole(base.BaseMonascaTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestReadOnlyRole, cls).resource_setup()
|
||||
credentials = cls.cred_provider.get_creds_by_roles(
|
||||
['monasca-read-only-user']).credentials
|
||||
cls.os = clients.Manager(credentials=credentials)
|
||||
cls.monasca_client = cls.os.monasca_client
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
super(TestReadOnlyRole, cls).resource_cleanup()
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_alarms_success(self):
|
||||
resp, response_body = self.monasca_client.list_alarms()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any alarms)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_metrics_success(self):
|
||||
resp, response_body = self.monasca_client.list_metrics()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any metrics)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/metrics'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_alarm_definition_success(self):
|
||||
resp, response_body = self.monasca_client.list_alarm_definitions()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any alarm definitions)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarm-definitions'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_notification_methods_success(self):
|
||||
resp, response_body = self.monasca_client.list_notification_methods()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any notifications)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/notification-methods'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_alarm_count_success(self):
|
||||
resp, response_body = self.monasca_client.count_alarms()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any alarms to count)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, response_body['counts'][0][0])
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms/count'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_alarm_state_history_success(self):
|
||||
resp, response_body = self.monasca_client.list_alarms_state_history()
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any alarms that have history)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms/state-history'))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_dimension_values_success(self):
|
||||
parms = '?dimension_name=foo'
|
||||
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any metrics/dimensions)
|
||||
#
|
||||
url = '/v2.0/metrics/dimensions/names/values?dimension_name=foo'
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements'][0]['values']))
|
||||
self.assertTrue(response_body['links'][0]['href'].endswith(url))
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_measurements_success(self):
|
||||
start_timestamp = int(time.time() * 1000)
|
||||
start_time = str(helpers.timestamp_to_iso(start_timestamp))
|
||||
parms = '?name=foo&start_time=' + start_time
|
||||
resp, response_body = self.monasca_client.list_measurements(parms)
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any metrics to get measurements for)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue('/v2.0/metrics/measurements' in response_body['links'][0]['href'])
|
||||
|
||||
|
||||
@test.attr(type="gate")
|
||||
def test_list_statistics_success(self):
|
||||
start_timestamp = int(time.time() * 1000)
|
||||
start_time = str(helpers.timestamp_to_iso(start_timestamp))
|
||||
query_parms = '?name=foo&statistics=avg&start_time=' + start_time
|
||||
resp, response_body = self.monasca_client.list_statistics(
|
||||
query_parms)
|
||||
#
|
||||
# Validate the call succeeds with empty result (we didn't
|
||||
# create any metrics to get statistics for)
|
||||
#
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual(0, len(response_body['elements']))
|
||||
self.assertTrue('/v2.0/metrics/statistics' in response_body['links'][0]['href'])
|
||||
|
||||
@test.attr(type="gate")
|
||||
@test.attr(type=['negative'])
|
||||
def test_delete_alarms_fails(self):
|
||||
self.assertRaises(exceptions.Unauthorized,
|
||||
self.monasca_client.delete_alarm, "foo")
|
||||
|
||||
@test.attr(type='gate')
|
||||
@test.attr(type=['negative'])
|
||||
def test_create_metric_fails(self):
|
||||
self.assertRaises(exceptions.Unauthorized,
|
||||
self.monasca_client.create_metrics,
|
||||
None)
|
||||
|
||||
@test.attr(type="gate")
|
||||
@test.attr(type=['negative'])
|
||||
def test_create_alarm_definition_fails(self):
|
||||
self.assertRaises(exceptions.Unauthorized,
|
||||
self.monasca_client.create_alarm_definitions,
|
||||
None)
|
||||
|
||||
@test.attr(type="gate")
|
||||
@test.attr(type=['negative'])
|
||||
def test_create_notification_fails(self):
|
||||
notif = helpers.create_notification()
|
||||
self.assertRaises(exceptions.Unauthorized,
|
||||
self.monasca_client.create_notifications,
|
||||
notif)
|
Loading…
Reference in New Issue