Add security-checklist action
Change-Id: I717ddc16d29d4e45e374c98e6e0f7913c9583522
This commit is contained in:
committed by
Chris MacNaughton
parent
a585c314b0
commit
370e4b8380
@@ -19,7 +19,7 @@ from enum import Enum
|
||||
import traceback
|
||||
|
||||
from charmhelpers.core.host import cmp_pkgrevno
|
||||
|
||||
import charmhelpers.contrib.openstack.utils as openstack_utils
|
||||
import charmhelpers.core.hookenv as hookenv
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ def audit(*args):
|
||||
deployed system that matches the given configuration
|
||||
|
||||
:param args: List of functions to filter tests against
|
||||
:type args: List[Callable(Config)]
|
||||
:type args: List[Callable[Dict]]
|
||||
"""
|
||||
def wrapper(f):
|
||||
test_name = f.__name__
|
||||
@@ -58,28 +58,92 @@ def audit(*args):
|
||||
|
||||
|
||||
def is_audit_type(*args):
|
||||
"""This audit is included in the specified kinds of audits."""
|
||||
def should_run(audit_options):
|
||||
"""This audit is included in the specified kinds of audits.
|
||||
|
||||
:param *args: List of AuditTypes to include this audit in
|
||||
:type args: List[AuditType]
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _is_audit_type(audit_options):
|
||||
if audit_options.get('audit_type') in args:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return should_run
|
||||
return _is_audit_type
|
||||
|
||||
|
||||
def since_package(pkg, pkg_version):
|
||||
"""This audit should be run after the specified package version (incl)."""
|
||||
return lambda audit_options=None: cmp_pkgrevno(pkg, pkg_version) >= 0
|
||||
"""This audit should be run after the specified package version (incl).
|
||||
|
||||
:param pkg: Package name to compare
|
||||
:type pkg: str
|
||||
:param release: The package version
|
||||
:type release: str
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _since_package(audit_options=None):
|
||||
return cmp_pkgrevno(pkg, pkg_version) >= 0
|
||||
|
||||
return _since_package
|
||||
|
||||
|
||||
def before_package(pkg, pkg_version):
|
||||
"""This audit should be run before the specified package version (excl)."""
|
||||
return lambda audit_options=None: not since_package(pkg, pkg_version)()
|
||||
"""This audit should be run before the specified package version (excl).
|
||||
|
||||
:param pkg: Package name to compare
|
||||
:type pkg: str
|
||||
:param release: The package version
|
||||
:type release: str
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _before_package(audit_options=None):
|
||||
return not since_package(pkg, pkg_version)()
|
||||
|
||||
return _before_package
|
||||
|
||||
|
||||
def since_openstack_release(pkg, release):
|
||||
"""This audit should run after the specified OpenStack version (incl).
|
||||
|
||||
:param pkg: Package name to compare
|
||||
:type pkg: str
|
||||
:param release: The OpenStack release codename
|
||||
:type release: str
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _since_openstack_release(audit_options=None):
|
||||
_release = openstack_utils.get_os_codename_package(pkg)
|
||||
return openstack_utils.CompareOpenStackReleases(_release) >= release
|
||||
|
||||
return _since_openstack_release
|
||||
|
||||
|
||||
def before_openstack_release(pkg, release):
|
||||
"""This audit should run before the specified OpenStack version (excl).
|
||||
|
||||
:param pkg: Package name to compare
|
||||
:type pkg: str
|
||||
:param release: The OpenStack release codename
|
||||
:type release: str
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _before_openstack_release(audit_options=None):
|
||||
return not since_openstack_release(pkg, release)()
|
||||
|
||||
return _before_openstack_release
|
||||
|
||||
|
||||
def it_has_config(config_key):
|
||||
"""This audit should be run based on specified config keys."""
|
||||
return lambda audit_options: audit_options.get(config_key) is not None
|
||||
"""This audit should be run based on specified config keys.
|
||||
|
||||
:param config_key: Config key to look for
|
||||
:type config_key: str
|
||||
:rtype: Callable[Dict]
|
||||
"""
|
||||
def _it_has_config(audit_options):
|
||||
return audit_options.get(config_key) is not None
|
||||
|
||||
return _it_has_config
|
||||
|
||||
|
||||
def run(audit_options):
|
||||
@@ -87,11 +151,19 @@ def run(audit_options):
|
||||
|
||||
:param audit_options: Configuration for the audit
|
||||
:type audit_options: Config
|
||||
|
||||
:rtype: Dict[str, str]
|
||||
"""
|
||||
errors = {}
|
||||
results = {}
|
||||
for name, audit in sorted(_audits.items()):
|
||||
result_name = name.replace('_', '-')
|
||||
if result_name in audit_options.get('excludes', []):
|
||||
print(
|
||||
"Skipping {} because it is"
|
||||
"excluded in audit config"
|
||||
.format(result_name))
|
||||
continue
|
||||
if all(p(audit_options) for p in audit.filters):
|
||||
try:
|
||||
audit.func(audit_options)
|
||||
@@ -121,7 +193,13 @@ def run(audit_options):
|
||||
|
||||
|
||||
def action_parse_results(result):
|
||||
"""Parse the result of `run` in the context of an action."""
|
||||
"""Parse the result of `run` in the context of an action.
|
||||
|
||||
:param result: The result of running the security-checklist
|
||||
action on a unit
|
||||
:type result: Dict[str, Dict[str, str]]
|
||||
:rtype: int
|
||||
"""
|
||||
passed = True
|
||||
for test, result in result.items():
|
||||
if result['success']:
|
||||
|
||||
@@ -194,7 +194,7 @@ SWIFT_CODENAMES = OrderedDict([
|
||||
('rocky',
|
||||
['2.18.0', '2.19.0']),
|
||||
('stein',
|
||||
['2.19.0']),
|
||||
['2.20.0']),
|
||||
])
|
||||
|
||||
# >= Liberty version->codename mapping
|
||||
|
||||
@@ -582,21 +582,24 @@ def remove_pool_snapshot(service, pool_name, snapshot_name):
|
||||
raise
|
||||
|
||||
|
||||
# max_bytes should be an int or long
|
||||
def set_pool_quota(service, pool_name, max_bytes):
|
||||
def set_pool_quota(service, pool_name, max_bytes=None, max_objects=None):
|
||||
"""
|
||||
:param service: six.string_types. The Ceph user name to run the command under
|
||||
:param pool_name: six.string_types
|
||||
:param max_bytes: int or long
|
||||
:return: None. Can raise CalledProcessError
|
||||
:param service: The Ceph user name to run the command under
|
||||
:type service: str
|
||||
:param pool_name: Name of pool
|
||||
:type pool_name: str
|
||||
:param max_bytes: Maximum bytes quota to apply
|
||||
:type max_bytes: int
|
||||
:param max_objects: Maximum objects quota to apply
|
||||
:type max_objects: int
|
||||
:raises: subprocess.CalledProcessError
|
||||
"""
|
||||
# Set a byte quota on a RADOS pool in ceph.
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set-quota', pool_name,
|
||||
'max_bytes', str(max_bytes)]
|
||||
try:
|
||||
check_call(cmd)
|
||||
except CalledProcessError:
|
||||
raise
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set-quota', pool_name]
|
||||
if max_bytes:
|
||||
cmd = cmd + ['max_bytes', str(max_bytes)]
|
||||
if max_objects:
|
||||
cmd = cmd + ['max_objects', str(max_objects)]
|
||||
check_call(cmd)
|
||||
|
||||
|
||||
def remove_pool_quota(service, pool_name):
|
||||
@@ -1153,19 +1156,46 @@ class CephBrokerRq(object):
|
||||
|
||||
def add_op_create_pool(self, name, replica_count=3, pg_num=None,
|
||||
weight=None, group=None, namespace=None,
|
||||
app_name=None):
|
||||
"""Adds an operation to create a pool.
|
||||
app_name=None, max_bytes=None, max_objects=None):
|
||||
"""DEPRECATED: Use ``add_op_create_replicated_pool()`` or
|
||||
``add_op_create_erasure_pool()`` instead.
|
||||
"""
|
||||
return self.add_op_create_replicated_pool(
|
||||
name, replica_count=replica_count, pg_num=pg_num, weight=weight,
|
||||
group=group, namespace=namespace, app_name=app_name,
|
||||
max_bytes=max_bytes, max_objects=max_objects)
|
||||
|
||||
@param pg_num setting: optional setting. If not provided, this value
|
||||
will be calculated by the broker based on how many OSDs are in the
|
||||
cluster at the time of creation. Note that, if provided, this value
|
||||
will be capped at the current available maximum.
|
||||
@param weight: the percentage of data the pool makes up
|
||||
def add_op_create_replicated_pool(self, name, replica_count=3, pg_num=None,
|
||||
weight=None, group=None, namespace=None,
|
||||
app_name=None, max_bytes=None,
|
||||
max_objects=None):
|
||||
"""Adds an operation to create a replicated pool.
|
||||
|
||||
:param name: Name of pool to create
|
||||
:type name: str
|
||||
:param replica_count: Number of copies Ceph should keep of your data.
|
||||
:type replica_count: int
|
||||
:param pg_num: Request specific number of Placement Groups to create
|
||||
for pool.
|
||||
:type pg_num: int
|
||||
:param weight: The percentage of data that is expected to be contained
|
||||
in the pool from the total available space on the OSDs.
|
||||
Used to calculate number of Placement Groups to create
|
||||
for pool.
|
||||
:type weight: float
|
||||
:param group: Group to add pool to
|
||||
:type group: str
|
||||
:param namespace: Group namespace
|
||||
:type namespace: str
|
||||
:param app_name: (Optional) Tag pool with application name. Note that
|
||||
there is certain protocols emerging upstream with
|
||||
regard to meaningful application names to use.
|
||||
Examples are ``rbd`` and ``rgw``.
|
||||
:type app_name: str
|
||||
:param max_bytes: Maximum bytes quota to apply
|
||||
:type max_bytes: int
|
||||
:param max_objects: Maximum objects quota to apply
|
||||
:type max_objects: int
|
||||
"""
|
||||
if pg_num and weight:
|
||||
raise ValueError('pg_num and weight are mutually exclusive')
|
||||
@@ -1173,7 +1203,41 @@ class CephBrokerRq(object):
|
||||
self.ops.append({'op': 'create-pool', 'name': name,
|
||||
'replicas': replica_count, 'pg_num': pg_num,
|
||||
'weight': weight, 'group': group,
|
||||
'group-namespace': namespace, 'app-name': app_name})
|
||||
'group-namespace': namespace, 'app-name': app_name,
|
||||
'max-bytes': max_bytes, 'max-objects': max_objects})
|
||||
|
||||
def add_op_create_erasure_pool(self, name, erasure_profile=None,
|
||||
weight=None, group=None, app_name=None,
|
||||
max_bytes=None, max_objects=None):
|
||||
"""Adds an operation to create a erasure coded pool.
|
||||
|
||||
:param name: Name of pool to create
|
||||
:type name: str
|
||||
:param erasure_profile: Name of erasure code profile to use. If not
|
||||
set the ceph-mon unit handling the broker
|
||||
request will set its default value.
|
||||
:type erasure_profile: str
|
||||
:param weight: The percentage of data that is expected to be contained
|
||||
in the pool from the total available space on the OSDs.
|
||||
:type weight: float
|
||||
:param group: Group to add pool to
|
||||
:type group: str
|
||||
:param app_name: (Optional) Tag pool with application name. Note that
|
||||
there is certain protocols emerging upstream with
|
||||
regard to meaningful application names to use.
|
||||
Examples are ``rbd`` and ``rgw``.
|
||||
:type app_name: str
|
||||
:param max_bytes: Maximum bytes quota to apply
|
||||
:type max_bytes: int
|
||||
:param max_objects: Maximum objects quota to apply
|
||||
:type max_objects: int
|
||||
"""
|
||||
self.ops.append({'op': 'create-pool', 'name': name,
|
||||
'pool-type': 'erasure',
|
||||
'erasure-profile': erasure_profile,
|
||||
'weight': weight,
|
||||
'group': group, 'app-name': app_name,
|
||||
'max-bytes': max_bytes, 'max-objects': max_objects})
|
||||
|
||||
def set_ops(self, ops):
|
||||
"""Set request ops to provided value.
|
||||
|
||||
Reference in New Issue
Block a user