Add keystone audit middleware API logging

This commit adds Keystone audit middleware API logging to the Cinder
charm in versions Yoga and newer to allow users to configure their
environment for CADF compliance. This feature can be enabled/disabled
and is set to 'disabled' by default to avoid bloat in log files.
The logging output is configured to /var/log/apache2/cinder_error.log.
This commit builds on previous discussions:
https://github.com/juju/charm-helpers/pull/808.

Related-Pr: https://github.com/juju/charm-helpers/pull/893
func-test-pr: https://github.com/openstack-charmers/zaza-openstack-tests/pull/1200
Closes-Bug: 1856555
Change-Id: I0066e0f91e97621a4efa4d000ba8eb40ccb17cda
This commit is contained in:
Myles Penner 2024-04-18 15:19:06 -07:00
parent 6697f415ea
commit 9317a61151
5 changed files with 241 additions and 8 deletions

View File

@ -12,6 +12,11 @@ options:
default: False
description: |
Setting this to True will allow supporting services to log to syslog.
audit-middleware:
type: boolean
default: False
description: |
Enable Keystone auditing middleware for logging API calls.
openstack-origin:
type: string
default: bobcat
@ -127,10 +132,10 @@ options:
description: Database to request access.
rabbit-user:
type: string
default: cinder
description: Username to request access on rabbitmq-server.
rabbit-vhost:
type: string
default: cinder api_paste_content = zaza.model.file_contents(
self.lead_unit,
api_paste_ini_path,
)
default: openstack
description: RabbitMQ virtual host to request access on rabbitmq-server.
region:
@ -312,7 +317,10 @@ options:
type: string
default:
description: |
The IP address and netmask of the OpenStack Public network (e.g.
The IP address and netmask of the api_paste_content = zaza.model.file_contents(
self.lead_unit,
api_paste_ini_path,
)OpenStack Public network (e.g.
192.168.0.0/24)
.
This network will be used for public endpoints.

View File

@ -167,6 +167,7 @@ CINDER_CONF_DIR = "/etc/cinder"
CINDER_CONF = '%s/cinder.conf' % CINDER_CONF_DIR
CINDER_API_CONF = '%s/api-paste.ini' % CINDER_CONF_DIR
CINDER_POLICY_JSON = '%s/policy.json' % CINDER_CONF_DIR
CINDER_AUDIT_MAP = '%s/api_audit_map.conf' % CINDER_CONF_DIR
CEPH_CONF = '/etc/ceph/ceph.conf'
HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
@ -237,18 +238,24 @@ BASE_RESOURCE_MAP = OrderedDict([
cinder_contexts.VolumeUsageAuditContext(),
context.MemcacheContext(),
cinder_contexts.SectionalConfigContext(),
cinder_contexts.LVMContext()],
cinder_contexts.LVMContext(),
context.KeystoneAuditMiddleware(service='cinder')],
'services': ['cinder-api', 'cinder-volume', 'cinder-scheduler',
'haproxy']
}),
(CINDER_API_CONF, {
'contexts': [context.IdentityServiceContext()],
'contexts': [context.IdentityServiceContext(),
context.KeystoneAuditMiddleware(service='cinder')],
'services': ['cinder-api'],
}),
(CINDER_POLICY_JSON, {
'contexts': [],
'services': ['cinder-api']
}),
(CINDER_AUDIT_MAP, {
'contexts': [context.KeystoneAuditMiddleware(service='cinder')],
'services': ['cinder-api']
}),
(ceph_config_file(), {
'contexts': [context.CephContext()],
'services': ['cinder-volume']
@ -773,7 +780,7 @@ def check_local_db_actions_complete():
# Echo notification
data = {CINDER_DB_INIT_ECHO_RKEY: init_id}
# BUG: #1928383 - clear CINDER_DB_INIT_RKEY if not the leader
if not(is_elected_leader(CLUSTER_RES)):
if not is_elected_leader(CLUSTER_RES):
data[CINDER_DB_INIT_RKEY] = None
relation_set(**data)

View File

@ -0,0 +1,101 @@
#############
# OpenStack #
#############
[composite:osapi_volume]
use = call:cinder.api:root_app_factory
/: apiversions
/healthcheck: healthcheck
/v1: openstack_volume_api_v1
/v2: openstack_volume_api_v2
/v3: openstack_volume_api_v3
[composite:openstack_volume_api_v1]
use = call:cinder.api.middleware.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv1
{% if audit_middleware and service_name -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv1
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv1
{% else -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv1
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv1
{% endif %}
[composite:openstack_volume_api_v2]
use = call:cinder.api.middleware.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv2
{% if audit_middleware and service_name -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv2
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv2
{% else -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv2
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv2
{% endif %}
[composite:openstack_volume_api_v3]
use = call:cinder.api.middleware.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv3
{% if audit_middleware and service_name -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv3
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext audit apiv3
{% else -%}
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv3
keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv3
{% endif %}
[filter:request_id]
paste.filter_factory = oslo_middleware.request_id:RequestId.factory
[filter:http_proxy_to_wsgi]
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
[filter:cors]
paste.filter_factory = oslo_middleware.cors:filter_factory
oslo_config_project = cinder
[filter:faultwrap]
paste.filter_factory = cinder.api.middleware.fault:FaultWrapper.factory
[filter:osprofiler]
paste.filter_factory = osprofiler.web:WsgiMiddleware.factory
[filter:noauth]
paste.filter_factory = cinder.api.middleware.auth:NoAuthMiddleware.factory
[filter:sizelimit]
paste.filter_factory = oslo_middleware.sizelimit:RequestBodySizeLimiter.factory
[app:apiv1]
paste.app_factory = cinder.api.v1.router:APIRouter.factory
[app:apiv2]
paste.app_factory = cinder.api.v2.router:APIRouter.factory
[app:apiv3]
paste.app_factory = cinder.api.v3.router:APIRouter.factory
[pipeline:apiversions]
pipeline = cors http_proxy_to_wsgi faultwrap osvolumeversionapp
[app:osvolumeversionapp]
paste.app_factory = cinder.api.versions:Versions.factory
[pipeline:healthcheck]
pipeline = request_id healthcheckapp
[app:healthcheckapp]
paste.app_factory = oslo_middleware:Healthcheck.app_factory
backends = disable_by_file
disable_by_file_path = /etc/cinder/healthcheck_disable
##########
# Shared #
##########
[filter:keystonecontext]
paste.filter_factory = cinder.api.middleware.auth:CinderKeystoneContext.factory
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
{% include "section-filter-audit" %}

View File

@ -0,0 +1,28 @@
[DEFAULT]
# default target endpoint type
# should match the endpoint type defined in service catalog
target_endpoint_type = None
# map urls ending with specific text to a unique action
[custom_actions]
associate = update/associate
disassociate = update/disassociate
disassociate_all = update/disassociate_all
associations = read/list/associations
# possible end path of api requests
[path_keywords]
defaults = None
detail = None
limits = None
os-quota-specs = project
qos-specs = qos-spec
snapshots = snapshot
types = type
volumes = volume
# map endpoint type defined in service catalog to CADF typeURI
[service_endpoints]
volume = service/storage/block
volumev2 = service/storage/block
volumev3 = service/storage/block

View File

@ -0,0 +1,89 @@
###############################################################################
# [ WARNING ]
# cinder configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
rootwrap_config = /etc/cinder/rootwrap.conf
api_paste_confg = /etc/cinder/api-paste.ini
iscsi_helper = tgtadm
verbose = {{ verbose }}
debug = {{ debug }}
use_syslog = {{ use_syslog }}
auth_strategy = keystone
state_path = /var/lib/cinder
osapi_volume_workers = {{ workers }}
{% if transport_url %}
transport_url = {{ transport_url }}
{% endif %}
{% if use_internal_endpoints -%}
swift_catalog_info = object-store:swift:internalURL
keystone_catalog_info = identity:Identity Service:internalURL
glance_catalog_info = image:glance:internalURL
nova_catalog_info = compute:Compute Service:internalURL
{% endif %}
osapi_volume_listen = {{ bind_host }}
{% if osapi_volume_listen_port -%}
osapi_volume_listen_port = {{ osapi_volume_listen_port }}
{% endif -%}
{% if glance_api_servers -%}
glance_api_servers = {{ glance_api_servers }}
{% endif -%}
{% if glance_api_version -%}
glance_api_version = {{ glance_api_version }}
{% endif -%}
{% if region -%}
os_region_name = {{ region }}
{% endif -%}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
volume_usage_audit_period = {{ volume_usage_audit_period }}
{% if auth_host -%}
cinder_internal_tenant_project_id = {{ admin_tenant_id }}
{% if admin_user_id -%}
cinder_internal_tenant_user_id = {{ admin_user_id }}
{% else -%}
cinder_internal_tenant_user_id = {{ admin_user }}
{% endif -%}
{% endif -%}
{% include "parts/backends" %}
{% include "section-keystone-authtoken-mitaka" %}
{% if keystone_authtoken -%}
{% include "section-service-user" %}
{% endif -%}
{% include "parts/section-database" %}
{% include "section-oslo-messaging-rabbit-ocata" %}
{% include "section-oslo-notifications" %}
{% include "section-audit-middleware-notifications" %}
[oslo_concurrency]
lock_path = /var/lock/cinder
[keymgr]
# XXX: hack to work around http://pad.lv/1516085
# will be superseded by SRU to cinder package
encryption_auth_url = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v3
{% include "section-oslo-middleware" %}
[nova]
{% include "parts/service-auth" %}