Enable audit middleware
We're enabling the audit middleware for the following API services:
* cinder
* nova
* neutron
* glance
* heat
* barbican
* octavia
* gnocchi
* config.verbose was deprecated a long time ago and Gnocchi doesn't
support a separate "logging.conf" file
* as such, Gnocchi can't be configured to use "info" level logging
* the audit logs will only be emitted in debug mode
* cf001e8428/gnocchi/service.py (L72-L79)
* newly defined audit map (the other services had already existing
definitions, which were updated):
* aodh
* designate
* magnum
* masakari
* updated wsgi log configuration
The following services do not support the audit middleware,
the support for api paste was dropped:
* placement
* watcher
* keystone (has its own pycadf audit implementation)
* emits notifications using oslo.notifications
* configurable driver, possible options include "messagingv2" and "log"
* we can't just use the log driver since the user may request amqp
notifications using:
"juju config keystone enable-telemetry-notifications=True"
* we'll listen for amqp notifications using a separate service
Reference:
* audit middleware configuration: https://docs.openstack.org/keystonemiddleware/latest/audit.html
* api map samples: https://opendev.org/openstack/pycadf/src/tag/3.1.1/etc/pycadf
Change-Id: I28a261b85067704221d6ab3d949c5d2a27a4a9d7
This commit is contained in:
@@ -288,6 +288,36 @@ class AodhOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
"""Healthcheck path for ingress relation."""
|
||||
return "/healthcheck"
|
||||
|
||||
@property
|
||||
def container_configs(self) -> List[sunbeam_core.ContainerConfigFile]:
|
||||
"""Container configurations files."""
|
||||
return [
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/aodh/aodh.conf",
|
||||
"root",
|
||||
"aodh",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/aodh/api-paste.ini",
|
||||
"root",
|
||||
"aodh",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/aodh/api_audit_map.conf",
|
||||
"root",
|
||||
"aodh",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
"aodh",
|
||||
0o640,
|
||||
),
|
||||
]
|
||||
|
||||
def get_pebble_handlers(
|
||||
self,
|
||||
) -> List[sunbeam_chandlers.ServicePebbleHandler]:
|
||||
|
@@ -1,5 +1,6 @@
|
||||
[DEFAULT]
|
||||
debug = {{ options.debug }}
|
||||
api_paste_confg = /etc/aodh/api-paste.ini
|
||||
|
||||
{% if amqp.transport_url -%}
|
||||
transport_url = {{ amqp.transport_url }}
|
||||
@@ -20,3 +21,6 @@ alarm_histories_delete_batch_size = {{ options.alarm_histories_delete_batch_size
|
||||
{% include "parts/section-service-credentials" %}
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
57
charms/aodh-k8s/src/templates/api-paste.ini.j2
Normal file
57
charms/aodh-k8s/src/templates/api-paste.ini.j2
Normal file
@@ -0,0 +1,57 @@
|
||||
[composite:aodh+noauth]
|
||||
use = egg:Paste#urlmap
|
||||
/ = aodhversions_pipeline
|
||||
/v2 = aodhv2_noauth_pipeline
|
||||
/healthcheck = healthcheck
|
||||
|
||||
[composite:aodh+keystone]
|
||||
use = egg:Paste#urlmap
|
||||
/ = aodhversions_pipeline
|
||||
/v2 = aodhv2_keystone_pipeline
|
||||
/healthcheck = healthcheck
|
||||
|
||||
[app:healthcheck]
|
||||
use = egg:oslo.middleware#healthcheck
|
||||
oslo_config_project = aodh
|
||||
|
||||
[pipeline:aodhversions_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi aodhversions
|
||||
|
||||
[app:aodhversions]
|
||||
paste.app_factory = aodh.api.app:app_factory
|
||||
root = aodh.api.controllers.root.VersionsController
|
||||
|
||||
[pipeline:aodhv2_keystone_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi request_id osprofiler authtoken audit aodhv2
|
||||
|
||||
[pipeline:aodhv2_noauth_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi request_id osprofiler aodhv2
|
||||
|
||||
[app:aodhv2]
|
||||
paste.app_factory = aodh.api.app:app_factory
|
||||
root = aodh.api.controllers.v2.root.V2Controller
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/aodh/api_audit_map.conf
|
||||
service_name = aodh
|
||||
driver = log
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
oslo_config_project = aodh
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = aodh
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
|
||||
oslo_config_project = aodh
|
||||
|
||||
[filter:osprofiler]
|
||||
paste.filter_factory = aodh.profiler:WsgiMiddleware.factory
|
||||
oslo_config_project = aodh
|
18
charms/aodh-k8s/src/templates/api_audit_map.conf.j2
Normal file
18
charms/aodh-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,18 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = alarming
|
||||
|
||||
[custom_actions]
|
||||
|
||||
[path_keywords]
|
||||
alarms = alarm
|
||||
state = alarm-state
|
||||
capabilities = capability
|
||||
quotas = quota
|
||||
metrics = metric
|
||||
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
alarming = service/alarming
|
@@ -347,6 +347,26 @@ class BarbicanOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
)
|
||||
return _cadapters
|
||||
|
||||
@property
|
||||
def container_configs(self) -> list[sunbeam_core.ContainerConfigFile]:
|
||||
"""Container configuration files for the service."""
|
||||
_cconfigs = super().container_configs
|
||||
_cconfigs.extend(
|
||||
[
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/barbican/api_audit_map.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/barbican/barbican-api-paste.ini",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
),
|
||||
]
|
||||
)
|
||||
return _cconfigs
|
||||
|
||||
def disable_barbican_config(self):
|
||||
"""Disable default barbican config."""
|
||||
container = self.unit.get_container(BARBICAN_API_CONTAINER)
|
||||
|
28
charms/barbican-k8s/src/templates/api_audit_map.conf.j2
Normal file
28
charms/barbican-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,28 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = key-manager
|
||||
|
||||
# map urls ending with specific text to a unique action
|
||||
# Don't need custom mapping for other resource operations
|
||||
# Note: action should match action names defined in CADF taxonomy
|
||||
[custom_actions]
|
||||
acl/get = read
|
||||
|
||||
# path of api requests for CADF target typeURI
|
||||
# Just need to include top resource path to identify class of resources
|
||||
[path_keywords]
|
||||
secrets=secret
|
||||
metadata=secret-metadata
|
||||
containers=container
|
||||
consumers=consumer
|
||||
orders=order
|
||||
cas=None
|
||||
quotas=quota
|
||||
project-quotas=project-quota
|
||||
secret-stores=secret-store
|
||||
acl=acl
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
key-manager = service/security/keymanager
|
72
charms/barbican-k8s/src/templates/barbican-api-paste.ini.j2
Executable file
72
charms/barbican-k8s/src/templates/barbican-api-paste.ini.j2
Executable file
@@ -0,0 +1,72 @@
|
||||
[composite:main]
|
||||
use = egg:Paste#urlmap
|
||||
/: barbican_version
|
||||
/healthcheck: healthcheck
|
||||
/v1: barbican-api-keystone-audit
|
||||
|
||||
# Use this pipeline for Barbican API - versions no authentication
|
||||
[pipeline:barbican_version]
|
||||
pipeline = cors http_proxy_to_wsgi microversion versionapp
|
||||
|
||||
# Use this pipeline for Barbican API - DEFAULT no authentication
|
||||
[pipeline:barbican_api]
|
||||
pipeline = cors http_proxy_to_wsgi unauthenticated-context microversion apiapp
|
||||
|
||||
#Use this pipeline to activate a repoze.profile middleware and HTTP port,
|
||||
# to provide profiling information for the REST API processing.
|
||||
[pipeline:barbican-profile]
|
||||
pipeline = cors http_proxy_to_wsgi unauthenticated-context microversion egg:Paste#cgitb egg:Paste#httpexceptions profile apiapp
|
||||
|
||||
#Use this pipeline for keystone auth
|
||||
[pipeline:barbican-api-keystone]
|
||||
pipeline = cors http_proxy_to_wsgi authtoken context microversion apiapp
|
||||
|
||||
#Use this pipeline for keystone auth with audit feature
|
||||
[pipeline:barbican-api-keystone-audit]
|
||||
pipeline = http_proxy_to_wsgi authtoken context microversion audit apiapp
|
||||
|
||||
[app:apiapp]
|
||||
paste.app_factory = barbican.api.app:create_main_app
|
||||
|
||||
[app:versionapp]
|
||||
paste.app_factory = barbican.api.app:create_version_app
|
||||
|
||||
[filter:simple]
|
||||
paste.filter_factory = barbican.api.middleware.simple:SimpleFilter.factory
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = barbican.api.middleware.context:UnauthenticatedContextMiddleware.factory
|
||||
|
||||
[filter:context]
|
||||
paste.filter_factory = barbican.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:microversion]
|
||||
paste.filter_factory = barbican.api.middleware.microversion:MicroversionMiddleware.factory
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/barbican/api_audit_map.conf
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
|
||||
[filter:profile]
|
||||
use = egg:repoze.profile
|
||||
log_filename = myapp.profile
|
||||
cachegrind_filename = cachegrind.out.myapp
|
||||
discard_first_request = true
|
||||
path = /__profile__
|
||||
flush_at_shutdown = true
|
||||
unwind = false
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = barbican
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware:HTTPProxyToWSGI.factory
|
||||
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
backends = disable_by_file
|
||||
disable_by_file_path = /etc/barbican/healthcheck_disable
|
@@ -2,6 +2,7 @@
|
||||
debug = {{ options.debug }}
|
||||
lock_path = /var/lock/barbican
|
||||
state_path = /var/lib/barbican
|
||||
api_paste_confg = /etc/barbican/barbican-api-paste.ini
|
||||
|
||||
host_href = ""
|
||||
transport_url = {{ amqp.transport_url }}
|
||||
@@ -39,3 +40,6 @@ ssl_ca_crt_file = {{ vault_kv.ca_crt_file }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -92,6 +92,9 @@ class CinderWSGIPebbleHandler(sunbeam_chandlers.WSGIPebbleHandler):
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/cinder/cinder.conf", "root", "cinder", 0o640
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/cinder/api_audit_map.conf", "root", "cinder", 0o640
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
|
@@ -11,8 +11,13 @@ use = call:cinder.api:root_app_factory
|
||||
[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
|
||||
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
|
||||
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
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/cinder/api_audit_map.conf
|
||||
service_name = cinder
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware.request_id:RequestId.factory
|
||||
|
55
charms/cinder-k8s/src/templates/api_audit_map.conf.j2
Normal file
55
charms/cinder-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,55 @@
|
||||
[DEFAULT]
|
||||
# Default target endpoint type,
|
||||
# should match the endpoint type defined in service catalog.
|
||||
# Possible values: cinderv3, block-storage.
|
||||
target_endpoint_type = block-storage
|
||||
|
||||
# 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
|
||||
backups/import_record = import_backup
|
||||
restore = restore
|
||||
export_record = export
|
||||
accept = accept-transfer
|
||||
cleanup = cleanup
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
defaults = None
|
||||
detail = None
|
||||
limits = None
|
||||
os-quota-specs = project
|
||||
os-quota-sets = quota-set
|
||||
os-quota-class-sets = quota-class
|
||||
qos-specs = qos-spec
|
||||
snapshots = snapshot
|
||||
types = type
|
||||
volumes = volume
|
||||
default-types = default-type
|
||||
manageable_volumes = manageable-volume
|
||||
manageable_snapshots = manageable-snapshot
|
||||
attachments = attachment
|
||||
os-availability-zone = availability-zone
|
||||
scheduler-stats = scheduler-stats
|
||||
os-volume-transfers = volume-transfer
|
||||
volume-transfers = volume-transfer
|
||||
backups = backup
|
||||
encryption = volume-encryption
|
||||
os-services = service
|
||||
consistencygroups = consistency-group
|
||||
clusters = cluster
|
||||
groups = group
|
||||
group_snapshots = group_snapshot
|
||||
group_specs = group_specs
|
||||
messages = message
|
||||
os-hosts = host
|
||||
resource_filters = resource_filter
|
||||
workers = worker
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
volume = service/storage/block
|
||||
volumev2 = service/storage/block
|
@@ -20,3 +20,6 @@ auth_strategy = keystone
|
||||
lock_path = /var/lib/cinder/tmp
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -153,6 +153,16 @@ class DesignatePebbleHandler(sunbeam_chandlers.WSGIPebbleHandler):
|
||||
"designate",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/designate/api_audit_map.conf",
|
||||
"designate",
|
||||
"designate",
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/designate/api-paste.ini",
|
||||
"designate",
|
||||
"designate",
|
||||
),
|
||||
]
|
||||
)
|
||||
return _cconfig
|
||||
|
77
charms/designate-k8s/src/templates/api-paste.ini
Normal file
77
charms/designate-k8s/src/templates/api-paste.ini
Normal file
@@ -0,0 +1,77 @@
|
||||
[composite:osapi_dns]
|
||||
use = egg:Paste#urlmap
|
||||
/: osapi_dns_versions
|
||||
/healthcheck: healthcheck
|
||||
/v2: osapi_dns_v2
|
||||
/admin: osapi_dns_admin
|
||||
|
||||
[composite:osapi_dns_versions]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = http_proxy_to_wsgi cors maintenance faultwrapper osprofiler osapi_dns_app_versions
|
||||
keystone = http_proxy_to_wsgi cors maintenance faultwrapper osprofiler osapi_dns_app_versions
|
||||
|
||||
[app:osapi_dns_app_versions]
|
||||
paste.app_factory = designate.api.versions:factory
|
||||
|
||||
[composite:osapi_dns_v2]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = http_proxy_to_wsgi cors request_id faultwrapper validation_API_v2 sizelimit osprofiler noauthcontext maintenance normalizeuri osapi_dns_app_v2
|
||||
keystone = http_proxy_to_wsgi cors request_id faultwrapper validation_API_v2 sizelimit osprofiler authtoken keystonecontext maintenance normalizeuri audit osapi_dns_app_v2
|
||||
|
||||
[app:osapi_dns_app_v2]
|
||||
paste.app_factory = designate.api.v2:factory
|
||||
|
||||
[composite:osapi_dns_admin]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = http_proxy_to_wsgi cors request_id faultwrapper sizelimit osprofiler noauthcontext maintenance normalizeuri osapi_dns_app_admin
|
||||
keystone = http_proxy_to_wsgi cors request_id faultwrapper sizelimit osprofiler authtoken keystonecontext maintenance normalizeuri audit osapi_dns_app_admin
|
||||
|
||||
[app:osapi_dns_app_admin]
|
||||
paste.app_factory = designate.api.admin:factory
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/designate/api_audit_map.conf
|
||||
service_name = designate
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = designate
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware:HTTPProxyToWSGI.factory
|
||||
|
||||
[filter:osprofiler]
|
||||
paste.filter_factory = designate.common.profiler:WsgiMiddleware.factory
|
||||
|
||||
[filter:sizelimit]
|
||||
paste.filter_factory = oslo_middleware:RequestBodySizeLimiter.factory
|
||||
|
||||
[filter:noauthcontext]
|
||||
paste.filter_factory = designate.api.middleware:NoAuthContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
|
||||
[filter:keystonecontext]
|
||||
paste.filter_factory = designate.api.middleware:KeystoneContextMiddleware.factory
|
||||
|
||||
[filter:maintenance]
|
||||
paste.filter_factory = designate.api.middleware:MaintenanceMiddleware.factory
|
||||
|
||||
[filter:normalizeuri]
|
||||
paste.filter_factory = designate.api.middleware:NormalizeURIMiddleware.factory
|
||||
|
||||
[filter:faultwrapper]
|
||||
paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory
|
||||
|
||||
[filter:validation_API_v2]
|
||||
paste.filter_factory = designate.api.middleware:APIv2ValidationErrorMiddleware.factory
|
||||
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
backends = disable_by_file
|
||||
disable_by_file_path = /etc/designate/healthcheck_disable
|
39
charms/designate-k8s/src/templates/api_audit_map.conf.j2
Normal file
39
charms/designate-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,39 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = dns
|
||||
|
||||
[custom_actions]
|
||||
export = export
|
||||
abandon = abandon
|
||||
xfr = xfr
|
||||
pool_move = pool_move
|
||||
|
||||
[path_keywords]
|
||||
zones = zone
|
||||
tasks = task
|
||||
imports = import
|
||||
exports = export
|
||||
nameservers = nameserver
|
||||
shares = share
|
||||
transfer_requests = transfer_request
|
||||
transfer_accepts = transfer_accept
|
||||
recordsets = recordset
|
||||
pools = pool
|
||||
limits = limit
|
||||
tlds = tld
|
||||
tsigkeys = tsigkey
|
||||
blacklists = blacklist
|
||||
quotas = quota
|
||||
service_statuses = service_status
|
||||
floatingips = floatingip
|
||||
|
||||
export = None
|
||||
abandon = None
|
||||
xfr = None
|
||||
pool_move = None
|
||||
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
dns = service/dns
|
@@ -2,6 +2,7 @@
|
||||
debug = {{ options.debug }}
|
||||
lock_path = /var/lock/designate
|
||||
state_path = /var/lib/designate
|
||||
api_paste_confg = /etc/designate/api-paste.ini
|
||||
|
||||
transport_url = {{ amqp.transport_url }}
|
||||
|
||||
@@ -24,3 +25,6 @@ enabled = True
|
||||
{% include "parts/database-connection-settings" %}
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -342,6 +342,18 @@ class GlanceOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/glance/api_audit_map.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/glance/glance-api-paste.ini",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
self.service_user,
|
||||
|
29
charms/glance-k8s/src/templates/api_audit_map.conf.j2
Normal file
29
charms/glance-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,29 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = image
|
||||
|
||||
[custom_actions]
|
||||
deactivate = deactivate
|
||||
reactivate = reactivate
|
||||
stage = stage
|
||||
import = import
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
detail = None
|
||||
file = None
|
||||
images = image
|
||||
members = member
|
||||
tags = tag
|
||||
tasks = task
|
||||
locations = location
|
||||
schemas = schema
|
||||
stores = store
|
||||
info = info
|
||||
cache = cache
|
||||
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
image = service/storage/image
|
98
charms/glance-k8s/src/templates/glance-api-paste.ini.j2
Normal file
98
charms/glance-k8s/src/templates/glance-api-paste.ini.j2
Normal file
@@ -0,0 +1,98 @@
|
||||
# Use this composite for no auth or image caching - DEFAULT
|
||||
[composite:glance-api]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
# Use this composite for image caching and no auth
|
||||
[composite:glance-api-caching]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
# Use this composite for caching w/ management interface but no auth
|
||||
[composite:glance-api-cachemanagement]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
# Use this composite for keystone auth
|
||||
[composite:glance-api-keystone]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
# Use this composite for keystone auth with image caching
|
||||
[composite:glance-api-keystone+caching]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
# Use this composite for keystone auth with caching and cache management
|
||||
[composite:glance-api-keystone+cachemanagement]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: api
|
||||
/healthcheck: healthcheck
|
||||
|
||||
[composite:api]
|
||||
paste.composite_factory = glance.api:pipeline_factory
|
||||
default = cors http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context rootapp
|
||||
caching = cors http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache rootapp
|
||||
cachemanagement = cors http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache cachemanage rootapp
|
||||
keystone = cors http_proxy_to_wsgi versionnegotiation osprofiler authtoken context audit rootapp
|
||||
keystone+caching = cors http_proxy_to_wsgi versionnegotiation osprofiler authtoken context audit cache rootapp
|
||||
keystone+cachemanagement = cors http_proxy_to_wsgi versionnegotiation osprofiler authtoken context audit cache cachemanage rootapp
|
||||
|
||||
[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
|
||||
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
backends = disable_by_file
|
||||
disable_by_file_path = /etc/glance/healthcheck_disable
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/glance/api_audit_map.conf
|
||||
service_name = glance
|
||||
|
||||
[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
|
@@ -49,3 +49,6 @@ rbd_store_ceph_conf = /etc/ceph/ceph.conf
|
||||
flavor = keystone
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -111,6 +111,12 @@ class GnocchiWSGIPebbleHandler(sunbeam_chandlers.WSGIPebbleHandler):
|
||||
self.charm.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/gnocchi/api_audit_map.conf",
|
||||
self.charm.service_user,
|
||||
self.charm.service_group,
|
||||
0o640,
|
||||
),
|
||||
]
|
||||
)
|
||||
_cconfigs.extend(self.charm.default_container_configs())
|
||||
|
@@ -34,8 +34,14 @@ use = egg:Paste#urlmap
|
||||
[pipeline:gnocchiv1+noauth]
|
||||
pipeline = http_proxy_to_wsgi gnocchiv1
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/gnocchi/api_audit_map.conf
|
||||
service_name = gnocchi
|
||||
driver = log
|
||||
|
||||
[pipeline:gnocchiv1+keystone]
|
||||
pipeline = http_proxy_to_wsgi keystone_authtoken gnocchiv1
|
||||
pipeline = http_proxy_to_wsgi keystone_authtoken audit gnocchiv1
|
||||
|
||||
[pipeline:gnocchiversions_pipeline]
|
||||
pipeline = http_proxy_to_wsgi gnocchiversions
|
||||
|
23
charms/gnocchi-k8s/src/templates/api_audit_map.conf.j2
Normal file
23
charms/gnocchi-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,23 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = metric
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
metric = metric_id
|
||||
measures = None
|
||||
archive_policy = archive_policy_name
|
||||
archive_policy_rule = archive_policy_rule_name
|
||||
generic = generic_id
|
||||
instance = instance_id
|
||||
history = None
|
||||
resource_type = resource_type_name
|
||||
capabilities = None
|
||||
status = None
|
||||
resource = resource
|
||||
aggregates = aggregate
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
metric=service/metric
|
@@ -1,5 +1,6 @@
|
||||
[DEFAULT]
|
||||
debug = {{ options.debug }}
|
||||
api_paste_confg = /etc/gnocchi/api-paste.ini
|
||||
|
||||
[api]
|
||||
auth_mode = keystone
|
||||
@@ -20,3 +21,6 @@ ceph_conffile = /etc/ceph/ceph.conf
|
||||
workers = 4
|
||||
|
||||
{% include "parts/section-identity" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -616,6 +616,12 @@ class HeatOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/heat/api_audit_map.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
@@ -639,6 +645,12 @@ class HeatOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/heat/api_audit_map_cfn.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
|
@@ -70,14 +70,14 @@ paste.composite_factory = heat.api:root_app_factory
|
||||
|
||||
[composite:api]
|
||||
paste.composite_factory = heat.api:pipeline_factory
|
||||
default = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authtoken context osprofiler apiv1app
|
||||
default = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authtoken context osprofiler audit apiv1app
|
||||
standalone = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authpassword context apiv1app
|
||||
custombackend = cors request_id context faultwrap versionnegotiation custombackendauth apiv1app
|
||||
noauth = cors request_id faultwrap noauth context http_proxy_to_wsgi versionnegotiation apiv1app
|
||||
|
||||
[composite:api-cfn]
|
||||
paste.composite_factory = heat.api:pipeline_factory
|
||||
default = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken authtoken context osprofiler apicfnv1app
|
||||
default = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken authtoken context osprofiler audit apicfnv1app
|
||||
standalone = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken context apicfnv1app
|
||||
|
||||
[app:apiv1app]
|
||||
@@ -91,6 +91,11 @@ heat.app_factory = heat.api.cfn.v1:API
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/heat/api_audit_map_cfn.conf
|
||||
service_name = heat
|
||||
|
||||
[filter:versionnegotiation]
|
||||
paste.filter_factory = heat.common.wsgi:filter_factory
|
||||
heat.filter_factory = heat.api.openstack:version_negotiation_filter
|
||||
|
@@ -70,14 +70,14 @@ paste.composite_factory = heat.api:root_app_factory
|
||||
|
||||
[composite:api]
|
||||
paste.composite_factory = heat.api:pipeline_factory
|
||||
default = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authtoken context osprofiler apiv1app
|
||||
default = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authtoken context osprofiler audit apiv1app
|
||||
standalone = cors request_id faultwrap http_proxy_to_wsgi versionnegotiation authurl authpassword context apiv1app
|
||||
custombackend = cors request_id context faultwrap versionnegotiation custombackendauth apiv1app
|
||||
noauth = cors request_id faultwrap noauth context http_proxy_to_wsgi versionnegotiation apiv1app
|
||||
|
||||
[composite:api-cfn]
|
||||
paste.composite_factory = heat.api:pipeline_factory
|
||||
default = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken authtoken context osprofiler apicfnv1app
|
||||
default = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken authtoken context osprofiler audit apicfnv1app
|
||||
standalone = cors request_id http_proxy_to_wsgi cfnversionnegotiation ec2authtoken context apicfnv1app
|
||||
|
||||
[app:apiv1app]
|
||||
@@ -91,6 +91,11 @@ heat.app_factory = heat.api.cfn.v1:API
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/heat/api_audit_map.conf
|
||||
service_name = heat
|
||||
|
||||
[filter:versionnegotiation]
|
||||
paste.filter_factory = heat.common.wsgi:filter_factory
|
||||
heat.filter_factory = heat.api.openstack:version_negotiation_filter
|
||||
|
39
charms/heat-k8s/src/templates/api_audit_map.conf.j2
Normal file
39
charms/heat-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,39 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = orchestration
|
||||
|
||||
[custom_actions]
|
||||
abandon = abandon
|
||||
export = export
|
||||
signal = signal
|
||||
validate = validate
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
abandon = None
|
||||
export = None
|
||||
signal = None
|
||||
validate = None
|
||||
stacks = stack
|
||||
resources = resource
|
||||
preview = None
|
||||
detail = None
|
||||
snapshots = snapshot
|
||||
restore = None
|
||||
outputs = output
|
||||
metadata = server
|
||||
events = event
|
||||
template = None
|
||||
template_versions = template_version
|
||||
functions = None
|
||||
resource_types = resource_type
|
||||
build_info = None
|
||||
actions = None
|
||||
software_configs = software_config
|
||||
software_deployments = software_deployment
|
||||
services = None
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
orchestration = service/orchestration
|
32
charms/heat-k8s/src/templates/api_audit_map_cfn.conf.j2
Normal file
32
charms/heat-k8s/src/templates/api_audit_map_cfn.conf.j2
Normal file
@@ -0,0 +1,32 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = cloudformation
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
stacks = stack
|
||||
resources = resource
|
||||
preview = None
|
||||
detail = None
|
||||
abandon = None
|
||||
snapshots = snapshot
|
||||
restore = None
|
||||
outputs = output
|
||||
metadata = server
|
||||
signal = None
|
||||
events = event
|
||||
template = None
|
||||
template_versions = template_version
|
||||
functions = None
|
||||
validate = None
|
||||
resource_types = resource_type
|
||||
build_info = None
|
||||
actions = None
|
||||
software_configs = software_config
|
||||
software_deployments = software_deployment
|
||||
services = None
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
orchestration = service/orchestration
|
@@ -32,3 +32,5 @@ workers = 4
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -33,3 +33,5 @@ workers = 4
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -274,6 +274,36 @@ class IdentityResourceProvidesHandler(sunbeam_rhandlers.RelationHandler):
|
||||
class WSGIKeystonePebbleHandler(sunbeam_chandlers.WSGIPebbleHandler):
|
||||
"""Keystone Pebble Handler."""
|
||||
|
||||
def get_layer(self) -> dict:
|
||||
"""Keystone WSGI service layer.
|
||||
|
||||
:returns: pebble layer configuration
|
||||
:rtype: dict
|
||||
"""
|
||||
layer = super().get_layer()
|
||||
# Append the audit monitor service, which will receive audit
|
||||
# messages over AMQP and log them.
|
||||
layer["services"]["keystone-audit-monitor"] = {
|
||||
"override": "replace",
|
||||
"summary": "keystone audit monitor",
|
||||
"command": "/usr/bin/python3 /usr/bin/keystone_audit_monitor.py",
|
||||
"user": "keystone",
|
||||
"group": "keystone",
|
||||
}
|
||||
return layer
|
||||
|
||||
def default_container_configs(
|
||||
self,
|
||||
) -> list[sunbeam_core.ContainerConfigFile]:
|
||||
"""Container configs for WSGI service."""
|
||||
configs = super().default_container_configs()
|
||||
configs += [
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/bin/keystone_audit_monitor.py", "root", "keystone", 0o750
|
||||
),
|
||||
]
|
||||
return configs
|
||||
|
||||
def init_service(self, context: sunbeam_core.OPSCharmContexts) -> None:
|
||||
"""Enable and start WSGI service."""
|
||||
container = self.charm.unit.get_container(self.container_name)
|
||||
@@ -860,7 +890,7 @@ export OS_AUTH_VERSION=3
|
||||
self.template_dir,
|
||||
self.configure_charm,
|
||||
f"wsgi-{self.service_name}",
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
def get_relation_handlers(
|
||||
|
@@ -0,0 +1,65 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
import sys
|
||||
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg # noqa
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger("keystone_audit_monitor")
|
||||
CONF = cfg.CONF
|
||||
|
||||
NOTIFICATION_TOPIC = "notifications"
|
||||
NOTIFICATION_EXCHANGE = "keystone"
|
||||
NOTIFICATION_POOL = "keystone-charm"
|
||||
|
||||
|
||||
class NotificationEndpoint(object):
|
||||
filter_rule = oslo_messaging.NotificationFilter(
|
||||
publisher_id='^identity.*')
|
||||
|
||||
def info(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
self._log_notification(
|
||||
ctxt, "info", publisher_id, event_type, payload, metadata)
|
||||
|
||||
def _log_notification(self, ctxt, priority, publisher_id,
|
||||
event_type, payload, metadata):
|
||||
LOG.info(
|
||||
"Received %(priority)s notification, "
|
||||
"publisher: %(publisher_id)s, "
|
||||
"event: %(event_type)s, "
|
||||
"payload: %(payload)s, "
|
||||
"metadata: %(metadata)s.",
|
||||
dict(priority=priority,
|
||||
publisher_id=publisher_id,
|
||||
event_type=event_type,
|
||||
payload=payload,
|
||||
metadata=metadata))
|
||||
|
||||
|
||||
def run_monitor():
|
||||
LOG.info("Starting Keystone audit monitor")
|
||||
|
||||
transport = oslo_messaging.get_notification_transport(CONF)
|
||||
targets = [
|
||||
oslo_messaging.Target(
|
||||
topic=NOTIFICATION_TOPIC,
|
||||
exchange=NOTIFICATION_EXCHANGE),
|
||||
]
|
||||
endpoints = [NotificationEndpoint()]
|
||||
pool = NOTIFICATION_POOL
|
||||
server = oslo_messaging.get_notification_listener(transport, targets,
|
||||
endpoints, pool=pool)
|
||||
server.start()
|
||||
server.wait()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.register_options(CONF)
|
||||
|
||||
CONF(sys.argv[1:], project="keystone",
|
||||
default_config_files=["/etc/keystone/keystone.conf"])
|
||||
|
||||
logging.setup(CONF, "keystone_audit_monitor")
|
||||
|
||||
run_monitor()
|
@@ -1,17 +1,17 @@
|
||||
[loggers]
|
||||
keys=root
|
||||
keys=root,keystone_audit_monitor
|
||||
|
||||
[formatters]
|
||||
keys=normal,normal_with_name,debug,context
|
||||
|
||||
[handlers]
|
||||
keys=production,devel
|
||||
keys=production,devel,keystone_audit_monitor
|
||||
|
||||
[logger_root]
|
||||
{% if ks_logging.root_level -%}
|
||||
level={{ ks_logging.root_level }}
|
||||
{% else -%}
|
||||
level=WARNING
|
||||
level=INFO
|
||||
{% endif -%}
|
||||
handlers=production
|
||||
|
||||
@@ -20,11 +20,22 @@ class=StreamHandler
|
||||
{% if ks_logging.log_level -%}
|
||||
level={{ ks_logging.log_level }}
|
||||
{% else -%}
|
||||
level=ERROR
|
||||
level=INFO
|
||||
{% endif -%}
|
||||
formatter=context
|
||||
args=(sys.stdout,)
|
||||
|
||||
[logger_keystone_audit_monitor]
|
||||
level=INFO
|
||||
handlers=keystone_audit_monitor
|
||||
qualname=keystone_audit_monitor
|
||||
|
||||
[handler_keystone_audit_monitor]
|
||||
class=StreamHandler
|
||||
level=INFO
|
||||
formatter=context
|
||||
args=(sys.stdout,)
|
||||
|
||||
[handler_file]
|
||||
class=FileHandler
|
||||
level=DEBUG
|
||||
|
@@ -227,6 +227,11 @@ class MagnumOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
"magnum",
|
||||
"magnum",
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/magnum/api_audit_map.conf",
|
||||
"magnum",
|
||||
"magnum",
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/magnum/keystone_auth_default_policy.json",
|
||||
"magnum",
|
||||
|
@@ -7,11 +7,16 @@ paste.composite_factory = magnum.api:root_app_factory
|
||||
{% endif %}
|
||||
|
||||
[pipeline:api]
|
||||
pipeline = cors http_proxy_to_wsgi request_id osprofiler authtoken api_v1
|
||||
pipeline = cors http_proxy_to_wsgi request_id osprofiler authtoken audit api_v1
|
||||
|
||||
[app:api_v1]
|
||||
paste.app_factory = magnum.api.app:app_factory
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/magnum/api_audit_map.conf
|
||||
service_name = magnum
|
||||
|
||||
[filter:authtoken]
|
||||
acl_public_routes = /, /v1
|
||||
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||
|
21
charms/magnum-k8s/src/templates/api_audit_map.conf.j2
Normal file
21
charms/magnum-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,21 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = container-infra
|
||||
|
||||
[custom_actions]
|
||||
resize = resize
|
||||
upgrade = upgrade
|
||||
|
||||
[path_keywords]
|
||||
clusters = cluster
|
||||
clustertemplates = clustertemplate
|
||||
certificates = certificate
|
||||
mservices = mservice
|
||||
stats = stats
|
||||
quotas = quota
|
||||
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
alarming = service/container-infra
|
@@ -64,3 +64,6 @@ region_name = {{ options.region }}
|
||||
{% if receive_ca_cert and receive_ca_cert.ca_bundle -%}
|
||||
ca_file = /usr/local/share/ca-certificates/ca-bundle.pem
|
||||
{% endif -%}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -297,6 +297,18 @@ class MasakariOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
group=self.service_group,
|
||||
permissions=0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/masakari/api_audit_map.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
permissions=0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/masakari/api-paste.ini",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
permissions=0o640,
|
||||
),
|
||||
]
|
||||
)
|
||||
return _cconfigs
|
||||
|
51
charms/masakari-k8s/src/templates/api-paste.ini.j2
Normal file
51
charms/masakari-k8s/src/templates/api-paste.ini.j2
Normal file
@@ -0,0 +1,51 @@
|
||||
[composite:masakari_api]
|
||||
use = call:masakari.api.urlmap:urlmap_factory
|
||||
/: apiversions
|
||||
/v1: masakari_api_v1
|
||||
|
||||
|
||||
[composite:masakari_api_v1]
|
||||
use = call:masakari.api.auth:pipeline_factory_v1
|
||||
keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit authtoken keystonecontext audit osapi_masakari_app_v1
|
||||
noauth2 = cors http_proxy_to_wsgi request_id faultwrap sizelimit noauth2 osapi_masakari_app_v1
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/masakari/api_audit_map.conf
|
||||
service_name = masakari
|
||||
|
||||
# filters
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = masakari
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:faultwrap]
|
||||
paste.filter_factory = masakari.api.openstack:FaultWrapper.factory
|
||||
|
||||
[filter:sizelimit]
|
||||
paste.filter_factory = oslo_middleware:RequestBodySizeLimiter.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
|
||||
[filter:keystonecontext]
|
||||
paste.filter_factory = masakari.api.auth:MasakariKeystoneContext.factory
|
||||
|
||||
[filter:noauth2]
|
||||
paste.filter_factory = masakari.api.auth:NoAuthMiddleware.factory
|
||||
|
||||
# apps
|
||||
[app:osapi_masakari_app_v1]
|
||||
paste.app_factory = masakari.api.openstack.ha:APIRouterV1.factory
|
||||
|
||||
[pipeline:apiversions]
|
||||
pipeline = faultwrap http_proxy_to_wsgi apiversionsapp
|
||||
|
||||
[app:apiversionsapp]
|
||||
paste.app_factory = masakari.api.openstack.ha.versions:Versions.factory
|
16
charms/masakari-k8s/src/templates/api_audit_map.conf.j2
Normal file
16
charms/masakari-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,16 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = instance-ha
|
||||
|
||||
[custom_actions]
|
||||
|
||||
[path_keywords]
|
||||
segments = segment
|
||||
hosts = host
|
||||
notifications = notification
|
||||
vmoves = vmove
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
alarming = service/instance-ha
|
@@ -3,6 +3,8 @@
|
||||
debug = {{ options.debug }}
|
||||
auth_strategy = keystone
|
||||
|
||||
api_paste_confg = /etc/masakari/api-paste.ini
|
||||
|
||||
{% if amqp.transport_url -%}
|
||||
transport_url = {{ amqp.transport_url }}
|
||||
{% endif -%}
|
||||
@@ -40,3 +42,6 @@ wait_period_after_service_update = {{ options.evacuation_delay }}
|
||||
|
||||
[host_failure]
|
||||
evacuate_all_instances = {{ options.evacuate_all_instances }}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -16,8 +16,8 @@ Listen {{ wsgi_config.public_port }}
|
||||
ErrorLogFormat "%{cu}t %M"
|
||||
</IfVersion>
|
||||
|
||||
ErrorLog /var/log/apache2/masakari_error.log
|
||||
CustomLog /var/log/apache2/masakari_access.log combined
|
||||
ErrorLog {{ wsgi_config.error_log }}
|
||||
CustomLog {{ wsgi_config.custom_log }} combined
|
||||
|
||||
<Directory /usr/bin>
|
||||
<IfVersion >= 2.4>
|
||||
|
@@ -142,6 +142,9 @@ class NeutronServerPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/neutron/api-paste.ini", "neutron", "neutron"
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/neutron/api_audit_map.conf", "root", "neutron"
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
@@ -394,6 +397,9 @@ class NeutronServerOVNPebbleHandler(NeutronServerPebbleHandler):
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/neutron/api-paste.ini", "root", "neutron", 0o640
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/neutron/api_audit_map.conf", "root", "neutron", 0o640
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
|
@@ -11,13 +11,18 @@ use = egg:Paste#urlmap
|
||||
[composite:neutronapi_v2_0]
|
||||
use = call:neutron.auth:pipeline_factory
|
||||
noauth = cors http_proxy_to_wsgi request_id fake_project_id catch_errors osprofiler extensions neutronapiapp_v2_0
|
||||
keystone = cors http_proxy_to_wsgi request_id catch_errors osprofiler authtoken keystonecontext extensions neutronapiapp_v2_0
|
||||
keystone = cors http_proxy_to_wsgi request_id catch_errors osprofiler authtoken audit keystonecontext extensions neutronapiapp_v2_0
|
||||
|
||||
[composite:neutronversions_composite]
|
||||
use = call:neutron.auth:pipeline_factory
|
||||
noauth = cors http_proxy_to_wsgi neutronversions
|
||||
keystone = cors http_proxy_to_wsgi neutronversions
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/neutron/api_audit_map.conf
|
||||
service_name = neutron
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
|
108
charms/neutron-k8s/src/templates/api_audit_map.conf.j2
Normal file
108
charms/neutron-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,108 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = network
|
||||
|
||||
[custom_actions]
|
||||
add_router_interface = update/add
|
||||
remove_router_interface = update/remove
|
||||
add_allowed_address_pairs = update/add
|
||||
remove_allowed_address_pairs = update/remove
|
||||
activate = activate
|
||||
add_subports = update/add
|
||||
remove_subports = update/remove
|
||||
get_subports = get/list
|
||||
add_extraroutes = update/add
|
||||
remove_extraroutes = update/remove
|
||||
add_external_gateways = update/add
|
||||
update_external_gateways = update
|
||||
remove_external_gateways = update/remove
|
||||
add_prefixes = update/add
|
||||
remove_prefixes = update/remove
|
||||
add_addresses = update/add
|
||||
remove_addresses = update/remove
|
||||
insert_rule = update/add
|
||||
remove_rule = update/remove
|
||||
add_bgp_peer = update/add
|
||||
remove_bgp_peer = update/remove
|
||||
add_gateway_network = update/add
|
||||
remove_gateway_network = update/remove
|
||||
get_advertised_routes = get/list
|
||||
bgp-dragents = get/list
|
||||
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
floatingips = ip
|
||||
healthmonitors = healthmonitor
|
||||
health_monitors = health_monitor
|
||||
lb = None
|
||||
members = member
|
||||
metering-labels = label
|
||||
metering-label-rules = rule
|
||||
networks = network
|
||||
pools = pool
|
||||
ports = port
|
||||
routers = router
|
||||
quotas = quota
|
||||
security-groups = security-group
|
||||
security-group-rules = rule
|
||||
subnets = subnet
|
||||
vips = vip
|
||||
extensions = extension
|
||||
network_segment_ranges = network-segment-range
|
||||
bindings = binding
|
||||
segments = segment
|
||||
trunks = trunk
|
||||
address-scopes = address-scope
|
||||
conntrack_helpers = conntrack_helper
|
||||
port_forwardings = port-forwarding
|
||||
ndp_proxies = ndp_proxy
|
||||
subnetpools = subnetpool
|
||||
local_ips = local_ip
|
||||
port_associations = port-association
|
||||
address-groups = address-group
|
||||
firewall_groups = firewall-groups
|
||||
firewall_policies = firewall-policy
|
||||
firewall_rules = firewall-rule
|
||||
rbac-policies = rbac-policy
|
||||
default-security-group-rules = default-security-group-rule
|
||||
ikepolicies = ikepolicy
|
||||
ipsecpolicies = ipsecpolicy
|
||||
ipsec-site-connections = ipsec-site-connection
|
||||
endpoint-groups = endpoint-group
|
||||
vpnservices = vpnservice
|
||||
flavors = flavor
|
||||
service_profiles = service-profile
|
||||
network-ip-availabilities = network-ip-availability
|
||||
service-providers = service-provider
|
||||
tags = tag
|
||||
qos/rule-types = qos/rule-type
|
||||
qos/policies = qos/policy
|
||||
bandwidth_limit_rules = bandwidth_limit_rule
|
||||
dscp_marking_rules = dscp_marking_rule
|
||||
minimum_bandwidth_rules = minimum_bandwidth_rule
|
||||
minimum_packet_rate_rules = minimum_packet_rate_rule
|
||||
packet_rate_limit_rules = packet_rate_limit_rule
|
||||
alias_bandwidth_limit_rules = alias_bandwidth_limit_rule
|
||||
alias_minimum_packet_rate_rules = alias_minimum_packet_rate_rule
|
||||
logging_resources = logging_resource
|
||||
firewall_logs = firewall_log
|
||||
bgpvpns = bgpvpn
|
||||
network_associations = network_association
|
||||
router_associations = router_association
|
||||
bgp-speakers = bgp-speaker
|
||||
dhcp-agents = dhcp-agent
|
||||
auto-allocated-topology = auto-allocated-topology
|
||||
tap_services = tap-service
|
||||
tap_flows = tap-flow
|
||||
tap_mirrors = tap-mirror
|
||||
port_chains = port-chain
|
||||
port_pair_groups = port-pair-group
|
||||
port_pairs = port-pairs
|
||||
flow_classifiers = flow-classifier
|
||||
service_graphs = service-graph
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
network = service/network
|
@@ -92,3 +92,6 @@ ipv6_ptr_zone_prefix_size = {{ options.ipv6_ptr_zone_prefix_size }}
|
||||
cafile = /usr/local/share/ca-certificates/ca-bundle.pem
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -566,6 +566,18 @@ class NovaOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
"nova",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/nova/api_audit_map.conf",
|
||||
"root",
|
||||
"nova",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/nova/api-paste.ini",
|
||||
"root",
|
||||
"nova",
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
|
95
charms/nova-k8s/src/templates/api-paste.ini.j2
Normal file
95
charms/nova-k8s/src/templates/api-paste.ini.j2
Normal file
@@ -0,0 +1,95 @@
|
||||
############
|
||||
# Metadata #
|
||||
############
|
||||
[composite:metadata]
|
||||
use = egg:Paste#urlmap
|
||||
/: meta
|
||||
|
||||
[pipeline:meta]
|
||||
pipeline = cors http_proxy_to_wsgi metaapp
|
||||
|
||||
[app:metaapp]
|
||||
paste.app_factory = nova.api.metadata.handler:MetadataRequestHandler.factory
|
||||
|
||||
#############
|
||||
# OpenStack #
|
||||
#############
|
||||
|
||||
[composite:osapi_compute]
|
||||
use = call:nova.api.openstack.urlmap:urlmap_factory
|
||||
/: oscomputeversions
|
||||
/v2: oscomputeversion_legacy_v2
|
||||
/v2.1: oscomputeversion_v2
|
||||
# v21 is an exactly feature match for v2, except it has more stringent
|
||||
# input validation on the wsgi surface (prevents fuzzing early on the
|
||||
# API). It also provides new features via API microversions which are
|
||||
# opt into for clients. Unaware clients will receive the same frozen
|
||||
# v2 API feature set, but with some relaxed validation
|
||||
/v2/+: openstack_compute_api_v21_legacy_v2_compatible
|
||||
/v2.1/+: openstack_compute_api_v21
|
||||
|
||||
[composite:openstack_compute_api_v21]
|
||||
use = call:nova.api.auth:pipeline_factory_v21
|
||||
keystone = cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler authtoken keystonecontext audit osapi_compute_app_v21
|
||||
|
||||
[composite:openstack_compute_api_v21_legacy_v2_compatible]
|
||||
use = call:nova.api.auth:pipeline_factory_v21
|
||||
keystone = cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler authtoken keystonecontext audit legacy_v2_compatible osapi_compute_app_v21
|
||||
|
||||
[filter:audit]
|
||||
paste.filter_factory = keystonemiddleware.audit:filter_factory
|
||||
audit_map_file = /etc/nova/api_audit_map.conf
|
||||
service_name = nova
|
||||
|
||||
[filter:request_log]
|
||||
paste.filter_factory = nova.api.openstack.requestlog:RequestLog.factory
|
||||
|
||||
[filter:compute_req_id]
|
||||
paste.filter_factory = nova.api.compute_req_id:ComputeReqIdMiddleware.factory
|
||||
|
||||
[filter:faultwrap]
|
||||
paste.filter_factory = nova.api.openstack:FaultWrapper.factory
|
||||
|
||||
[filter:osprofiler]
|
||||
paste.filter_factory = nova.profiler:WsgiMiddleware.factory
|
||||
|
||||
[filter:sizelimit]
|
||||
paste.filter_factory = oslo_middleware:RequestBodySizeLimiter.factory
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
|
||||
|
||||
[filter:legacy_v2_compatible]
|
||||
paste.filter_factory = nova.api.openstack:LegacyV2CompatibleWrapper.factory
|
||||
|
||||
[app:osapi_compute_app_v21]
|
||||
paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory
|
||||
|
||||
[pipeline:oscomputeversions]
|
||||
pipeline = cors faultwrap request_log http_proxy_to_wsgi oscomputeversionapp
|
||||
|
||||
[pipeline:oscomputeversion_v2]
|
||||
pipeline = cors compute_req_id faultwrap request_log http_proxy_to_wsgi oscomputeversionapp_v2
|
||||
|
||||
[pipeline:oscomputeversion_legacy_v2]
|
||||
pipeline = cors compute_req_id faultwrap request_log http_proxy_to_wsgi legacy_v2_compatible oscomputeversionapp_v2
|
||||
|
||||
[app:oscomputeversionapp]
|
||||
paste.app_factory = nova.api.openstack.compute.versions:Versions.factory
|
||||
|
||||
[app:oscomputeversionapp_v2]
|
||||
paste.app_factory = nova.api.openstack.compute.versions:VersionsV2.factory
|
||||
|
||||
##########
|
||||
# Shared #
|
||||
##########
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = nova
|
||||
|
||||
[filter:keystonecontext]
|
||||
paste.filter_factory = nova.api.auth:NovaKeystoneContext.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
72
charms/nova-k8s/src/templates/api_audit_map.conf.j2
Normal file
72
charms/nova-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,72 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = compute
|
||||
|
||||
[custom_actions]
|
||||
enable = enable
|
||||
disable = disable
|
||||
delete = delete
|
||||
startup = start/startup
|
||||
shutdown = stop/shutdown
|
||||
reboot = start/reboot
|
||||
os-migrations/get = read
|
||||
os-server-password/post = update
|
||||
|
||||
# possible end path of api requests
|
||||
[path_keywords]
|
||||
add = None
|
||||
action = None
|
||||
enable = None
|
||||
disable = None
|
||||
configure-project = None
|
||||
defaults = None
|
||||
delete = None
|
||||
detail = None
|
||||
diagnostics = None
|
||||
entries = entry
|
||||
extensions = alias
|
||||
flavors = flavor
|
||||
images = image
|
||||
ips = label
|
||||
limits = None
|
||||
metadata = key
|
||||
os-agents = os-agent
|
||||
os-aggregates = os-aggregate
|
||||
os-availability-zone = None
|
||||
os-certificates = None
|
||||
os-cloudpipe = None
|
||||
os-fixed-ips = ip
|
||||
os-extra_specs = key
|
||||
os-flavor-access = None
|
||||
os-floating-ip-dns = domain
|
||||
os-floating-ips-bulk = host
|
||||
os-floating-ip-pools = None
|
||||
os-floating-ips = floating-ip
|
||||
os-hosts = host
|
||||
os-hypervisors = hypervisor
|
||||
os-instance-actions = instance-action
|
||||
os-keypairs = keypair
|
||||
os-migrations = None
|
||||
os-networks = network
|
||||
os-quota-sets = tenant
|
||||
os-security-groups = security_group
|
||||
os-security-group-rules = rule
|
||||
os-server-password = None
|
||||
os-services = None
|
||||
os-simple-tenant-usage = tenant
|
||||
os-virtual-interfaces = None
|
||||
os-volume_attachments = attachment
|
||||
os-volumes_boot = None
|
||||
os-volumes = volume
|
||||
os-volume-types = volume-type
|
||||
os-snapshots = snapshot
|
||||
reboot = None
|
||||
servers = server
|
||||
shutdown = None
|
||||
startup = None
|
||||
statistics = None
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
compute = service/compute
|
@@ -2,6 +2,7 @@
|
||||
lock_path = /var/lock/nova
|
||||
state_path = /var/lib/nova
|
||||
debug = {{ options.debug }}
|
||||
api_paste_confg = /etc/nova/api-paste.ini
|
||||
|
||||
transport_url = {{ amqp.transport_url }}
|
||||
|
||||
@@ -56,3 +57,6 @@ workers = 4
|
||||
openstack =
|
||||
|
||||
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -215,6 +215,12 @@ class OctaviaOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/etc/octavia/api_audit_map.conf",
|
||||
self.service_user,
|
||||
self.service_group,
|
||||
0o640,
|
||||
),
|
||||
sunbeam_core.ContainerConfigFile(
|
||||
"/usr/local/share/ca-certificates/ca-bundle.pem",
|
||||
"root",
|
||||
|
40
charms/octavia-k8s/src/templates/api_audit_map.conf.j2
Normal file
40
charms/octavia-k8s/src/templates/api_audit_map.conf.j2
Normal file
@@ -0,0 +1,40 @@
|
||||
[DEFAULT]
|
||||
# default target endpoint type
|
||||
# should match the endpoint type defined in service catalog
|
||||
target_endpoint_type = load-balancer
|
||||
|
||||
[custom_actions]
|
||||
failover = update/failover
|
||||
|
||||
# possible end path of API requests
|
||||
# path of api requests for CADF target typeURI
|
||||
# Just need to include top resource path to identify class
|
||||
# of resources. Ex: Log audit event for API requests
|
||||
# path containing "nodes" keyword and node uuid.
|
||||
[path_keywords]
|
||||
amphorae = amphora
|
||||
availabilityzones = availabilityzone
|
||||
availabilityzoneprofiles = availabilityzoneprofile
|
||||
config = None
|
||||
defaults = None
|
||||
failover = None
|
||||
flavors = flavor
|
||||
flavorprofiles = flavorprofile
|
||||
healthmonitors = healthmonitor
|
||||
l7policies = l7policy
|
||||
listeners = listener
|
||||
loadbalancers = loadbalancer
|
||||
members = member
|
||||
pools = pool
|
||||
providers = None
|
||||
quotas = quota
|
||||
rules = rule
|
||||
stats = None
|
||||
status = None
|
||||
|
||||
# map endpoint type defined in service catalog to CADF typeURI
|
||||
[service_endpoints]
|
||||
load-balancer = service/load-balancer
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
@@ -31,3 +31,10 @@ ovn_sb_ca_cert = {{ ovn.ovn_ca_cert }}
|
||||
{% include "parts/identity-data" %}
|
||||
|
||||
{% include "parts/section-identity" %}
|
||||
|
||||
[audit]
|
||||
enabled = True
|
||||
audit_map_file = /etc/octavia/api_audit_map.conf
|
||||
|
||||
[audit_middleware_notifications]
|
||||
driver = log
|
||||
|
@@ -390,6 +390,8 @@ relations:
|
||||
- keystone:database
|
||||
- - traefik:ingress
|
||||
- keystone:ingress-internal
|
||||
- - rabbitmq:amqp
|
||||
- keystone:amqp
|
||||
|
||||
- - mysql:database
|
||||
- glance:database
|
||||
|
@@ -11,6 +11,18 @@ configure:
|
||||
tests:
|
||||
- zaza.openstack.charm_tests.tempest.tests.TempestTestWithKeystoneMinimalNewRBAC
|
||||
- zaza.sunbeam.charm_tests.openstack_images_sync_k8s.tests.OpenStackImagesSyncK8sTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.AodhAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.BarbicanAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.CinderAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.DesignateAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.GlanceAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.HeatAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.KeystoneAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.MagnumAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.MasakariAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.NeutronAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.NovaAPIAuditTest
|
||||
- zaza.sunbeam.charm_tests.api_audit.tests.OctaviaAPIAuditTest
|
||||
tests_options:
|
||||
trust:
|
||||
- smoke
|
||||
|
@@ -145,6 +145,8 @@ relations:
|
||||
- keystone:database
|
||||
- - traefik:ingress
|
||||
- keystone:ingress-internal
|
||||
- - rabbitmq:amqp
|
||||
- keystone:amqp
|
||||
|
||||
- - mysql:database
|
||||
- glance:database
|
||||
|
@@ -126,6 +126,8 @@ relations:
|
||||
- keystone:database
|
||||
- - traefik:ingress
|
||||
- keystone:ingress-internal
|
||||
- - rabbitmq:amqp
|
||||
- keystone:amqp
|
||||
|
||||
- - mysql:database
|
||||
- cinder:database
|
||||
|
@@ -160,6 +160,8 @@ relations:
|
||||
- keystone:database
|
||||
- - traefik:ingress
|
||||
- keystone:ingress-internal
|
||||
- - rabbitmq:amqp
|
||||
- keystone:amqp
|
||||
|
||||
- - mysql:database
|
||||
- glance:database
|
||||
|
204
tests/local/zaza/sunbeam/charm_tests/api_audit/tests.py
Normal file
204
tests/local/zaza/sunbeam/charm_tests/api_audit/tests.py
Normal file
@@ -0,0 +1,204 @@
|
||||
# Copyright (c) 2024 Canonical Ltd.
|
||||
#
|
||||
# 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 random
|
||||
import subprocess
|
||||
|
||||
import barbicanclient.client as barbican_client
|
||||
import zaza.openstack.charm_tests.test_utils as test_utils
|
||||
from zaza.openstack.utilities import openstack as openstack_utils
|
||||
|
||||
|
||||
class OpenStackAPIAuditTest(test_utils.BaseCharmTest):
|
||||
"""Charm tests for API audit logging."""
|
||||
|
||||
application_name = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass(application_name=cls.application_name)
|
||||
|
||||
cls.keystone_session = openstack_utils.get_overcloud_keystone_session()
|
||||
|
||||
auth = openstack_utils.get_overcloud_auth()
|
||||
cls.keystone_client = openstack_utils.get_keystone_client(auth)
|
||||
|
||||
@classmethod
|
||||
def get_pod_logs(cls, pod_name, since="5m",
|
||||
container=None, all_containers=True):
|
||||
# We expect the k8s namespace name to match the model name.
|
||||
namespace = cls.model_name
|
||||
|
||||
cmd = ["sudo", "k8s", "kubectl", "logs", "-n", namespace,
|
||||
f"pod/{pod_name}"]
|
||||
if all_containers:
|
||||
cmd += ["--all-containers"]
|
||||
if container:
|
||||
cmd += ["--container", container]
|
||||
|
||||
result = subprocess.run(cmd, check=True, capture_output=True)
|
||||
return result.stdout.decode()
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
# Perform any API action that is expected to trigger an audit event.
|
||||
pass
|
||||
|
||||
def check_audit_logs(self, exp_msg):
|
||||
self._trigger_audit_event()
|
||||
|
||||
# For simplicity we expect there to be just one pod.
|
||||
# If needed, we can check multiple pods or aggregate the
|
||||
# logs using COS.
|
||||
pod_name = f"{self.application_name}-0"
|
||||
pod_logs = self.get_pod_logs(pod_name)
|
||||
assert exp_msg in pod_logs, (
|
||||
f"{pod_name} logs do not contain the expected message: {exp_msg}")
|
||||
|
||||
|
||||
class KeystoneAPIAuditTest(OpenStackAPIAuditTest):
|
||||
application_name = "keystone"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
# We'll update the user email to trigger an audit event.
|
||||
auth = openstack_utils.get_overcloud_auth()
|
||||
username = auth["OS_USERNAME"]
|
||||
user = self.keystone_client.users.find(name=username)
|
||||
|
||||
rand_num = random.randint(0, 32768)
|
||||
email = f"test{rand_num}.example.com"
|
||||
self.keystone_client.users.update(user.id, email=email)
|
||||
|
||||
def test_audit(self):
|
||||
# Expects the following relation: rabbitmq:amqp keystone:amqp
|
||||
default_config = {'enable-telemetry-notifications': False}
|
||||
alternate_config = {'enable-telemetry-notifications': True}
|
||||
with self.config_change(
|
||||
default_config=default_config,
|
||||
alternate_config=alternate_config,
|
||||
application_name="keystone"):
|
||||
exp_msg = (
|
||||
"keystone_audit_monitor Received info notification, "
|
||||
"publisher: identity.keystone")
|
||||
self.check_audit_logs(exp_msg)
|
||||
|
||||
|
||||
class AuditMiddlewareTest(OpenStackAPIAuditTest):
|
||||
"""Base class for services that use the audit paste middleware"""
|
||||
|
||||
def test_audit(self):
|
||||
exp_msg = "oslo.messaging.notification.audit.http.request"
|
||||
self.check_audit_logs(exp_msg)
|
||||
|
||||
|
||||
class AodhAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "aodh"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_aodh_session_client(
|
||||
self.keystone_session)
|
||||
client.alarm.list()
|
||||
|
||||
|
||||
class BarbicanAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "barbican"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
barbican_endpoint = self.keystone_client.service_catalog.url_for(
|
||||
service_type='key-manager', interface='publicURL')
|
||||
client = barbican_client.Client(session=self.keystone_session,
|
||||
endpoint=barbican_endpoint)
|
||||
client.secrets.list()
|
||||
|
||||
|
||||
class CinderAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "cinder"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_cinder_session_client(
|
||||
self.keystone_session)
|
||||
client.volumes.list()
|
||||
|
||||
|
||||
class DesignateAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "designate"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_designate_session_client(
|
||||
session=self.keystone_session)
|
||||
client.zones.list()
|
||||
|
||||
|
||||
class GlanceAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "glance"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_glance_session_client(
|
||||
self.keystone_session)
|
||||
client.images.list()
|
||||
|
||||
|
||||
class HeatAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "heat"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_heat_session_client(
|
||||
self.keystone_session)
|
||||
client.stacks.list()
|
||||
|
||||
|
||||
class MagnumAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "magnum"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_magnum_session_client(
|
||||
self.keystone_session)
|
||||
client.clusters.list()
|
||||
|
||||
|
||||
class MasakariAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "masakari"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_masakari_session_client(
|
||||
self.keystone_session)
|
||||
for segment in client.segments():
|
||||
pass
|
||||
|
||||
|
||||
class NovaAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "nova"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_nova_session_client(
|
||||
self.keystone_session)
|
||||
client.servers.list()
|
||||
|
||||
|
||||
class NeutronAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "neutron"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_neutron_session_client(
|
||||
self.keystone_session)
|
||||
client.list_networks()
|
||||
|
||||
|
||||
class OctaviaAPIAuditTest(AuditMiddlewareTest):
|
||||
application_name = "octavia"
|
||||
|
||||
def _trigger_audit_event(self):
|
||||
client = openstack_utils.get_octavia_session_client(
|
||||
self.keystone_session)
|
||||
client.amphora_list()
|
Reference in New Issue
Block a user