Add keystone audit middleware API logging
This commit adds Keystone audit middleware API logging to the Glance 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 writes to /var/log/glance/glance-api.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/1212 Closes-Bug: 1856555 Change-Id: Ied08b56cf3c4fa30827d43a50ca7b552db0fa82b
This commit is contained in:
parent
75d36368f4
commit
66a167eb42
@ -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
|
||||
|
@ -121,13 +121,13 @@ SERVICES = [
|
||||
CHARM = "glance"
|
||||
|
||||
GLANCE_CONF_DIR = "/etc/glance"
|
||||
GLANCE_AUDIT_MAP = "%s/api_audit_map.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_REGISTRY_CONF = "%s/glance-registry.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_API_CONF = "%s/glance-api.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_SWIFT_CONF = "%s/glance-swift.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_REGISTRY_PASTE = os.path.join(GLANCE_CONF_DIR,
|
||||
'glance-registry-paste.ini')
|
||||
GLANCE_API_PASTE = os.path.join(GLANCE_CONF_DIR,
|
||||
'glance-api-paste.ini')
|
||||
GLANCE_API_PASTE = os.path.join(GLANCE_CONF_DIR, 'api-paste.ini')
|
||||
GLANCE_POLICY_FILE = os.path.join(GLANCE_CONF_DIR, "policy.json")
|
||||
# NOTE(ajkavanagh): from Ussuri, glance switched to policy-in-code; this is the
|
||||
# policy.yaml file (as there is not packaged policy.json or .yaml) that is used
|
||||
@ -204,6 +204,7 @@ CONFIG_FILES = OrderedDict([
|
||||
config_file=GLANCE_API_CONF),
|
||||
context.MemcacheContext(),
|
||||
glance_contexts.GlanceImageImportContext(),
|
||||
context.KeystoneAuditMiddleware(service=CHARM),
|
||||
glance_contexts.ExternalS3Context()],
|
||||
'services': ['glance-api']
|
||||
}),
|
||||
@ -218,6 +219,14 @@ CONFIG_FILES = OrderedDict([
|
||||
'hook_contexts': [],
|
||||
'services': ['glance-api', 'glance-registry']
|
||||
}),
|
||||
(GLANCE_AUDIT_MAP, {
|
||||
'hook_contexts': [context.KeystoneAuditMiddleware(service=CHARM)],
|
||||
'services': ['glance-api']
|
||||
}),
|
||||
(GLANCE_API_PASTE, {
|
||||
'hook_contexts': [context.KeystoneAuditMiddleware(service=CHARM)],
|
||||
'services': ['glance-api']
|
||||
}),
|
||||
(ceph_config_file(), {
|
||||
'hook_contexts': [context.CephContext()],
|
||||
'services': ['glance-api', 'glance-registry']
|
||||
@ -257,7 +266,9 @@ def register_configs():
|
||||
|
||||
confs = [GLANCE_REGISTRY_CONF,
|
||||
GLANCE_API_CONF,
|
||||
HAPROXY_CONF]
|
||||
HAPROXY_CONF,
|
||||
GLANCE_API_PASTE,
|
||||
GLANCE_AUDIT_MAP]
|
||||
|
||||
if relation_ids('ceph'):
|
||||
mkdir(os.path.dirname(ceph_config_file()))
|
||||
@ -403,6 +414,8 @@ def restart_map():
|
||||
cmp_release = CompareOpenStackReleases(os_release('glance-common'))
|
||||
|
||||
for f, ctxt in CONFIG_FILES.items():
|
||||
if f == GLANCE_AUDIT_MAP and cmp_release < 'yoga':
|
||||
continue
|
||||
svcs = []
|
||||
for svc in ctxt['services']:
|
||||
if cmp_release >= 'stein' and svc == 'glance-registry':
|
||||
|
86
templates/yoga/api-paste.ini
Normal file
86
templates/yoga/api-paste.ini
Normal file
@ -0,0 +1,86 @@
|
||||
# Use this pipeline for no auth or image caching - DEFAULT
|
||||
[pipeline:glance-api]
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context rootapp
|
||||
|
||||
# Use this pipeline for image caching and no auth
|
||||
[pipeline:glance-api-caching]
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache rootapp
|
||||
|
||||
# Use this pipeline for caching w/ management interface but no auth
|
||||
[pipeline:glance-api-cachemanagement]
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache cachemanage rootapp
|
||||
|
||||
# Use this pipeline for keystone auth
|
||||
[pipeline:glance-api-keystone]
|
||||
{% if audit_middleware and service_name -%}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context rootapp
|
||||
{% else %}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context rootapp
|
||||
{% endif %}
|
||||
|
||||
# Use this pipeline for keystone auth with image caching
|
||||
[pipeline:glance-api-keystone+caching]
|
||||
{% if audit_middleware and service_name -%}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context cache rootapp
|
||||
{% else %}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context cache rootapp
|
||||
{% endif %}
|
||||
|
||||
# Use this pipeline for keystone auth with caching and cache management
|
||||
[pipeline:glance-api-keystone+cachemanagement]
|
||||
{% if audit_middleware and service_name -%}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context cache cachemanage rootapp
|
||||
{% else %}
|
||||
pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context cache cachemanage rootapp
|
||||
{% endif %}
|
||||
|
||||
[composite:rootapp]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: apiversions
|
||||
/v2: apiv2app
|
||||
|
||||
[app:apiversions]
|
||||
paste.app_factory = glance.api.versions:create_resource
|
||||
|
||||
[app:apiv2app]
|
||||
paste.app_factory = glance.api.v2.router:API.factory
|
||||
|
||||
[filter:healthcheck]
|
||||
paste.filter_factory = oslo_middleware:Healthcheck.factory
|
||||
backends = disable_by_file
|
||||
disable_by_file_path = /etc/glance/healthcheck_disable
|
||||
|
||||
[filter:versionnegotiation]
|
||||
paste.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory
|
||||
|
||||
[filter:cache]
|
||||
paste.filter_factory = glance.api.middleware.cache:CacheFilter.factory
|
||||
|
||||
[filter:cachemanage]
|
||||
paste.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter.factory
|
||||
|
||||
[filter:context]
|
||||
paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
delay_auth_decision = true
|
||||
|
||||
[filter:gzip]
|
||||
paste.filter_factory = glance.api.middleware.gzip:GzipMiddleware.factory
|
||||
|
||||
[filter:osprofiler]
|
||||
paste.filter_factory = osprofiler.web:WsgiMiddleware.factory
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = glance
|
||||
oslo_config_program = glance-api
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware:HTTPProxyToWSGI.factory
|
||||
|
||||
{% include "section-filter-audit" %}
|
16
templates/yoga/api_audit_map.conf
Normal file
16
templates/yoga/api_audit_map.conf
Normal file
@ -0,0 +1,16 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = None
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
detail = None
|
||||
file = None
|
||||
images = image
|
||||
members = member
|
||||
tags = tag
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
image = service/storage/image
|
89
templates/yoga/glance-api.conf
Normal file
89
templates/yoga/glance-api.conf
Normal file
@ -0,0 +1,89 @@
|
||||
[DEFAULT]
|
||||
verbose = {{ verbose }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
debug = {{ debug }}
|
||||
workers = {{ workers }}
|
||||
bind_host = {{ bind_host }}
|
||||
|
||||
{% if ext -%}
|
||||
bind_port = {{ ext }}
|
||||
{% elif bind_port -%}
|
||||
bind_port = {{ bind_port }}
|
||||
{% else -%}
|
||||
bind_port = 9292
|
||||
{% endif -%}
|
||||
|
||||
{% if transport_url %}
|
||||
transport_url = {{ transport_url }}
|
||||
{% endif %}
|
||||
|
||||
log_file = /var/log/glance/api.log
|
||||
backlog = 4096
|
||||
|
||||
{% if expose_image_locations -%}
|
||||
show_multiple_locations = {{ expose_image_locations }}
|
||||
show_image_direct_url = {{ expose_image_locations }}
|
||||
{% endif -%}
|
||||
|
||||
{% if api_config_flags -%}
|
||||
{% for key, value in api_config_flags.items() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
delayed_delete = False
|
||||
scrub_time = 43200
|
||||
scrubber_datadir = /var/lib/glance/scrubber
|
||||
image_cache_dir = /var/lib/glance/image-cache/
|
||||
db_enforce_mysql_charset = False
|
||||
|
||||
{% if image_size_cap -%}
|
||||
image_size_cap = {{ image_size_cap }}
|
||||
{% endif -%}
|
||||
|
||||
{% if enabled_backends %}
|
||||
enabled_backends = {{ enabled_backends }}
|
||||
{% endif %}
|
||||
|
||||
[glance_store]
|
||||
{% if default_store_backend %}
|
||||
default_backend = {{ default_store_backend }}
|
||||
{% endif %}
|
||||
|
||||
[image_format]
|
||||
disk_formats = {{ disk_formats }}
|
||||
{% if container_formats -%}
|
||||
container_formats = {{ container_formats }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "section-keystone-authtoken-v3only" %}
|
||||
|
||||
{% if auth_host -%}
|
||||
[paste_deploy]
|
||||
flavor = keystone
|
||||
config_file = /etc/glance/api-paste.ini
|
||||
{% endif %}
|
||||
|
||||
[barbican]
|
||||
auth_endpoint = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v3
|
||||
|
||||
{% include "parts/section-database" %}
|
||||
|
||||
{% include "section-oslo-messaging-rabbit" %}
|
||||
|
||||
{% include "section-oslo-notifications" %}
|
||||
|
||||
{% include "section-oslo-middleware" %}
|
||||
|
||||
{% include "parts/section-storage" %}
|
||||
|
||||
{% for name, cfg in enabled_backend_configs.items() %}
|
||||
[{{name}}]
|
||||
{% for key, val in cfg.items() -%}
|
||||
{{ key }} = {{ val }}
|
||||
{% endfor -%}
|
||||
{% endfor%}
|
||||
|
||||
{% include "parts/section-image-import" %}
|
||||
|
||||
{% include "section-audit-middleware-notifications" %}
|
@ -26,6 +26,7 @@ tests:
|
||||
- zaza.openstack.charm_tests.glance.tests.GlanceCephRGWBackendTest
|
||||
- zaza.openstack.charm_tests.glance.tests.GlanceExternalS3Test
|
||||
- zaza.openstack.charm_tests.glance.tests.GlanceCinderBackendTest
|
||||
- zaza.openstack.charm_tests.audit.tests.KeystoneAuditMiddlewareTest
|
||||
- zaza.openstack.charm_tests.policyd.tests.GlanceTests
|
||||
- zaza.openstack.charm_tests.ceph.tests.CheckPoolTypes
|
||||
- zaza.openstack.charm_tests.ceph.tests.BlueStoreCompressionCharmOperation
|
||||
@ -35,6 +36,8 @@ tests:
|
||||
- zaza.openstack.charm_tests.policyd.tests.GlanceTests
|
||||
|
||||
tests_options:
|
||||
audit-middleware:
|
||||
service: glance
|
||||
tempest:
|
||||
full_run:
|
||||
smoke: true
|
||||
|
@ -159,6 +159,7 @@ class TestGlanceUtils(CharmTestCase):
|
||||
(utils.GLANCE_API_CONF, ['glance-api']),
|
||||
(utils.GLANCE_SWIFT_CONF, ['glance-api']),
|
||||
(utils.GLANCE_POLICY_FILE, ['glance-api', 'glance-registry']),
|
||||
(utils.GLANCE_API_PASTE, ['glance-api']),
|
||||
(utils.ceph_config_file(), ['glance-api', 'glance-registry']),
|
||||
(utils.HAPROXY_CONF, ['haproxy']),
|
||||
(utils.HTTPS_APACHE_CONF, ['apache2']),
|
||||
@ -181,6 +182,31 @@ class TestGlanceUtils(CharmTestCase):
|
||||
(utils.GLANCE_API_CONF, ['glance-api']),
|
||||
(utils.GLANCE_SWIFT_CONF, ['glance-api']),
|
||||
(utils.GLANCE_POLICY_FILE, ['glance-api']),
|
||||
(utils.GLANCE_API_PASTE, ['glance-api']),
|
||||
(utils.ceph_config_file(), ['glance-api']),
|
||||
(utils.HAPROXY_CONF, ['haproxy']),
|
||||
(utils.HTTPS_APACHE_CONF, ['apache2']),
|
||||
(utils.HTTPS_APACHE_24_CONF, ['apache2']),
|
||||
(utils.APACHE_PORTS_CONF, ['apache2']),
|
||||
(utils.MEMCACHED_CONF, ['memcached']),
|
||||
])
|
||||
self.assertEqual(ex_map, utils.restart_map())
|
||||
self.enable_memcache.return_value = False
|
||||
del ex_map[utils.MEMCACHED_CONF]
|
||||
self.assertEqual(ex_map, utils.restart_map())
|
||||
|
||||
def test_restart_map_yoga(self):
|
||||
self.enable_memcache.return_value = True
|
||||
self.config.side_effect = None
|
||||
self.service_name.return_value = 'glance'
|
||||
self.os_release.return_value = 'yoga'
|
||||
|
||||
ex_map = OrderedDict([
|
||||
(utils.GLANCE_API_CONF, ['glance-api']),
|
||||
(utils.GLANCE_SWIFT_CONF, ['glance-api']),
|
||||
(utils.GLANCE_POLICY_FILE, ['glance-api']),
|
||||
(utils.GLANCE_AUDIT_MAP, ['glance-api']),
|
||||
(utils.GLANCE_API_PASTE, ['glance-api']),
|
||||
(utils.ceph_config_file(), ['glance-api']),
|
||||
(utils.HAPROXY_CONF, ['haproxy']),
|
||||
(utils.HTTPS_APACHE_CONF, ['apache2']),
|
||||
@ -205,6 +231,7 @@ class TestGlanceUtils(CharmTestCase):
|
||||
(utils.GLANCE_API_CONF, ['glance-api']),
|
||||
(utils.GLANCE_SWIFT_CONF, ['glance-api']),
|
||||
(utils.GLANCE_POLICY_FILE, ['glance-api']),
|
||||
(utils.GLANCE_API_PASTE, ['glance-api']),
|
||||
(utils.ceph_config_file(), ['glance-api']),
|
||||
(utils.HAPROXY_CONF, ['haproxy']),
|
||||
(utils.HTTPS_APACHE_CONF, ['apache2']),
|
||||
|
Loading…
x
Reference in New Issue
Block a user