[policy in code] part 4
Add service rule, resource rules, actions rules, build_info rules, events rules. Partially-Implements: bp policy-in-code Change-Id: I497f4d02b5ea8399265dedc548214e4eca6b6a35
This commit is contained in:
parent
46f0e16d11
commit
51e4f04693
@ -25,16 +25,6 @@
|
|||||||
"cloudwatch:PutMetricData": "",
|
"cloudwatch:PutMetricData": "",
|
||||||
"cloudwatch:SetAlarmState": "rule:deny_stack_user",
|
"cloudwatch:SetAlarmState": "rule:deny_stack_user",
|
||||||
|
|
||||||
"actions:action": "rule:deny_stack_user",
|
|
||||||
"build_info:build_info": "rule:deny_stack_user",
|
|
||||||
"events:index": "rule:deny_stack_user",
|
|
||||||
"events:show": "rule:deny_stack_user",
|
|
||||||
"resource:index": "rule:deny_stack_user",
|
|
||||||
"resource:metadata": "",
|
|
||||||
"resource:signal": "",
|
|
||||||
"resource:mark_unhealthy": "rule:deny_stack_user",
|
|
||||||
"resource:show": "rule:deny_stack_user",
|
|
||||||
|
|
||||||
"software_configs:global_index": "rule:deny_everybody",
|
"software_configs:global_index": "rule:deny_everybody",
|
||||||
"software_configs:index": "rule:deny_stack_user",
|
"software_configs:index": "rule:deny_stack_user",
|
||||||
"software_configs:create": "rule:deny_stack_user",
|
"software_configs:create": "rule:deny_stack_user",
|
||||||
@ -45,7 +35,5 @@
|
|||||||
"software_deployments:show": "rule:deny_stack_user",
|
"software_deployments:show": "rule:deny_stack_user",
|
||||||
"software_deployments:update": "rule:deny_stack_user",
|
"software_deployments:update": "rule:deny_stack_user",
|
||||||
"software_deployments:delete": "rule:deny_stack_user",
|
"software_deployments:delete": "rule:deny_stack_user",
|
||||||
"software_deployments:metadata": "",
|
"software_deployments:metadata": ""
|
||||||
|
|
||||||
"service:index": "rule:context_is_admin"
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ class ActionController(object):
|
|||||||
|
|
||||||
Implements the API for stack actions
|
Implements the API for stack actions
|
||||||
"""
|
"""
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json or policies in
|
||||||
|
# code)
|
||||||
REQUEST_SCOPE = 'actions'
|
REQUEST_SCOPE = 'actions'
|
||||||
|
|
||||||
ACTIONS = (
|
ACTIONS = (
|
||||||
@ -41,7 +42,7 @@ class ActionController(object):
|
|||||||
self.options = options
|
self.options = options
|
||||||
self.rpc_client = rpc_client.EngineClient()
|
self.rpc_client = rpc_client.EngineClient()
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def action(self, req, identity, body=None):
|
def action(self, req, identity, body=None):
|
||||||
"""Performs a specified action on a stack.
|
"""Performs a specified action on a stack.
|
||||||
|
|
||||||
|
@ -24,14 +24,15 @@ class BuildInfoController(object):
|
|||||||
|
|
||||||
Returns build information for current app.
|
Returns build information for current app.
|
||||||
"""
|
"""
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json or policies in
|
||||||
|
# code)
|
||||||
REQUEST_SCOPE = 'build_info'
|
REQUEST_SCOPE = 'build_info'
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
self.rpc_client = rpc_client.EngineClient()
|
self.rpc_client = rpc_client.EngineClient()
|
||||||
|
|
||||||
@util.policy_enforce
|
@util.registered_policy_enforce
|
||||||
def build_info(self, req):
|
def build_info(self, req):
|
||||||
engine_revision = self.rpc_client.get_revision(req.context)
|
engine_revision = self.rpc_client.get_revision(req.context)
|
||||||
build_info = {
|
build_info = {
|
||||||
|
@ -84,7 +84,8 @@ class EventController(object):
|
|||||||
|
|
||||||
Implements the API actions.
|
Implements the API actions.
|
||||||
"""
|
"""
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json or policies in
|
||||||
|
# code)
|
||||||
REQUEST_SCOPE = 'events'
|
REQUEST_SCOPE = 'events'
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options):
|
||||||
@ -106,7 +107,7 @@ class EventController(object):
|
|||||||
|
|
||||||
return [format_event(req, e, keys) for e in events]
|
return [format_event(req, e, keys) for e in events]
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def index(self, req, identity, resource_name=None):
|
def index(self, req, identity, resource_name=None):
|
||||||
"""Lists summary information for all events."""
|
"""Lists summary information for all events."""
|
||||||
whitelist = {
|
whitelist = {
|
||||||
@ -149,7 +150,7 @@ class EventController(object):
|
|||||||
|
|
||||||
return {'events': events}
|
return {'events': events}
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def show(self, req, identity, resource_name, event_id):
|
def show(self, req, identity, resource_name, event_id):
|
||||||
"""Gets detailed information for an event."""
|
"""Gets detailed information for an event."""
|
||||||
|
|
||||||
|
@ -75,7 +75,8 @@ class ResourceController(object):
|
|||||||
|
|
||||||
Implements the API actions.
|
Implements the API actions.
|
||||||
"""
|
"""
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json or policies in
|
||||||
|
# code)
|
||||||
REQUEST_SCOPE = 'resource'
|
REQUEST_SCOPE = 'resource'
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options):
|
||||||
@ -92,7 +93,7 @@ class ResourceController(object):
|
|||||||
else:
|
else:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def index(self, req, identity):
|
def index(self, req, identity):
|
||||||
"""Lists information for all resources."""
|
"""Lists information for all resources."""
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ class ResourceController(object):
|
|||||||
|
|
||||||
return {'resources': [format_resource(req, res) for res in res_list]}
|
return {'resources': [format_resource(req, res) for res in res_list]}
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def show(self, req, identity, resource_name):
|
def show(self, req, identity, resource_name):
|
||||||
"""Gets detailed information for a resource."""
|
"""Gets detailed information for a resource."""
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ class ResourceController(object):
|
|||||||
|
|
||||||
return {'resource': format_resource(req, res)}
|
return {'resource': format_resource(req, res)}
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def metadata(self, req, identity, resource_name):
|
def metadata(self, req, identity, resource_name):
|
||||||
"""Gets metadata information for a resource."""
|
"""Gets metadata information for a resource."""
|
||||||
|
|
||||||
@ -156,14 +157,14 @@ class ResourceController(object):
|
|||||||
|
|
||||||
return {rpc_api.RES_METADATA: res[rpc_api.RES_METADATA]}
|
return {rpc_api.RES_METADATA: res[rpc_api.RES_METADATA]}
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def signal(self, req, identity, resource_name, body=None):
|
def signal(self, req, identity, resource_name, body=None):
|
||||||
self.rpc_client.resource_signal(req.context,
|
self.rpc_client.resource_signal(req.context,
|
||||||
stack_identity=identity,
|
stack_identity=identity,
|
||||||
resource_name=resource_name,
|
resource_name=resource_name,
|
||||||
details=body)
|
details=body)
|
||||||
|
|
||||||
@util.identified_stack
|
@util.registered_identified_stack
|
||||||
def mark_unhealthy(self, req, identity, resource_name, body):
|
def mark_unhealthy(self, req, identity, resource_name, body):
|
||||||
"""Mark a resource as healthy or unhealthy."""
|
"""Mark a resource as healthy or unhealthy."""
|
||||||
data = dict()
|
data = dict()
|
||||||
|
@ -25,14 +25,15 @@ from heat.rpc import client as rpc_client
|
|||||||
|
|
||||||
class ServiceController(object):
|
class ServiceController(object):
|
||||||
"""WSGI controller for reporting the heat engine status in Heat v1 API."""
|
"""WSGI controller for reporting the heat engine status in Heat v1 API."""
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json or policies in
|
||||||
|
# code)
|
||||||
REQUEST_SCOPE = 'service'
|
REQUEST_SCOPE = 'service'
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
self.rpc_client = rpc_client.EngineClient()
|
self.rpc_client = rpc_client.EngineClient()
|
||||||
|
|
||||||
@util.policy_enforce
|
@util.registered_policy_enforce
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
try:
|
try:
|
||||||
services = self.rpc_client.list_services(req.context)
|
services = self.rpc_client.list_services(req.context)
|
||||||
|
@ -13,14 +13,24 @@
|
|||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from heat.policies import actions
|
||||||
from heat.policies import base
|
from heat.policies import base
|
||||||
|
from heat.policies import build_info
|
||||||
|
from heat.policies import events
|
||||||
|
from heat.policies import resource
|
||||||
from heat.policies import resource_types
|
from heat.policies import resource_types
|
||||||
|
from heat.policies import service
|
||||||
from heat.policies import stacks
|
from heat.policies import stacks
|
||||||
|
|
||||||
|
|
||||||
def list_rules():
|
def list_rules():
|
||||||
return itertools.chain(
|
return itertools.chain(
|
||||||
base.list_rules(),
|
base.list_rules(),
|
||||||
stacks.list_rules(),
|
actions.list_rules(),
|
||||||
|
build_info.list_rules(),
|
||||||
|
events.list_rules(),
|
||||||
|
resource.list_rules(),
|
||||||
resource_types.list_rules(),
|
resource_types.list_rules(),
|
||||||
|
service.list_rules(),
|
||||||
|
stacks.list_rules(),
|
||||||
)
|
)
|
||||||
|
37
heat/policies/actions.py
Normal file
37
heat/policies/actions.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from heat.policies import base
|
||||||
|
|
||||||
|
POLICY_ROOT = 'actions:%s'
|
||||||
|
|
||||||
|
actions_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'action',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='Performs non-lifecycle operations on the stack '
|
||||||
|
'(Snapshot, Resume, Cancel update, or check stack resources).',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'actions',
|
||||||
|
'method': 'POST'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return actions_policies
|
35
heat/policies/build_info.py
Normal file
35
heat/policies/build_info.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from heat.policies import base
|
||||||
|
|
||||||
|
POLICY_ROOT = 'build_info:%s'
|
||||||
|
|
||||||
|
build_info_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'build_info',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='Show build information.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/build_info',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return build_info_policies
|
48
heat/policies/events.py
Normal file
48
heat/policies/events.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from heat.policies import base
|
||||||
|
|
||||||
|
POLICY_ROOT = 'events:%s'
|
||||||
|
|
||||||
|
events_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'index',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='List events.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'events',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'show',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='Show event.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources/{resource_name}/events/{event_id}',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return events_policies
|
84
heat/policies/resource.py
Normal file
84
heat/policies/resource.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from heat.policies import base
|
||||||
|
|
||||||
|
POLICY_ROOT = 'resource:%s'
|
||||||
|
|
||||||
|
resource_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'index',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='List resources.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'metadata',
|
||||||
|
check_str=base.RULE_ALLOW_EVERYBODY,
|
||||||
|
description='Show resource metadata.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources/{resource_name}/metadata',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'signal',
|
||||||
|
check_str=base.RULE_ALLOW_EVERYBODY,
|
||||||
|
description='Signal resource.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources/{resource_name}/signal',
|
||||||
|
'method': 'POST'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'mark_unhealthy',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='Mark resource as unhealthy.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources/{resource_name_or_physical_id}',
|
||||||
|
'method': 'PATCH'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=POLICY_ROOT % 'show',
|
||||||
|
check_str=base.RULE_DENY_STACK_USER,
|
||||||
|
description='Show resource.',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/'
|
||||||
|
'resources/{resource_name}',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return resource_policies
|
27
heat/policies/service.py
Normal file
27
heat/policies/service.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from heat.policies import base
|
||||||
|
|
||||||
|
POLICY_ROOT = 'service:%s'
|
||||||
|
|
||||||
|
service_policies = [
|
||||||
|
policy.RuleDefault(
|
||||||
|
name=POLICY_ROOT % 'index',
|
||||||
|
check_str=base.RULE_CONTEXT_IS_ADMIN)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return service_policies
|
Loading…
Reference in New Issue
Block a user