Merge "conf: Add '[api] response_validation' option"
This commit is contained in:
@@ -1701,6 +1701,7 @@ function configure_ironic {
|
|||||||
rm -f $IRONIC_CONF_FILE
|
rm -f $IRONIC_CONF_FILE
|
||||||
|
|
||||||
iniset $IRONIC_CONF_FILE DEFAULT debug True
|
iniset $IRONIC_CONF_FILE DEFAULT debug True
|
||||||
|
iniset $IRONIC_CONF_FILE api response_validation error
|
||||||
inicomment $IRONIC_CONF_FILE DEFAULT log_file
|
inicomment $IRONIC_CONF_FILE DEFAULT log_file
|
||||||
iniset $IRONIC_CONF_FILE database connection `database_connection_url ironic`
|
iniset $IRONIC_CONF_FILE database connection `database_connection_url ironic`
|
||||||
iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
|
iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
|
||||||
|
@@ -16,6 +16,9 @@ import functools
|
|||||||
import inspect
|
import inspect
|
||||||
import typing as ty
|
import typing as ty
|
||||||
|
|
||||||
|
import jsonschema.exceptions
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from webob import exc as webob_exc
|
from webob import exc as webob_exc
|
||||||
|
|
||||||
@@ -23,6 +26,9 @@ from ironic import api
|
|||||||
from ironic.api.validation import validators
|
from ironic.api.validation import validators
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def api_version(
|
def api_version(
|
||||||
min_version: ty.Optional[int],
|
min_version: ty.Optional[int],
|
||||||
@@ -350,6 +356,11 @@ def response_body_schema(
|
|||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
response = func(*args, **kwargs)
|
response = func(*args, **kwargs)
|
||||||
|
|
||||||
|
if CONF.api.response_validation == 'ignore':
|
||||||
|
# don't waste our time checking anything if we're ignoring
|
||||||
|
# schema errors
|
||||||
|
return response
|
||||||
|
|
||||||
# FIXME(stephenfin): How is ironic/pecan doing jsonification? The
|
# FIXME(stephenfin): How is ironic/pecan doing jsonification? The
|
||||||
# below will fail on e.g. date-time fields
|
# below will fail on e.g. date-time fields
|
||||||
|
|
||||||
@@ -362,13 +373,20 @@ def response_body_schema(
|
|||||||
else:
|
else:
|
||||||
body = jsonutils.loads(_body)
|
body = jsonutils.loads(_body)
|
||||||
|
|
||||||
_schema_validator(
|
try:
|
||||||
schema,
|
_schema_validator(
|
||||||
body,
|
schema,
|
||||||
min_version,
|
body,
|
||||||
max_version,
|
min_version,
|
||||||
is_body=True,
|
max_version,
|
||||||
)
|
is_body=True,
|
||||||
|
)
|
||||||
|
except jsonschema.exceptions.ValidationError:
|
||||||
|
if CONF.api.response_validation == 'warn':
|
||||||
|
LOG.exception('Schema failed to validate')
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
if hasattr(func, 'arguments_transformed'):
|
if hasattr(func, 'arguments_transformed'):
|
||||||
|
@@ -111,6 +111,40 @@ opts = [
|
|||||||
"the server securely."),
|
"the server securely."),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
validation_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'response_validation',
|
||||||
|
choices=(
|
||||||
|
(
|
||||||
|
'error',
|
||||||
|
'Raise a HTTP 500 (Server Error) for responses that fail '
|
||||||
|
'response body schema validation',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'warn',
|
||||||
|
'Log a warning for responses that fail response body schema '
|
||||||
|
'validation',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'ignore',
|
||||||
|
'Ignore response body schema validation failures',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
default='warn',
|
||||||
|
help=_("""\
|
||||||
|
Configure validation of API responses.
|
||||||
|
|
||||||
|
``warn`` is the current recommendation for production environments and
|
||||||
|
``error`` should only be used in testing environments.
|
||||||
|
|
||||||
|
If you find it necessary to enable the ``ignore`` option, please report the
|
||||||
|
issues you are seeing to the Nova team so we can improve our schemas.
|
||||||
|
"""),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
opt_group = cfg.OptGroup(name='api',
|
opt_group = cfg.OptGroup(name='api',
|
||||||
title='Options for the ironic-api service')
|
title='Options for the ironic-api service')
|
||||||
|
|
||||||
@@ -118,3 +152,4 @@ opt_group = cfg.OptGroup(name='api',
|
|||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
conf.register_group(opt_group)
|
conf.register_group(opt_group)
|
||||||
conf.register_opts(opts, group=opt_group)
|
conf.register_opts(opts, group=opt_group)
|
||||||
|
conf.register_opts(validation_opts, group=opt_group)
|
||||||
|
@@ -202,6 +202,7 @@ class TestCase(oslo_test_base.BaseTestCase):
|
|||||||
group='neutron')
|
group='neutron')
|
||||||
self.config(enabled_hardware_types=['fake-hardware',
|
self.config(enabled_hardware_types=['fake-hardware',
|
||||||
'manual-management'])
|
'manual-management'])
|
||||||
|
self.config(response_validation='error', group='api')
|
||||||
self.config(initial_grub_template=None, group='pxe')
|
self.config(initial_grub_template=None, group='pxe')
|
||||||
for iface in drivers_base.ALL_INTERFACES:
|
for iface in drivers_base.ALL_INTERFACES:
|
||||||
default = None
|
default = None
|
||||||
|
6
releasenotes/notes/api-validation-eface4a013c58a70.yaml
Normal file
6
releasenotes/notes/api-validation-eface4a013c58a70.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
A new configuration option, ``[api] response_validation``, has been added.
|
||||||
|
This allows operators to configure the behavior of ``ironic-api`` when a
|
||||||
|
response fails schema validation
|
Reference in New Issue
Block a user