diff --git a/.gitreview b/.gitreview
index 56224f5de..e26745728 100644
--- a/.gitreview
+++ b/.gitreview
@@ -1,4 +1,4 @@
[gerrit]
-host=review.openstack.org
+host=review.opendev.org
port=29418
project=openstack/python-keystoneclient.git
diff --git a/.zuul.yaml b/.zuul.yaml
index 3803f2673..8b2b1a6d1 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -1,21 +1,31 @@
+- job:
+ name: keystoneclient-devstack-functional
+ parent: devstack-minimal
+ timeout: 4200
+ required-projects:
+ - openstack/keystone
+ - openstack/python-keystoneclient
+ run: playbooks/run-ds-tox.yaml
+ post-run: playbooks/tox-post.yaml
+ vars:
+ devstack_localrc:
+ USE_PYTHON3: true
+ devstack_services:
+ key: true
+ tox_envlist: functional
+ zuul_work_dir: src/opendev.org/openstack/python-keystoneclient
+
- project:
templates:
- - openstack-python-jobs
- - openstack-python35-jobs
- - openstack-python36-jobs
+ - openstack-cover-jobs
+ - openstack-python3-jobs
- publish-openstack-docs-pti
- check-requirements
- - lib-forward-testing
- lib-forward-testing-python3
- release-notes-jobs-python3
check:
jobs:
- - openstack-tox-lower-constraints
- - legacy-keystoneclient-dsvm-functional:
- voting: false
+ - keystoneclient-devstack-functional
gate:
jobs:
- - openstack-tox-lower-constraints
- post:
- jobs:
- - openstack-tox-cover
+ - keystoneclient-devstack-functional
diff --git a/README.rst b/README.rst
index d4bac5d36..6b27711a8 100644
--- a/README.rst
+++ b/README.rst
@@ -34,7 +34,7 @@ OpenStack's Identity Service. For command line interface support, use
.. _Launchpad project: https://launchpad.net/python-keystoneclient
.. _Blueprints: https://blueprints.launchpad.net/python-keystoneclient
.. _Bugs: https://bugs.launchpad.net/python-keystoneclient
-.. _Source: https://git.openstack.org/cgit/openstack/python-keystoneclient
+.. _Source: https://opendev.org/openstack/python-keystoneclient
.. _OpenStackClient: https://pypi.org/project/python-openstackclient
.. _How to Contribute: https://docs.openstack.org/infra/manual/developers.html
.. _Specs: https://specs.openstack.org/openstack/keystone-specs/
diff --git a/babel.cfg b/babel.cfg
deleted file mode 100644
index efceab818..000000000
--- a/babel.cfg
+++ /dev/null
@@ -1 +0,0 @@
-[python: **.py]
diff --git a/bindep.txt b/bindep.txt
index d17936945..fde5b372e 100644
--- a/bindep.txt
+++ b/bindep.txt
@@ -2,7 +2,8 @@
# see https://docs.openstack.org/infra/bindep/ for additional information.
gettext
-libssl-dev
+libssl-dev [platform:dpkg]
+openssl-devel [platform:rpm]
dbus-devel [platform:rpm]
dbus-glib-devel [platform:rpm]
@@ -13,11 +14,8 @@ libffi-devel [platform:rpm]
libsasl2-dev [platform:dpkg]
libxml2-dev [platform:dpkg]
libxslt1-dev [platform:dpkg]
-python-all-dev [platform:dpkg]
python3-all-dev [platform:dpkg]
cyrus-sasl-devel [platform:rpm]
libxml2-devel [platform:rpm]
-python-devel [platform:rpm]
-python3-devel [platform:fedora]
-python34-devel [platform:centos]
+python3-devel [platform:rpm]
diff --git a/doc/requirements.txt b/doc/requirements.txt
index e557e2673..6c96d9ac2 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -1,10 +1,7 @@
-# The order of packages is significant, because pip processes them in the order
-# of appearance. Changing the order has an impact on the overall integration
-# process, which may cause wedges in the gate later.
-
# These are needed for docs generation
-openstackdocstheme>=1.18.1 # Apache-2.0
-sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
-reno>=2.5.0 # Apache-2.0
-lxml!=3.7.0,>=3.4.1 # BSD
+openstackdocstheme>=2.2.1 # Apache-2.0
+sphinx>=2.0.0 # BSD
+sphinxcontrib-apidoc>=0.2.0 # BSD
+reno>=3.1.0 # Apache-2.0
+lxml>=3.4.1 # BSD
fixtures>=3.0.0 # Apache-2.0/BSD
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 56363055e..9c984584d 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -10,13 +10,9 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-from __future__ import unicode_literals
-
import os
import sys
-import pbr.version
-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..')))
@@ -31,7 +27,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc',
+extensions = ['sphinxcontrib.apidoc',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.intersphinx',
@@ -53,18 +49,8 @@
master_doc = 'index'
# General information about the project.
-project = 'python-keystoneclient'
copyright = 'OpenStack Contributors'
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-version_info = pbr.version.VersionInfo('python-keystoneclient')
-# The short X.Y version.
-version = version_info.version_string()
-# The full version, including alpha/beta/rc tags.
-release = version_info.release_string()
-
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
@@ -98,7 +84,7 @@
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['keystoneclient.']
@@ -145,10 +131,6 @@
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['static']
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%Y-%m-%d %H:%M'
-
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
@@ -183,6 +165,14 @@
# Output file base name for HTML help builder.
htmlhelp_basename = 'python-keystoneclientdoc'
+# -- sphinxcontrib.apidoc configuration --------------------------------------
+
+apidoc_module_dir = '../../keystoneclient'
+apidoc_output_dir = 'api'
+apidoc_excluded_paths = [
+ 'fixture',
+ 'tests',
+]
# -- Options for LaTeX output -------------------------------------------------
@@ -196,10 +186,9 @@
# (source start file, target name, title, author, documentclass [howto/manual])
# .
latex_documents = [
- ('index', 'python-keystoneclient.tex',
+ ('index', 'doc-python-keystoneclient.tex',
'python-keystoneclient Documentation',
- 'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss',
- 'manual'),
+ 'OpenStack', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -219,6 +208,18 @@
# If false, no module index is generated.
#latex_use_modindex = True
+# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664
+latex_use_xindy = False
+
+latex_domain_indices = False
+
+latex_elements = {
+ 'makeindex': '',
+ 'printindex': '',
+ 'preamble': r'\setcounter{tocdepth}{3}',
+ 'maxlistdepth': 10,
+}
+
keystoneauth_url = 'https://docs.openstack.org/keystoneauth/latest/'
intersphinx_mapping = {
'python': ('https://docs.python.org/', None),
@@ -227,6 +228,7 @@
}
# -- Options for openstackdocstheme -------------------------------------------
-repository_name = 'openstack/python-keystoneclient'
-bug_project = 'python-keystoneclient'
-bug_tag = ''
+openstackdocs_repo_name = 'openstack/python-keystoneclient'
+openstackdocs_bug_project = 'python-keystoneclient'
+openstackdocs_bug_tag = ''
+openstackdocs_pdf_link = True
diff --git a/doc/source/history.rst b/doc/source/history.rst
deleted file mode 100644
index 69ed4fe6c..000000000
--- a/doc/source/history.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../../ChangeLog
diff --git a/doc/source/index.rst b/doc/source/index.rst
index bee963066..f1114b67c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -1,3 +1,4 @@
+========================================================
Python bindings to the OpenStack Identity API (Keystone)
========================================================
@@ -27,19 +28,19 @@ provides `Identity Service`_, as well as `WSGI Middleware`_.
Release Notes
=============
-.. toctree::
- :maxdepth: 1
- history
+Read also the `Keystoneclient Release Notes
+`_.
+
Contributing
============
-Code is hosted `on GitHub`_. Submit bugs to the Keystone project on
+Code is hosted `on OpenDev`_. Submit bugs to the Keystone project on
`Launchpad`_. Submit code to the ``openstack/python-keystoneclient`` project
using `Gerrit`_.
-.. _on GitHub: https://github.com/openstack/python-keystoneclient
+.. _on OpenDev: https://opendev.org/openstack/python-keystoneclient
.. _Launchpad: https://launchpad.net/python-keystoneclient
.. _Gerrit: https://docs.openstack.org/infra/manual/developers.html#development-workflow
diff --git a/doc/source/using-api-v2.rst b/doc/source/using-api-v2.rst
index 1b7c5deaf..7b0815f49 100644
--- a/doc/source/using-api-v2.rst
+++ b/doc/source/using-api-v2.rst
@@ -79,7 +79,7 @@ This example will create a tenant named *openstackDemo*::
>>> keystone = client.Client(...)
>>> keystone.tenants.create(tenant_name="openstackDemo",
... description="Default Tenant", enabled=True)
-
+
Creating users
==============
diff --git a/doc/source/using-api-v3.rst b/doc/source/using-api-v3.rst
index f0c82c5f2..4f305e81f 100644
--- a/doc/source/using-api-v3.rst
+++ b/doc/source/using-api-v3.rst
@@ -102,6 +102,31 @@ For more information on Sessions refer to: `Using Sessions`_.
.. _`Using Sessions`: using-sessions.html
+Getting Metadata Responses
+==========================
+
+Instantiating :py:class:`keystoneclient.v3.client.Client` using
+`include_metadata=True` will cause manager response to return
+:py:class:`keystoneclient.base.Response` instead of just the data.
+The metadata property will be available directly to the
+:py:class:`keystoneclient.base.Response` and the response data will
+be available as property `data` to it.
+
+ >>> from keystoneauth1.identity import v3
+ >>> from keystoneauth1 import session
+ >>> from keystoneclient.v3 import client
+ >>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v3',
+ ... user_id='myuserid',
+ ... password='mypassword',
+ ... project_id='myprojectid')
+ >>> sess = session.Session(auth=auth)
+ >>> keystone = client.Client(session=sess, include_metadata=True)
+ >>> resp = keystone.projects.list()
+ >>> resp.request_ids[0]
+ req-1234-5678-...
+ >>> resp.data
+ [, , ...]
+
Non-Session Authentication (deprecated)
=======================================
diff --git a/examples/pki/certs/cacert.pem b/examples/pki/certs/cacert.pem
index 952bdaea3..6519671a5 100644
--- a/examples/pki/certs/cacert.pem
+++ b/examples/pki/certs/cacert.pem
@@ -1,23 +1,23 @@
-----BEGIN CERTIFICATE-----
-MIID1jCCAr6gAwIBAgIJAJOtRP2+wrM/MA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD
-VQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55
-dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMG
-CSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2Vs
-ZiBTaWduZWQwIBcNMTMwOTEzMTYyNTQyWhgPMjA3MjAzMDcxNjI1NDJaMIGeMQow
-CAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1
-bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTEl
-MCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxML
-U2VsZiBTaWduZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCl8906
-EaRpibQFcCBWfxzLi5x/XpZ9iL6UX92NrSJxcDbaGws7s+GtjgDy8UOEonesRWTe
-qQEZtHpC3/UHHOnsA8F6ha/pq9LioqT7RehCnZCLBJwh5Ct+lclpWs15SkjJD2LT
-Dkjox0eA9nOBx+XDlWyU/GAyqx5Wsvg/Kxr0iod9/4IcJdnSdUjq4v0Cxg/zNk08
-XPJX+F0bUDhgdUf7JrAmmS5LA8wphRnbIgtVsf6VN9HrbqtHAJDxh8gEfuwdhEW1
-df1fBtZ+6WMIF3IRSbIsZELFB6sqcyRj7HhMoWMkdEyPb2f8mq61MzTgE6lJGIyT
-RvEoFie7qtGADIofAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
-AQEFBQADggEBAJRMdEwAdN+crqI9dBLYlbBbnQ8xr9mk+REMdz9+SKhDCNdVisWU
-iLEZvK/aozrsRsDi81JjS4Tz0wXo8zsPPoDnXgDYEicNPTKifbPKgHdDIGFOwBKn
-y2cF6fHEn8n3KIBrDCNY6rHcYGZ7lbq/8eF0GoYQboPiuYesvVpynPmIK5/Mmire
-EuuZALAe1IFqqFt+l6tiJU2JWUFjLkFARMOD14qFZm+SInl64toi08j6gdou+NMW
-7GEMbVHwNTafM/TgFN5j0yP9SAnYubckLSyH6hwR+rM8dztP5769joxQfnc9O/Bn
-TBD9KFpeQv6VJWLAxiIKcQCRTTDJLZZ0MQI=
+MIID4TCCAsmgAwIBAgIUD+MH2KCtZgLgFWNghxF+xZQZx98wDQYJKoZIhvcNAQEL
+BQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAG
+A1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3RhY2sxETAPBgNVBAsMCEtl
+eXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQw
+EgYDVQQDDAtTZWxmIFNpZ25lZDAgFw0yMjAzMDcxNTM1MThaGA8yMDgwMDgyOTE1
+MzUxOFowgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTES
+MBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3RhY2sxETAPBgNVBAsM
+CEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVuc3RhY2sub3Jn
+MRQwEgYDVQQDDAtTZWxmIFNpZ25lZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAL/+AsUcqyF2b/3gaHGtUZx+mReX2QMv+gXmW2KUj1CTmSTxGXCaeoJ5
+N7PA6BeBD/HJVqTgCo/oNuHmOgtYrgRngyWpABItt9ONRmTCr2AvA23AZIjfUdwR
+ZceRHf67H6N1NOttr8IFkuQFhTAKuRHJGcXNqNMJrNv2v5ha3GNeAhxZd965ok9B
+GSd+hvibjZ2mDBZ8kiJ9BGf53TDie/zg+q5CkgqLArgR30pGCe+ZLXPLrhekpyet
+BR3guKTV2PMCeIh7Yg/uTJMe22qZ87M6Q1DosSKC/1l+/1ArBve6msc8JEElnc32
+HJ7NuTTJreZKEvPmUI2oTcdvokWXtRsCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAmdWRPzpI5pAoVn9GX1KNgiN/e9oCpnHYIofV
+fX7i70OBYOwBoyQhFqniHtGH4uqYIxGJdbDtHzsSYCSV1mGqHhK+kStLy4MULUUV
+cNM5yDYDPEtjgJy7G90z/ksX5WuXQgktx9N8emdI6yH8C1b6sHMtHcfnb6O0waMH
+HQ9QpZFQapwuIjeWU0zRDFZkdEAkx6wfVuoMhHOjy1WRAuIOL2ELa6h0GL2d+bmw
+x4Xpyi4X7pgixz3l/9Kfc6VdVrEy4H2bhldUeZ0WjzvMdYaw953+C/5YAfFYanCH
+en9BebSKQMv8QI0OrNyTefMXuxWvcKSOWjQVfRk1ckz6aIrfSw==
-----END CERTIFICATE-----
diff --git a/examples/pki/certs/middleware.pem b/examples/pki/certs/middleware.pem
deleted file mode 100644
index 7d593efd7..000000000
--- a/examples/pki/certs/middleware.pem
+++ /dev/null
@@ -1,50 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
-BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
-EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
-ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgZAxCzAJBgNVBAYTAlVTMQsw
-CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
-Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQDL06AaJROwHPgJ9tcySSBepzJ81jYars2sMvLjyuvd
-iIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rpv8dGDIDsxZQVjT/4SLaQUOeDM+9b
-fkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLYWso0SJD0vAi1gmGDlSM/mmhhHTpC
-DGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1ZrslPC5lFvlHD7KBBf6IU2A8Xh/dUa3
-p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYRR45pPCVkk6vFsy6P0JwwpnkszB+L
-cK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4YEPirGGrAgMBAAEwDQYJKoZIhvcN
-AQEFBQADggEBAAjU7YomUx/U56p1KWHvr1B7oczHF8fPHYbuk5c/N81WOJeSRy+P
-5ZGZ2UPjvqqXByv+78YWMKGY1BZ/2doeWuydr0sdSxEwmIUBYxFpujuYY+0AjS/n
-mMr1ZijK7TJssteKM7/MClzghUhPweDZrAg3ff1hbhK5QSy+9UPxUqLH44tfYSVC
-/BzM6se0p5ToM0bwdsa8TofaBRE1L1IW/Hg4VIGOoKs0R0uLm7+Oot2me2cEuZ6h
-Wls6MED8ND1Nz8EAKwndkeDu2iMM+qx/YFp6K8BQ5E5nXd2rbUZUlQMp1WbUlZ87
-KvC98aT0UYIq6uo1Lx/dQvJs7faAkYd4lmE=
------END CERTIFICATE-----
------BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDL06AaJROwHPgJ
-9tcySSBepzJ81jYars2sMvLjyuvdiIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rp
-v8dGDIDsxZQVjT/4SLaQUOeDM+9bfkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLY
-Wso0SJD0vAi1gmGDlSM/mmhhHTpCDGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1Zrs
-lPC5lFvlHD7KBBf6IU2A8Xh/dUa3p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYR
-R45pPCVkk6vFsy6P0JwwpnkszB+LcK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4
-YEPirGGrAgMBAAECggEATwvbY0hNwlb5uqOIAXBqpUqiQdexU9fG26lGmSDxKBDv
-9o5frcRgBDrMWwvDCgY+HT4CAvB9kJx4/qnpVjkzJp/ZNiJ5VIiehIlbv348rXbh
-xkk+bz5dDATCFOXuu1fwL2FhyM5anwhMAav0DyK1VLQ3jGzr9GO6L8hqAn+bQFFu
-6ngiODwfhBMl5aRoL9UOBEhccK07znrH0JGRz+3+5Cdz59Xw91Bv210LhNNDL58+
-0JD0N+YztVOQd2bgwo0bQbOEijzmYq+0mjoqAnJh1/++y7PlIPs0AnPgqSnFPx9+
-6FsQEVRgk5Uq3kvPLaP4nT2y6MDZSp+ujYldvJhyQQKBgQDuX2pZIJMZ4aFnkG+K
-TmJ5wsLa/u9an0TmvAL9RLtBpVpQNKD8cQ+y8PUZavXDbAIt5NWqZVnTbCR79Dnd
-mZKblwcHhtsyA5f89el5KcxY2BREWdHdTnJpNd7XRlUECmzvX1zGj77lA982PhII
-yflRBRV3vqLkgC8vfoYgRyRElwKBgQDa5jnLdx/RahfYMOgn1HE5o4hMzLR4Y0Dd
-+gELshcUbPqouoP5zOb8WOagVJIgZVOSN+/VqbilVYrqRiNTn2rnoxs+HHRdaJNN
-3eXllD4J2HfC2BIj1xSpIdyh2XewAJqw9IToHNB29QUhxOtgwseHciPG6JaKH2ik
-kqGKH/EKDQKBgFFAftygiOPCkCTgC9UmANUmOQsy6N2H+pF3tsEj43xt44oBVnqW
-A1boYXNnjRwuvdNs9BPf9i1l6E3EItFRXrLgWQoMwryakv0ryYh+YeRKyyW9RBbe
-fYs1TJ8unx4Ae79gTxxztQsVNcmkgLs0NWKTjAzEE3w14V+cDhYEie1DAoGBAJdI
-V5cLrBzBstsB6eBlDR9lqrRRIUS2a8U9m+1mVlcSfiWQSdehSd4K3tDdwePLw3ch
-W4qR8n+pYAlLEe0gFvUhn5lMdwt7U5qUCeehjUKmrRYm2FqWsbu2IFJnBjXIJSC4
-zQXRrC0aZ0KQYpAL7XPpaVp1slyhGmPqxuO78Y0dAoGBAMHo3EIMwu9rfuGwFodr
-GFsOZhfJqgo5GDNxxf89Q9WWpMDTCdX+wdBTrN/wsMbBuwIDHrUuRnk6D5CWRjSk
-/ikCgHN3kOtrbL8zzqRomGAIIWKYGFEIGe1GHVGo5r//HXHdPxFXygvruQ/xbOA4
-RGvmDiji8vVDq7Shho8I6KuT
------END PRIVATE KEY-----
diff --git a/examples/pki/certs/signing_cert.pem b/examples/pki/certs/signing_cert.pem
index 63ab2478d..6428be8d0 100644
--- a/examples/pki/certs/signing_cert.pem
+++ b/examples/pki/certs/signing_cert.pem
@@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIIDpTCCAo0CAREwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
-BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
-EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
-ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgY8xCzAJBgNVBAYTAlVTMQsw
-CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
-Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMREwDwYDVQQDEwhLZXlzdG9uZTCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBAMz5WsgsuX3rZUdLwQpZXN2Ro7LQ6jEZnreBqMztVObw
-BuC1WdiJsg6dVlC7PVdt+0gY1c8WFg1TKmsucxesQSyfGAPg+9T/hsRMb6y12uJx
-fp3Wgqqw0U1HsXvMiaJH87MaGnt043BxzF+R9fhAcDk6Cyj5cx9J0LvZJEOzN4J4
-ZRyO6j/DZZItb3lK5W9xkuoT+mTdDZOQJnXyG818uiWfjdCkLjr1ruytRcBOo4na
-Y828voT/A7I95+YCgKgbjiUWhHeTaNmMEQiGy0nGYfteC+oSsHOlxZ3b12azzHPk
-83Bh2ez0Ih9vcZoe9DqvlFOXfv9q8OsYc5Yo6gPTXEsCAwEAATANBgkqhkiG9w0B
-AQUFAAOCAQEAmaYE98kOQWu6DV84ZcZP/OdT8eeu3vdB247nRj+6+GYItN/Gzqt4
-HVvz7c+FVTolCcAQQ+z3XGswI9fIJ78Hb0p9CgnLprc3L7Xtk60Im59Xlf3tcurn
-r/ZnSDcjRBXKiEDrSM0VrhAnc0GoSeb6aDWopec+1hWOWfBVAg9R8yJgU9sUgO3O
-0gimGyrw8eubmNhckSQLJTunUTsrkcBjuSg63wAD9OqCiX6c2eoQr+0YBp2eV2/n
-aOiJXWNLbeueMKSYiJNyyvM/dlON7/56cdwDTzKzgD34TImouM5VKipUwCX1ovLu
-ITLzALzpqFFzc8ugV9pMgUKtDbZoPp9EEA==
+MIIDpTCCAo0CAREwDQYJKoZIhvcNAQELBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQK
+DAlPcGVuU3RhY2sxETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
+ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDDAtTZWxmIFNpZ25lZDAgFw0y
+MjAzMDcxNTM1MThaGA8yMDgwMDgyOTE1MzUxOFowgY8xCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3Rh
+Y2sxETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
+cGVuc3RhY2sub3JnMREwDwYDVQQDDAhLZXlzdG9uZTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJ7Gc/CGy82PWOmlGD+C8d6Kw3Q1ZodOz9EduhXecfLN
++zHXd9Qd35f5hHf4c8j0yAxI8qfeabjnOefEkoHC4W+DTTsUwq1x7FvAPHbTncSH
+zePqBE8wKp4pfFuZAhMxP55nTJC/N8t1M1lUqYTANgTCAystyOJuLuMc03UBqO8b
+OGzCJsAdcsBPpdYkfycrWv5ZosdaHf3OmakPtWymjSPQ8/lM4x5Fm5GaoYUqb9mo
+busMp0te7MMkzWYilSqZBWHx7dsGR7HoN4zMqalttC0inJGc0wnusNrkeb3ieuXw
+U6T3V3pE3yTTuHy6HcZZd/8m3O/L9F1odzDnUH10PjkCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAiSaPtpERflBUDYtRrAPVEyM3K9DJyZ8pv1vQxCU/h4ZNttVWsRdC
+gqdZg8nYSLj81ZwU1OATQhjXjGn9/mYAIzbm+HH1TMJDWqmnkSblAHGPZmswKmga
+/Cns8PsgsLcMV9BA38lyBhVtgBn4QgsG9EUvscZvVUnxevgqg3a/tlfpPf7fvbmC
+Efcq3liI/l+wxv4O3ET3V6rBZsmTUMNrIIhqFcicynUy3NIIRO3mL92se9X81Jpj
+YxHtMt+RakM0P7yRYL2hjgQW2srssGlMt9U/OIEZQKJVBH85qYuoBAcXC7Y6xRy1
+LvQc4IKf3X4hmqZC7jhBIQAAbaDZTn8peg==
-----END CERTIFICATE-----
diff --git a/examples/pki/certs/ssl_cert.pem b/examples/pki/certs/ssl_cert.pem
index cdd2e4c02..00d33a7bb 100644
--- a/examples/pki/certs/ssl_cert.pem
+++ b/examples/pki/certs/ssl_cert.pem
@@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
-BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
-EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
-ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MzA5MTMxNjI1NDNaGA8yMDcyMDMwNzE2MjU0M1owgZAxCzAJBgNVBAYTAlVTMQsw
-CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
-Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQDL06AaJROwHPgJ9tcySSBepzJ81jYars2sMvLjyuvd
-iIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rpv8dGDIDsxZQVjT/4SLaQUOeDM+9b
-fkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLYWso0SJD0vAi1gmGDlSM/mmhhHTpC
-DGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1ZrslPC5lFvlHD7KBBf6IU2A8Xh/dUa3
-p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYRR45pPCVkk6vFsy6P0JwwpnkszB+L
-cK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4YEPirGGrAgMBAAEwDQYJKoZIhvcN
-AQEFBQADggEBAAjU7YomUx/U56p1KWHvr1B7oczHF8fPHYbuk5c/N81WOJeSRy+P
-5ZGZ2UPjvqqXByv+78YWMKGY1BZ/2doeWuydr0sdSxEwmIUBYxFpujuYY+0AjS/n
-mMr1ZijK7TJssteKM7/MClzghUhPweDZrAg3ff1hbhK5QSy+9UPxUqLH44tfYSVC
-/BzM6se0p5ToM0bwdsa8TofaBRE1L1IW/Hg4VIGOoKs0R0uLm7+Oot2me2cEuZ6h
-Wls6MED8ND1Nz8EAKwndkeDu2iMM+qx/YFp6K8BQ5E5nXd2rbUZUlQMp1WbUlZ87
-KvC98aT0UYIq6uo1Lx/dQvJs7faAkYd4lmE=
+MIIDpjCCAo4CARAwDQYJKoZIhvcNAQELBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQK
+DAlPcGVuU3RhY2sxETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
+ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDDAtTZWxmIFNpZ25lZDAgFw0y
+MjAzMDcxNTM1MThaGA8yMDgwMDgyOTE1MzUxOFowgZAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3Rh
+Y2sxETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
+cGVuc3RhY2sub3JnMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQD1i9+ydZSypNAkkVXdzIqZ8E62cqH7i0JGVGBuGdH8
+ZVF3MDcbi8VwqfNRWoWn9mrJUp5HYDV9t5WXz25Ej4EnqlJ3WLZvC1e+ldDIInmi
+ULic3iIAgrWbumU3XNLHska/smoVJuLIuFUxEfRpwGOpguOzAO1M6BKCSwr+TBLY
+JZxc3F7v1vtwNhisyE5S2H6Q49K0UXHTPjp+fLZAHQ5+Yxqwf0KAJqAD3vMo8Ewx
+XlgJu8pQyjjxwtrwnN2WHYoJGt/OOdkLBbzdupWH9CGcxeVc5hSJ1hEKuYS8AOZI
+eH6q2MKwT+QiepBsVfuy1JFt4raLht/RcX/WR8lIAzoFAgMBAAEwDQYJKoZIhvcN
+AQELBQADggEBAArxwP6I5XXIl3Dhkkt6gegRNc1vYWPEIDkKqggnvntZAOZwavVQ
+kiydT09io82SjD3qv/PQFH+N1KkTCIgYreHQpCQaWMvkpCD2iEcu9R75p4rnZMR2
+NwIlj4BHvXIo9ET5dkhUUxzUGK7eIymNEoMWMF6OGlQhK1FV3Tvjum0sqLOyKOgr
+NFxDv7qFzoKfqjY3lfb9yqO7xC1t3CZSOsBLIaUQ9SBoRJ11UNYGq9ZXHNF3cCbC
+PyE1TgVjNEvWBBRY0ofGoPmdqrTe2oZ6rAFKf0aWJ1qIq+umePp9R8ZwWLonbxQ4
+0nqaUI5AOAdsRpUJHGvW0mmMALYjHT+tF8U=
-----END CERTIFICATE-----
diff --git a/examples/pki/cms/auth_token_revoked.pem b/examples/pki/cms/auth_token_revoked.pem
index 12e4f0ce7..b0312a9b0 100644
--- a/examples/pki/cms/auth_token_revoked.pem
+++ b/examples/pki/cms/auth_token_revoked.pem
@@ -1,79 +1,79 @@
-----BEGIN CMS-----
-MIIOTQYJKoZIhvcNAQcCoIIOPjCCDjoCAQExCTAHBgUrDgMCGjCCDFoGCSqGSIb3
-DQEHAaCCDEsEggxHew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6
-IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMzgtMDEtMThUMjE6MTQ6MDda
-IiwNCiAgICAgICAgICAgICJpc3N1ZWRfYXQiOiAiMjAwMi0wMS0xOFQyMToxNDow
-N1oiLA0KICAgICAgICAgICAgImlkIjogInBsYWNlaG9sZGVyIiwNCiAgICAgICAg
-ICAgICJ0ZW5hbnQiOiB7DQogICAgICAgICAgICAgICAgImlkIjogInRlbmFudF9p
-ZDEiLA0KICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwNCiAgICAgICAg
-ICAgICAgICAiZGVzY3JpcHRpb24iOiBudWxsLA0KICAgICAgICAgICAgICAgICJu
-YW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAgICAgIH0NCiAgICAgICAgfSwN
-CiAgICAgICAgInNlcnZpY2VDYXRhbG9nIjogWw0KICAgICAgICAgICAgew0KICAg
-ICAgICAgICAgICAgICJlbmRwb2ludHNfbGlua3MiOiBbXSwNCiAgICAgICAgICAg
-ICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
-ICAgICAgICAgICAgICAgICAgICAiYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAu
-MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTI3
-LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2Ei
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJodHRwOi8v
-MTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYx
-N2EiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0K
-ICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQogICAgICAgICAgICAg
-ICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAg
-IHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAg
-ICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAg
-ew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8x
-MjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVn
-aW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
-ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAg
-ICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5
-MjkyL3YxIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
-XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpbWFnZSIsDQogICAgICAgICAg
-ICAgICAgIm5hbWUiOiAiZ2xhbmNlIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
-ICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQog
-ICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAg
-ICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6
-Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
-YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn
-aW9uT25lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6
-ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2
-MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQz
-NWU4YTYwZmNmODliYjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAg
-ICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjb21wdXRl
-IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJub3ZhIg0KICAgICAgICAgICAg
-fSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xp
-bmtzIjogW10sDQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAg
-ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWlu
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMToz
-NTM1Ny92Mi4wIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwi
-OiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YyLjAiDQogICAgICAgICAgICAgICAg
-ICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBl
-IjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJrZXlzdG9u
-ZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgInVzZXIiOiB7
-DQogICAgICAgICAgICAidXNlcm5hbWUiOiAicmV2b2tlZF91c2VybmFtZTEiLA0K
-ICAgICAgICAgICAgInJvbGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJy
-b2xlMSIsDQogICAgICAgICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwN
-CiAgICAgICAgICAgICJpZCI6ICJyZXZva2VkX3VzZXJfaWQxIiwNCiAgICAgICAg
-ICAgICJyb2xlcyI6IFsNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAg
-ICAgICAgICJpZCI6ICJmMDNmZGE4ZjhhMzI0OWIyYTcwZmIxZjE3NmE3YjYzMSIs
-DQogICAgICAgICAgICAgICAgICAgICJuYW1lIjogInJvbGUxIg0KICAgICAgICAg
-ICAgICAgIH0sDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAg
-ICAiaWQiOiAiZjAzZmRhOGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2MzEiLA0KICAg
-ICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMiINCiAgICAgICAgICAgICAg
-ICB9DQogICAgICAgICAgICBdLA0KICAgICAgICAgICAgIm5hbWUiOiAicmV2b2tl
-ZF91c2VybmFtZTEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHKMIIBxgIBATCB
-pDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYD
-VQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5
-c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDAS
-BgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIB
-AA2C5qslA4D7vzbiPJ+PzI6CWKH4fxy2nl6wFneHRlzflRGVtbk7/gwVpgHvVH8+
-FvQEWeXiCvpXDcHUae0YsdB6aifDRkRctoBwWZkSIkLtdLjZTBrwoOBD2cWPTlr6
-gFPp0ARCKVP87YXiKHXStvivZDQFbnBrPTZbGwsCZFXzDYtVPkDvgWOIzHP+olB0
-k0wrFXdTQrr62GmkUdgmY31SBLAmPRlvbFBsdM8R62EVc9Mdk7A8Xenpib6+3hPV
-7Jgj5IcC3WWtI1A/WOzuEepfW5AU3bcmsJ4UrsJdZLPYqxy/FS37s7oekBOfSR+Y
-WSVmaaTY21X3kOqAQULJTDI=
+MIIOVQYJKoZIhvcNAQcCoIIORjCCDkICAQExDTALBglghkgBZQMEAgEwggxaBgkq
+hkiG9w0BBwGgggxLBIIMR3sNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r
+ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMDM4LTAxLTE4VDIxOjE0
+OjA3WiIsDQogICAgICAgICAgICAiaXNzdWVkX2F0IjogIjIwMDItMDEtMThUMjE6
+MTQ6MDdaIiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAg
+ICAgICAgICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5h
+bnRfaWQxIiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAg
+ICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAg
+ICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAg
+IH0sDQogICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsN
+CiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAg
+ICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0K
+ICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcu
+MC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDov
+LzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2
+MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0
+cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
+YjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
+XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAg
+ICAgICAgICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAg
+ICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0K
+ICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAg
+ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRw
+Oi8vMTI3LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+InJlZ2lvbiI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+ImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAg
+ICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6OTI5Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg
+ICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAg
+ICAgICAgICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAg
+ICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtd
+LA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg
+ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJo
+dHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj
+Zjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjog
+InJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxV
+UkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1
+ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1
+YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNj
+NTM0MzVlOGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0K
+ICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29t
+cHV0ZSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAg
+ICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50
+c19saW5rcyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQog
+ICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJh
+ZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
+VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAg
+ICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAi
+dHlwZSI6ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5
+c3RvbmUiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2Vy
+Ijogew0KICAgICAgICAgICAgInVzZXJuYW1lIjogInJldm9rZWRfdXNlcm5hbWUx
+IiwNCiAgICAgICAgICAgICJyb2xlc19saW5rcyI6IFsNCiAgICAgICAgICAgICAg
+ICAicm9sZTEiLA0KICAgICAgICAgICAgICAgICJyb2xlMiINCiAgICAgICAgICAg
+IF0sDQogICAgICAgICAgICAiaWQiOiAicmV2b2tlZF91c2VyX2lkMSIsDQogICAg
+ICAgICAgICAicm9sZXMiOiBbDQogICAgICAgICAgICAgICAgew0KICAgICAgICAg
+ICAgICAgICAgICAiaWQiOiAiZjAzZmRhOGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2
+MzEiLA0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAg
+ICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAg
+ICAgICAgImlkIjogImYwM2ZkYThmOGEzMjQ5YjJhNzBmYjFmMTc2YTdiNjMxIiwN
+CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAg
+ICAgICAgfQ0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInJl
+dm9rZWRfdXNlcm5hbWUxIg0KICAgICAgICB9DQogICAgfQ0KfQ0KMYIBzjCCAcoC
+AQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTES
+MBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3RhY2sxETAPBgNVBAsM
+CEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVuc3RhY2sub3Jn
+MRQwEgYDVQQDDAtTZWxmIFNpZ25lZAIBETALBglghkgBZQMEAgEwDQYJKoZIhvcN
+AQEBBQAEggEAGUm9+Jb4P4dO23cAg39q0vVDFPkiPxgxakKE+g4d7VSI7Krt5ypB
+iXo4mHbLqM28zrxgCBxnq2ZhhGzk/qhVWadYWUQQ9FjUBna06Cbd5clGpP8Kp2yk
++SRydFZAw9jUviditNhZA7Nhl8Qzu6T9TB+jPI2y1PY/XXebN97dQqmc+QMGVfzz
+ssU+89ASfki8vEDJWxn2RtxjaXPKeWFUw/qrvj1RkDdI3d22dOTR9p0q7Y9CKLam
+Y1DkosGbBqUF8hTtJMXIfHTLh5Zp+zz1dlsY0FR9kxLKxKya9OG3ACyidL7ewM9r
+pEz2NQztAoi3Guxj6793G0Sfgb0ZCTGcaA==
-----END CMS-----
diff --git a/examples/pki/cms/auth_token_scoped.pem b/examples/pki/cms/auth_token_scoped.pem
index 8754a959c..2974358ba 100644
--- a/examples/pki/cms/auth_token_scoped.pem
+++ b/examples/pki/cms/auth_token_scoped.pem
@@ -1,78 +1,79 @@
-----BEGIN CMS-----
-MIIONwYJKoZIhvcNAQcCoIIOKDCCDiQCAQExCTAHBgUrDgMCGjCCDEQGCSqGSIb3
-DQEHAaCCDDUEggwxew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6
-IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMzgtMDEtMThUMjE6MTQ6MDda
-IiwNCiAgICAgICAgICAgICJpc3N1ZWRfYXQiOiAiMjAwMi0wMS0xOFQyMToxNDow
-N1oiLA0KICAgICAgICAgICAgImlkIjogInBsYWNlaG9sZGVyIiwNCiAgICAgICAg
-ICAgICJ0ZW5hbnQiOiB7DQogICAgICAgICAgICAgICAgImlkIjogInRlbmFudF9p
-ZDEiLA0KICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwNCiAgICAgICAg
-ICAgICAgICAiZGVzY3JpcHRpb24iOiBudWxsLA0KICAgICAgICAgICAgICAgICJu
-YW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAgICAgIH0NCiAgICAgICAgfSwN
-CiAgICAgICAgInNlcnZpY2VDYXRhbG9nIjogWw0KICAgICAgICAgICAgew0KICAg
-ICAgICAgICAgICAgICJlbmRwb2ludHNfbGlua3MiOiBbXSwNCiAgICAgICAgICAg
-ICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
-ICAgICAgICAgICAgICAgICAgICAiYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAu
-MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTI3
-LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2Ei
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJodHRwOi8v
-MTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYx
-N2EiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0K
-ICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQogICAgICAgICAgICAg
-ICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAg
-IHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAg
-ICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAg
-ew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8x
-MjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVn
-aW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
-ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAg
-ICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5
-MjkyL3YxIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
-XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpbWFnZSIsDQogICAgICAgICAg
-ICAgICAgIm5hbWUiOiAiZ2xhbmNlIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
-ICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQog
-ICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAg
-ICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6
-Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
-YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn
-aW9uT25lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6
-ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2
-MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQz
-NWU4YTYwZmNmODliYjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAg
-ICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjb21wdXRl
-IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJub3ZhIg0KICAgICAgICAgICAg
-fSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xp
-bmtzIjogW10sDQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAg
-ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWlu
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMToz
-NTM1Ny92Mi4wIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwi
-OiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YyLjAiDQogICAgICAgICAgICAgICAg
-ICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBl
-IjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJrZXlzdG9u
-ZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgInVzZXIiOiB7
-DQogICAgICAgICAgICAidXNlcm5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAg
-ICAgICAicm9sZXNfbGlua3MiOiBbDQogICAgICAgICAgICAgICAgInJvbGUxIiwN
-CiAgICAgICAgICAgICAgICAicm9sZTIiDQogICAgICAgICAgICBdLA0KICAgICAg
-ICAgICAgImlkIjogInVzZXJfaWQxIiwNCiAgICAgICAgICAgICJyb2xlcyI6IFsN
-CiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICJpZCI6ICJm
-MDNmZGE4ZjhhMzI0OWIyYTcwZmIxZjE3NmE3YjYzMSIsDQogICAgICAgICAgICAg
-ICAgICAgICJuYW1lIjogInJvbGUxIg0KICAgICAgICAgICAgICAgIH0sDQogICAg
-ICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAiaWQiOiAiZjAzZmRh
-OGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2MzEiLA0KICAgICAgICAgICAgICAgICAg
-ICAibmFtZSI6ICJyb2xlMiINCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAg
-ICBdLA0KICAgICAgICAgICAgIm5hbWUiOiAidXNlcl9uYW1lMSINCiAgICAgICAg
-fQ0KICAgIH0NCn0NCjGCAcowggHGAgEBMIGkMIGeMQowCAYDVQQFEwE1MQswCQYD
-VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55dmFsZTESMBAGA1UE
-ChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMGCSqGSIb3DQEJARYW
-a2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2VsZiBTaWduZWQCAREw
-BwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEggEAxyHPqb53KXaWJH1IE6IFp3zzm5vl
-zlotcMxMepMRIxQPUDwJrP2ZJwXemQXVTpRa3Aer7hSkCRlyI++mcj/rD4h5Ygb0
-q9sscjfeZB11Y436E4ZhXCdTfrtmKyBlHMqyhTBz64zroN0P+DVH7OLZDX/gqN2U
-KTX99HTN+LvUa8VqQYIzsjNv80CU6pog/YOCGPixjMKE9m9xYUr9huKZUxliHtX2
-AHoCfQPhI8nsnNHLzCx6u5xIM7A69ZIDPQ82hSHC58k+g0bq9uflRCixBSD7ulR7
-7ZRJM8IgOgFGpNeuyKcHJsCdPpZS8p1MmDCkwTOt5Kvf7Nopz+Cc325uOA==
+MIIOPwYJKoZIhvcNAQcCoIIOMDCCDiwCAQExDTALBglghkgBZQMEAgEwggxEBgkq
+hkiG9w0BBwGgggw1BIIMMXsNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r
+ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMDM4LTAxLTE4VDIxOjE0
+OjA3WiIsDQogICAgICAgICAgICAiaXNzdWVkX2F0IjogIjIwMDItMDEtMThUMjE6
+MTQ6MDdaIiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAg
+ICAgICAgICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5h
+bnRfaWQxIiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAg
+ICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAg
+ICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAg
+IH0sDQogICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsN
+CiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAg
+ICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0K
+ICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcu
+MC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDov
+LzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2
+MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0
+cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
+YjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
+XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAg
+ICAgICAgICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAg
+ICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0K
+ICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAg
+ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRw
+Oi8vMTI3LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+InJlZ2lvbiI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+ImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAg
+ICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6OTI5Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg
+ICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAg
+ICAgICAgICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAg
+ICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtd
+LA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg
+ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJo
+dHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj
+Zjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjog
+InJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxV
+UkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1
+ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1
+YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNj
+NTM0MzVlOGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0K
+ICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29t
+cHV0ZSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAg
+ICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50
+c19saW5rcyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQog
+ICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJh
+ZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
+VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAg
+ICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAi
+dHlwZSI6ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5
+c3RvbmUiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2Vy
+Ijogew0KICAgICAgICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAg
+ICAgICAgICAgInJvbGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xl
+MSIsDQogICAgICAgICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAg
+ICAgICAgICAgICJpZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMi
+OiBbDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAiaWQi
+OiAiZjAzZmRhOGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2MzEiLA0KICAgICAgICAg
+ICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAgICAgICAgICAgICB9LA0K
+ICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgImlkIjogImYw
+M2ZkYThmOGEzMjQ5YjJhNzBmYjFmMTc2YTdiNjMxIiwNCiAgICAgICAgICAgICAg
+ICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAgICAgfQ0KICAgICAg
+ICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJfbmFtZTEiDQogICAg
+ICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgGA1UEBRMBNTEL
+MAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEjAQ
+BgNVBAoMCU9wZW5TdGFjazERMA8GA1UECwwIS2V5c3RvbmUxJTAjBgkqhkiG9w0B
+CQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMMC1NlbGYgU2lnbmVk
+AgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQBYn04AtTif863EsRze
+H4qwhQwcDMEy9+tqm6Pof1ysl7wnqtyeJbUaEmljzYOeiYvcI9tOAj/beTpxbU3A
+6vo0XkPt82Fdn3tPu2Rbr5cmCWkqRUAazEXBwfwPFBeA01Th2yxtTNUeiZJyjbcO
+6DfeXeQSQWkblB375+2RQNGOuEbU1JwC8sErk8eTetA419fh+tn5m3h/FhHRiWGo
+2NWy9HRx0OjCnnjNtIWY++QbVLQS7lty/f3E1c3l8ebGhBXleEmWbpp1zUi9e5oK
+0NlVB+nwiw9qkzAgX5ForSaFGkGlHjjAtoIs/i3DgP+3ET/pZkislu6NpiXfklY4
+o35g
-----END CMS-----
diff --git a/examples/pki/cms/auth_token_scoped_expired.pem b/examples/pki/cms/auth_token_scoped_expired.pem
index 43e09f333..9c4bdb9e1 100644
--- a/examples/pki/cms/auth_token_scoped_expired.pem
+++ b/examples/pki/cms/auth_token_scoped_expired.pem
@@ -1,76 +1,79 @@
-----BEGIN CMS-----
-MIINuQYJKoZIhvcNAQcCoIINqjCCDaYCAQExCTAHBgUrDgMCGjCCC8YGCSqGSIb3
-DQEHAaCCC7cEgguzew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6
-IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMTAtMDYtMDJUMTQ6NDc6MzRa
-IiwNCiAgICAgICAgICAgICJpc3N1ZWRfYXQiOiAiMjAwMi0wMS0xOFQyMToxNDow
-N1oiLA0KICAgICAgICAgICAgImlkIjogInBsYWNlaG9sZGVyIiwNCiAgICAgICAg
-ICAgICJ0ZW5hbnQiOiB7DQogICAgICAgICAgICAgICAgImlkIjogInRlbmFudF9p
-ZDEiLA0KICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwNCiAgICAgICAg
-ICAgICAgICAiZGVzY3JpcHRpb24iOiBudWxsLA0KICAgICAgICAgICAgICAgICJu
-YW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAgICAgIH0NCiAgICAgICAgfSwN
-CiAgICAgICAgInNlcnZpY2VDYXRhbG9nIjogWw0KICAgICAgICAgICAgew0KICAg
-ICAgICAgICAgICAgICJlbmRwb2ludHNfbGlua3MiOiBbXSwNCiAgICAgICAgICAg
-ICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
-ICAgICAgICAgICAgICAgICAgICAiYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAu
-MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTI3
-LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2Ei
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJodHRwOi8v
-MTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYx
-N2EiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0K
-ICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQogICAgICAgICAgICAg
-ICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAg
-IHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAg
-ICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAg
-ew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8x
-MjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVn
-aW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
-ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAg
-ICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5
-MjkyL3YxIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
-XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpbWFnZSIsDQogICAgICAgICAg
-ICAgICAgIm5hbWUiOiAiZ2xhbmNlIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
-ICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQog
-ICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAg
-ICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6
-Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
-YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn
-aW9uT25lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcm5hbFVSTCI6
-ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2
-MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQz
-NWU4YTYwZmNmODliYjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAg
-ICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjb21wdXRl
-IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJub3ZhIg0KICAgICAgICAgICAg
-fSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xp
-bmtzIjogW10sDQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAg
-ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImFkbWlu
-VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMToz
-NTM1Ny92Mi4wIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwi
-OiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YyLjAiDQogICAgICAgICAgICAgICAg
-ICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBl
-IjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJrZXlzdG9u
-ZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgInVzZXIiOiB7
-DQogICAgICAgICAgICAidXNlcm5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAg
-ICAgICAicm9sZXNfbGlua3MiOiBbDQogICAgICAgICAgICAgICAgInJvbGUxIiwN
-CiAgICAgICAgICAgICAgICAicm9sZTIiDQogICAgICAgICAgICBdLA0KICAgICAg
-ICAgICAgImlkIjogInVzZXJfaWQxIiwNCiAgICAgICAgICAgICJyb2xlcyI6IFsN
-CiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICJuYW1lIjog
-InJvbGUxIg0KICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAgew0K
-ICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMiINCiAgICAgICAgICAg
-ICAgICB9DQogICAgICAgICAgICBdLA0KICAgICAgICAgICAgIm5hbWUiOiAidXNl
-cl9uYW1lMSINCiAgICAgICAgfQ0KICAgIH0NCn0NCjGCAcowggHGAgEBMIGkMIGe
-MQowCAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcT
-CVN1bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9u
-ZTElMCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UE
-AxMLU2VsZiBTaWduZWQCAREwBwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEggEAw7K9
-7FaxXE6QNbsWmTAo/mtppDB2hv2DCwxMnjaZuOlV3g7UGnF8mxHjWd2Pcj1r0oGb
-0iACE9qmoZVHTPWU6WWBClAIF/bcs6Y+5S10bCu1uRVrzUCsLEbbJOLxBZG1qiEZ
-opLn6pBIOY8ovxcoKKmI56JgsqVGclZM5yH9Z9E5hSZgMREJZFZcVHA3pTJeTjc2
-9Mpb3RS5Q/FXf2nP09YA4Mp9+J15gFH/YuhBQiyo+LqvHtg+DdWdxcM3keAaTuxw
-Z8Cd26T+cTv1iS5qXcykd8OP7V0eIF7i39wshXGm6B9XpwFEYiLTZy7398O/yeGd
-izImJNpCowBA0Pyr8w==
+MIIOPwYJKoZIhvcNAQcCoIIOMDCCDiwCAQExDTALBglghkgBZQMEAgEwggxEBgkq
+hkiG9w0BBwGgggw1BIIMMXsNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r
+ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMDEwLTA2LTAyVDE0OjQ3
+OjM0WiIsDQogICAgICAgICAgICAiaXNzdWVkX2F0IjogIjIwMDItMDEtMThUMjE6
+MTQ6MDdaIiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAg
+ICAgICAgICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5h
+bnRfaWQxIiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAg
+ICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAg
+ICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAg
+IH0sDQogICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsN
+CiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAg
+ICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0K
+ICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcu
+MC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDov
+LzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2
+MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0
+cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
+YjY2MTdhIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAg
+XSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAg
+ICAgICAgICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAg
+ICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0K
+ICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAg
+ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRw
+Oi8vMTI3LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+InJlZ2lvbiI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+ImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAg
+ICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6OTI5Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg
+ICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAg
+ICAgICAgICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAg
+ICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtd
+LA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg
+ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJo
+dHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj
+Zjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjog
+InJlZ2lvbk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxV
+UkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1
+ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1
+YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNj
+NTM0MzVlOGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0K
+ICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29t
+cHV0ZSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAg
+ICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50
+c19saW5rcyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQog
+ICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJh
+ZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4w
+LjE6MzUzNTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGlj
+VVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAg
+ICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAi
+dHlwZSI6ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5
+c3RvbmUiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2Vy
+Ijogew0KICAgICAgICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAg
+ICAgICAgICAgInJvbGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xl
+MSIsDQogICAgICAgICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAg
+ICAgICAgICAgICJpZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMi
+OiBbDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAiaWQi
+OiAiZjAzZmRhOGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2MzEiLA0KICAgICAgICAg
+ICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAgICAgICAgICAgICB9LA0K
+ICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgImlkIjogImYw
+M2ZkYThmOGEzMjQ5YjJhNzBmYjFmMTc2YTdiNjMxIiwNCiAgICAgICAgICAgICAg
+ICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAgICAgfQ0KICAgICAg
+ICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJfbmFtZTEiDQogICAg
+ICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgGA1UEBRMBNTEL
+MAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEjAQ
+BgNVBAoMCU9wZW5TdGFjazERMA8GA1UECwwIS2V5c3RvbmUxJTAjBgkqhkiG9w0B
+CQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMMC1NlbGYgU2lnbmVk
+AgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQCFiZDCR4kvDWvNVo3l
+306T6uMi+CuLklTr9msrA4rhRDROZ6N8y/0TrpnBInhJC9A5OGnRgiAPFrg3ksLP
+ONqqtdQSgNLnzVjauJzVvejzOIYtnp6quQzxy+B1xS/QX+8ODgxz8PcvFszWDvBx
+qDi/q3XAU2fvdRkq96WBGkqjAOb1pxHA1WbOklcjAm/PL5qgcFc+aryiVvPVBjFy
+1KfOZjncXtDBB0Bz5+7MxAxej7LhRZ/eqlK2A/mn2vIlvPKLTGdfuQ10aIBtJ5lW
+cP2miCjk179e2OU71eJdpJk1bFBXNoNbeu7dhI6/W65SKo/EbEgLO07NXW4qqcVQ
+vnt9
-----END CMS-----
diff --git a/examples/pki/cms/auth_token_unscoped.pem b/examples/pki/cms/auth_token_unscoped.pem
index 274ac3860..bfb97968f 100644
--- a/examples/pki/cms/auth_token_unscoped.pem
+++ b/examples/pki/cms/auth_token_unscoped.pem
@@ -1,29 +1,29 @@
-----BEGIN CMS-----
-MIIE9gYJKoZIhvcNAQcCoIIE5zCCBOMCAQExCTAHBgUrDgMCGjCCAwMGCSqGSIb3
-DQEHAaCCAvQEggLwew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6
-IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIxMTItMDgtMTdUMTU6MzU6MzRa
-IiwNCiAgICAgICAgICAgICJpc3N1ZWRfYXQiOiAiMjAwMi0wMS0xOFQyMToxNDow
-N1oiLA0KICAgICAgICAgICAgImlkIjogIjAxZTAzMmM5OTZlZjQ0MDZiMTQ0MzM1
-OTE1YTQxZTc5Ig0KICAgICAgICB9LA0KICAgICAgICAic2VydmljZUNhdGFsb2ci
-OiB7fSwNCiAgICAgICAgInVzZXIiOiB7DQogICAgICAgICAgICAidXNlcm5hbWUi
-OiAidXNlcl9uYW1lMSIsDQogICAgICAgICAgICAicm9sZXNfbGlua3MiOiBbXSwN
-CiAgICAgICAgICAgICJpZCI6ICJjOWM4OWUzYmUzZWU0NTNmYmYwMGM3OTY2ZjZk
-M2ZiZCIsDQogICAgICAgICAgICAicm9sZXMiOiBbDQogICAgICAgICAgICAgICAg
-ew0KICAgICAgICAgICAgICAgICAgICAiaWQiOiAiMzU5ZGE0MmQzMWMwNDQzN2Ez
-MjgxMmFlYjc5ZTljMGIiLA0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJy
-b2xlMSINCiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAg
-ICAgICAgICAgICAgICAgICAgImlkIjogIjU4MWFmMTk3MjZmYTRhZjViZGE3NDU3
-ODlhYjJiZjJiIiwNCiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIi
-DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAg
-ICJuYW1lIjogInVzZXJfbmFtZTEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHK
-MIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
-AkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8G
-A1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFj
-ay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3
-DQEBAQUABIIBAMmrhRIUjSd+SLUAYn+18MDB8MXiaiF+FJQbu86IFW3OpL86ksvg
-CTP44Rvu1F4vvoZAQ60/tOfFVNTnBgnMv0NEfl4huiFqYrXjCphnNFQ5OYnmU6LR
-bFV+dvjZXWUn0wJDroUUEjbgyy/mqUnULzQgUzyK7Ho8T0dWahQc7EFMNVjoeKfa
-K7DeRe9trNNHM8anKVaeKhpWIfzbxiwIwypukce6wVGfdhaP+58jeFnGwHUIsY8V
-8rzWj9UN46ko61piMAZljcktbrpqw2fDJ1H9Xl23G83rnXY7uVLQWUe7fRcUFtQt
-gQvKsGkN2hqlOgMT/FxFM3HC8kcl3wmzrNA=
+MIIE/gYJKoZIhvcNAQcCoIIE7zCCBOsCAQExDTALBglghkgBZQMEAgEwggMDBgkq
+hkiG9w0BBwGgggL0BIIC8HsNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r
+ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMTEyLTA4LTE3VDE1OjM1
+OjM0WiIsDQogICAgICAgICAgICAiaXNzdWVkX2F0IjogIjIwMDItMDEtMThUMjE6
+MTQ6MDdaIiwNCiAgICAgICAgICAgICJpZCI6ICIwMWUwMzJjOTk2ZWY0NDA2YjE0
+NDMzNTkxNWE0MWU3OSINCiAgICAgICAgfSwNCiAgICAgICAgInNlcnZpY2VDYXRh
+bG9nIjoge30sDQogICAgICAgICJ1c2VyIjogew0KICAgICAgICAgICAgInVzZXJu
+YW1lIjogInVzZXJfbmFtZTEiLA0KICAgICAgICAgICAgInJvbGVzX2xpbmtzIjog
+W10sDQogICAgICAgICAgICAiaWQiOiAiYzljODllM2JlM2VlNDUzZmJmMDBjNzk2
+NmY2ZDNmYmQiLA0KICAgICAgICAgICAgInJvbGVzIjogWw0KICAgICAgICAgICAg
+ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgImlkIjogIjM1OWRhNDJkMzFjMDQ0
+MzdhMzI4MTJhZWI3OWU5YzBiIiwNCiAgICAgICAgICAgICAgICAgICAgIm5hbWUi
+OiAicm9sZTEiDQogICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICB7
+DQogICAgICAgICAgICAgICAgICAgICJpZCI6ICI1ODFhZjE5NzI2ZmE0YWY1YmRh
+NzQ1Nzg5YWIyYmYyYiIsDQogICAgICAgICAgICAgICAgICAgICJuYW1lIjogInJv
+bGUyIg0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIF0sDQogICAgICAg
+ICAgICAibmFtZSI6ICJ1c2VyX25hbWUxIg0KICAgICAgICB9DQogICAgfQ0KfQ0K
+MYIBzjCCAcoCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD
+VQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3RhY2sx
+ETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu
+c3RhY2sub3JnMRQwEgYDVQQDDAtTZWxmIFNpZ25lZAIBETALBglghkgBZQMEAgEw
+DQYJKoZIhvcNAQEBBQAEggEAYIiuAmAxllZ5FdGlJWu0bxAsxwFb114lZAq2/mju
+v2Hu9505N4TbkJJI++ojNwv1extCAL0H7jmM2nbPovPa0R6RVDRgh1R03E+uLNld
+rBXyiTeZh2OrbmoXdHAXdJRnBkLIfjDXISY5qN/yJhsr3g6djekGnkWzZfwtwjyb
+qBbVVB9oK9p5svd85jiOcGlcBxuBhWeqwZiYTzyDtJ2SuwtvBaIDQICyS9VtGI+F
+NzqtdUHw/vxsQqOq6tR4Qf32wtZnUS+komQWX3uJXwYpSZHomuGPbs0XolGXYm8D
+fM/7R9AH6CUlmBmq/WVQdEMMv9VADaP9yHuGvM8w3f6ZvA==
-----END CMS-----
diff --git a/examples/pki/cms/auth_v3_token_revoked.pem b/examples/pki/cms/auth_v3_token_revoked.pem
index ca2bf06be..0b1ecbf4a 100644
--- a/examples/pki/cms/auth_v3_token_revoked.pem
+++ b/examples/pki/cms/auth_v3_token_revoked.pem
@@ -1,123 +1,125 @@
-----BEGIN CMS-----
-MIIWqQYJKoZIhvcNAQcCoIIWmjCCFpYCAQExCTAHBgUrDgMCGjCCFLYGCSqGSIb3
-DQEHAaCCFKcEghSjew0KICAgICJ0b2tlbiI6IHsNCiAgICAgICAgImNhdGFsb2ci
-OiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6
-IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAg
-ICAgImlkIjogIjNiNWU1NTRiY2YxMTRmMjQ4M2U4YTFiZTdhMDUwNmQxIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAiYWRtaW4iLA0KICAg
-ICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3
-NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAg
-ICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAg
-ICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAg
-ICAgICAgICAgICAgICAgICJpZCI6ICI1NGFiZDJkYzQ2M2M0YmE0YTcyOTE1NDk4
-ZjhlY2FkMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjog
-ImludGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0
-cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
-YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn
-aW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAg
-ICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQiOiAiNzBhN2VmYTRi
-MWI5NDE5NjgzNTdjYzQzYWUxNDE5ZWUiLA0KICAgICAgICAgICAgICAgICAgICAg
-ICAgImludGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAgICAgICAg
-ICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUz
-NDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
-InJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAg
-ICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJpZCI6ICI1NzA3YzNm
-YzBhMjk0NzAzYTNjNjM4ZTljZjZhNmMzYSIsDQogICAgICAgICAgICAgICAgInR5
-cGUiOiAidm9sdW1lIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJ2b2x1bWUi
-DQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg
-ICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAg
-ICAgICAgICAgICAgICAgICJpZCI6ICI5MjIxN2EzYjk1Mzk0NDkyODU5YmM0OWZk
-NDc0MzgyZiIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjog
-ImFkbWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDov
-LzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJy
+MIIW/gYJKoZIhvcNAQcCoIIW7zCCFusCAQExDTALBglghkgBZQMEAgEwghUDBgkq
+hkiG9w0BBwGgghT0BIIU8HsNCiAgICAidG9rZW4iOiB7DQogICAgICAgICJjYXRh
+bG9nIjogWw0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJlbmRwb2lu
+dHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAg
+ICAgICAgICJpZCI6ICIzYjVlNTU0YmNmMTE0ZjI0ODNlOGExYmU3YTA1MDZkMSIs
+DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImFkbWluIiwN
+CiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAu
+MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAg
+ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAg
+ICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
+ICAgICAgICAgICAgICAgICAgICAiaWQiOiAiNTRhYmQyZGM0NjNjNGJhNGE3Mjkx
+NTQ5OGY4ZWNhZDEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFj
+ZSI6ICJpbnRlcm5hbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjog
+Imh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj
+Zjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjog
+InJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAg
+ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogIjcwYTdl
+ZmE0YjFiOTQxOTY4MzU3Y2M0M2FlMTQxOWVlIiwNCiAgICAgICAgICAgICAgICAg
+ICAgICAgICJpbnRlcmZhY2UiOiAicHVibGljIiwNCiAgICAgICAgICAgICAgICAg
+ICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2Zi
+Y2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAg
+ICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9
+DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAiaWQiOiAiNTcw
+N2MzZmMwYTI5NDcwM2EzYzYzOGU5Y2Y2YTZjM2EiLA0KICAgICAgICAgICAgICAg
+ICJ0eXBlIjogInZvbHVtZSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAidm9s
+dW1lIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAg
+ICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
+ICAgICAgICAgICAgICAgICAgICAiaWQiOiAiOTIyMTdhM2I5NTM5NDQ5Mjg1OWJj
+NDlmZDQ3NDM4MmYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFj
+ZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0
+dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAg
+ICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwN
+CiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAg
+ImlkIjogImYyMDU2M2JkZjY2ZjRlZmE4YTFmMTFkOTliNjcyYmUxIiwNCiAgICAg
+ICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAiaW50ZXJuYWwiLA0KICAg
+ICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjky
+OTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdp
+b25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAg
+ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICIzNzVmOWJhNDU5
+YTQ0NzczOGZiNjBmZTVmYzI2ZTlhYSIsDQogICAgICAgICAgICAgICAgICAgICAg
+ICAiaW50ZXJmYWNlIjogInB1YmxpYyIsDQogICAgICAgICAgICAgICAgICAgICAg
+ICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAg
+ICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAg
+ICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAg
+ImlkIjogIjE1YzIxYWFlNmIyNzRhOGRhNTJlMGEwNjhlOTA4YWFjIiwNCiAgICAg
+ICAgICAgICAgICAidHlwZSI6ICJpbWFnZSIsDQogICAgICAgICAgICAgICAgIm5h
+bWUiOiAiZ2xhbmNlIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAgIHsNCiAg
+ICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAg
+ICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQiOiAiZWRiZDlmNTBmNjY3
+NDZhZTllZDExZGMzYjFhZTM1ZGEiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
+ImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAi
+dXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQz
+NWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJy
ZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAg
ICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQi
-OiAiZjIwNTYzYmRmNjZmNGVmYThhMWYxMWQ5OWI2NzJiZTEiLA0KICAgICAgICAg
+OiAiOWUwM2M0NmM4MGEzNGExNTljYjM5ZjVjYjA0OThiOTIiLA0KICAgICAgICAg
ICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJpbnRlcm5hbCIsDQogICAgICAg
-ICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92
-MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9u
-ZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAg
-ew0KICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogIjM3NWY5YmE0NTlhNDQ3
-NzM4ZmI2MGZlNWZjMjZlOWFhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJp
-bnRlcmZhY2UiOiAicHVibGljIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1
-cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAgICAgICAg
-ICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAg
-ICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAiaWQi
-OiAiMTVjMjFhYWU2YjI3NGE4ZGE1MmUwYTA2OGU5MDhhYWMiLA0KICAgICAgICAg
-ICAgICAgICJ0eXBlIjogImltYWdlIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6
-ICJnbGFuY2UiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgew0KICAgICAg
-ICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsN
-CiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICJlZGJkOWY1MGY2Njc0NmFl
-OWVkMTFkYzNiMWFlMzVkYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
-ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwi
-OiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThh
-NjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv
-biI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAg
-ICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICI5
-ZTAzYzQ2YzgwYTM0YTE1OWNiMzlmNWNiMDQ5OGI5MiIsDQogICAgICAgICAgICAg
-ICAgICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAg
-ICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEv
-NjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAg
-ICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAg
-ICAgICAgIH0sDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAg
-ICAgICAgICAgICJpZCI6ICIxZGYwYjQ0ZDkyNjM0ZDU5YmQwZTBkNjBjZjdjZTQz
-MiIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogInB1Ymxp
-YyIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcu
-MC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdh
-IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25l
-Ig0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAg
-ICAgICAgICAgICAgICAiaWQiOiAiMmY0MDRmZGI4OTE1NGM1ODllZmJjMTA3MjZi
-MDI5ZWMiLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogImNvbXB1dGUiLA0KICAg
-ICAgICAgICAgICAgICJuYW1lIjogIm5vdmEiDQogICAgICAgICAgICB9LA0KICAg
-ICAgICAgICAgew0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAg
-ICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6
-ICJhNDUwMWUxNDFhNGI0ZTE0YmYyODJlN2JmZmQ4MWRjNSIsDQogICAgICAgICAg
-ICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAgICAg
-ICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTozNTM1Ny92MyIs
-DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSIN
-CiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0K
-ICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogIjNkMTdlMzIyN2JmYzQ0ODNi
-NThkZTVlYWE1ODRlMzYwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRl
-cmZhY2UiOiAiaW50ZXJuYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVy
-bCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAgICAgICAg
-ICAgICAgICAgICJyZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAgICAgICAgICAg
-ICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAg
-ICAgICAgICAiaWQiOiAiOGNkNGI5NTcwOTBmNGNhNTg0MmEyMmU5YTc0MDk5Y2Qi
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMi
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAu
-MC4xOjUwMDAvdjMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6
-ICJSZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAg
-ICAgICBdLA0KICAgICAgICAgICAgICAgICJpZCI6ICJjNWQ5MjZkNTY2NDI0ZTRm
-YmE0ZjgwYzM3OTE2Y2RlNSIsDQogICAgICAgICAgICAgICAgInR5cGUiOiAiaWRl
-bnRpdHkiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogImtleXN0b25lIg0KICAg
-ICAgICAgICAgfQ0KICAgICAgICBdLA0KICAgICAgICAiaXNzdWVkX2F0IjogIjIw
-MDItMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgImV4cGlyZXNfYXQiOiAiMjAz
-OC0wMS0xOFQyMToxNDowN1oiLA0KICAgICAgICAicHJvamVjdCI6IHsNCiAgICAg
-ICAgICAgICJlbmFibGVkIjogdHJ1ZSwNCiAgICAgICAgICAgICJkZXNjcmlwdGlv
-biI6IG51bGwsDQogICAgICAgICAgICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiLA0K
-ICAgICAgICAgICAgImlkIjogInRlbmFudF9pZDEiLA0KICAgICAgICAgICAgImRv
-bWFpbiI6IHsNCiAgICAgICAgICAgICAgICAiaWQiOiAiZG9tYWluX2lkMSIsDQog
-ICAgICAgICAgICAgICAgIm5hbWUiOiAiZG9tYWluX25hbWUxIg0KICAgICAgICAg
-ICAgfQ0KICAgICAgICB9LA0KICAgICAgICAidXNlciI6IHsNCiAgICAgICAgICAg
-ICJuYW1lIjogInJldm9rZWRfdXNlcm5hbWUxIiwNCiAgICAgICAgICAgICJpZCI6
-ICJyZXZva2VkX3VzZXJfaWQxIiwNCiAgICAgICAgICAgICJkb21haW4iOiB7DQog
-ICAgICAgICAgICAgICAgImlkIjogImRvbWFpbl9pZDEiLA0KICAgICAgICAgICAg
-ICAgICJuYW1lIjogImRvbWFpbl9uYW1lMSINCiAgICAgICAgICAgIH0NCiAgICAg
-ICAgfSwNCiAgICAgICAgInJvbGVzIjogWw0KICAgICAgICAgICAgew0KICAgICAg
-ICAgICAgICAgICJpZCI6ICJmMDNmZGE4ZjhhMzI0OWIyYTcwZmIxZjE3NmE3YjYz
-MSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTEiDQogICAgICAgICAg
-ICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJpZCI6ICJmMDNm
-ZGE4ZjhhMzI0OWIyYTcwZmIxZjE3NmE3YjYzMSIsDQogICAgICAgICAgICAgICAg
-Im5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAg
-ICAgICJtZXRob2RzIjogWw0KICAgICAgICAgICAgInBhc3N3b3JkIg0KICAgICAg
-ICBdDQogICAgfQ0KfQ0KMYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJ
-BgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYD
-VQQKEwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkB
-FhZrZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIB
-ETAHBgUrDgMCGjANBgkqhkiG9w0BAQEFAASCAQCy1xOK1+nQy8tL3fORdWkcp0Y5
-88cNgl4sXmJOE1TOOEauMyVWE188gtxHelVDCFWr8kICALvAnPX0UbIhoEaxscey
-mvcUazUMP2WWSsBMgSXBfbl6amTZp5KMgpMmAuGjP1xok3yvOecEF6Szh8yE3Q5O
-sNEKsMI5UiJTDU7WWSUp1Zs7E4UvFjAepZGhIQWOCxSvEnrl3Mfw1f7HWKDBlijR
-4XnPqJPiTmYLjzyDmi31GOHWZM4nZxShHfidLblPV4AyA/gsCh27/cZxYW/Q+cyL
-wfQogs4g7XfNgLdDHlbvv7NCS06RhydhLeiqNUcCp4hnZZC16KDPWzJ2Ql5y
+ICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92
+MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAg
+ICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAg
+ICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAg
+ICAgICAgICAgICAgICAiaWQiOiAiMWRmMGI0NGQ5MjYzNGQ1OWJkMGUwZDYwY2Y3
+Y2U0MzIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJw
+dWJsaWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8v
+MTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2
+NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv
+bk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s
+DQogICAgICAgICAgICAgICAgImlkIjogIjJmNDA0ZmRiODkxNTRjNTg5ZWZiYzEw
+NzI2YjAyOWVjIiwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJjb21wdXRlIiwN
+CiAgICAgICAgICAgICAgICAibmFtZSI6ICJub3ZhIg0KICAgICAgICAgICAgfSwN
+CiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0K
+ICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAi
+aWQiOiAiYTQ1MDFlMTQxYTRiNGUxNGJmMjgyZTdiZmZkODFkYzUiLA0KICAgICAg
+ICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAg
+ICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcv
+djMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25P
+bmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAgICAg
+IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICIzZDE3ZTMyMjdiZmM0
+NDgzYjU4ZGU1ZWFhNTg0ZTM2MCIsDQogICAgICAgICAgICAgICAgICAgICAgICAi
+aW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAg
+ICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTozNTM1Ny92MyIsDQogICAgICAgICAg
+ICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSINCiAgICAgICAgICAg
+ICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAg
+ICAgICAgICAgICAgImlkIjogIjhjZDRiOTU3MDkwZjRjYTU4NDJhMjJlOWE3NDA5
+OWNkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAicHVi
+bGljIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEy
+Ny4wLjAuMTo1MDAwL3YzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdp
+b24iOiAiUmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAg
+ICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAiaWQiOiAiYzVkOTI2ZDU2NjQy
+NGU0ZmJhNGY4MGMzNzkxNmNkZTUiLA0KICAgICAgICAgICAgICAgICJ0eXBlIjog
+ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJrZXlzdG9uZSIN
+CiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgImlzc3VlZF9hdCI6
+ICIyMDAyLTAxLTE4VDIxOjE0OjA3WiIsDQogICAgICAgICJleHBpcmVzX2F0Ijog
+IjIwMzgtMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgImF1ZGl0X2lkcyI6IFsi
+Wnp6WjJaWllxVDhPemZVVnZyakVJVFEiLCAiY0NDQ0NDY3RUek8xLVhVazVTVHli
+dyJdLA0KICAgICAgICAicHJvamVjdCI6IHsNCiAgICAgICAgICAgICJlbmFibGVk
+IjogdHJ1ZSwNCiAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6IG51bGwsDQogICAg
+ICAgICAgICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiLA0KICAgICAgICAgICAgImlk
+IjogInRlbmFudF9pZDEiLA0KICAgICAgICAgICAgImRvbWFpbiI6IHsNCiAgICAg
+ICAgICAgICAgICAiaWQiOiAiZG9tYWluX2lkMSIsDQogICAgICAgICAgICAgICAg
+Im5hbWUiOiAiZG9tYWluX25hbWUxIg0KICAgICAgICAgICAgfQ0KICAgICAgICB9
+LA0KICAgICAgICAidXNlciI6IHsNCiAgICAgICAgICAgICJuYW1lIjogInJldm9r
+ZWRfdXNlcm5hbWUxIiwNCiAgICAgICAgICAgICJpZCI6ICJyZXZva2VkX3VzZXJf
+aWQxIiwNCiAgICAgICAgICAgICJkb21haW4iOiB7DQogICAgICAgICAgICAgICAg
+ImlkIjogImRvbWFpbl9pZDEiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogImRv
+bWFpbl9uYW1lMSINCiAgICAgICAgICAgIH0NCiAgICAgICAgfSwNCiAgICAgICAg
+InJvbGVzIjogWw0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJpZCI6
+ICJmMDNmZGE4ZjhhMzI0OWIyYTcwZmIxZjE3NmE3YjYzMSIsDQogICAgICAgICAg
+ICAgICAgIm5hbWUiOiAicm9sZTEiDQogICAgICAgICAgICB9LA0KICAgICAgICAg
+ICAgew0KICAgICAgICAgICAgICAgICJpZCI6ICJmMDNmZGE4ZjhhMzI0OWIyYTcw
+ZmIxZjE3NmE3YjYzMSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIi
+DQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJtZXRob2RzIjog
+Ww0KICAgICAgICAgICAgInBhc3N3b3JkIg0KICAgICAgICBdDQogICAgfQ0KfQ0K
+MYIBzjCCAcoCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD
+VQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlPcGVuU3RhY2sx
+ETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu
+c3RhY2sub3JnMRQwEgYDVQQDDAtTZWxmIFNpZ25lZAIBETALBglghkgBZQMEAgEw
+DQYJKoZIhvcNAQEBBQAEggEAh4ESJgQ+2tuZrQdOUGXKi5uO56bbX5c15WdhPcHA
+gXK4TUXC8Gb0pTyAGXXWkHwErf+7NHrZbA5Y8zqTor8qjig+tT8Ywh82lzY+mXOE
+HgnkKNoGUmgv1auJuECjysLHX6T5c0AUOxPSBvCQtvmGl33/riX5/gM+D/Dkptul
+iEOGXZc/S8qoOJE/SoJnFhimbJ7BuECKO8euTXeQrpKVyAULTm0RSQogWMTlXHzk
+hY71+Qn0dpp4ZCQTKaFO2u6aYQ2fjJ3BlH8UK0edIUJ4cHqKfMm/TCiIHQ/jbEOp
+cy83wzZMoDNK+7r/fxdUz7CJA1r2LrbWJMOhDVgKIYE6TA==
-----END CMS-----
diff --git a/examples/pki/cms/auth_v3_token_scoped.pem b/examples/pki/cms/auth_v3_token_scoped.pem
index 50641147f..ae3f4f37c 100644
--- a/examples/pki/cms/auth_v3_token_scoped.pem
+++ b/examples/pki/cms/auth_v3_token_scoped.pem
@@ -1,123 +1,125 @@
-----BEGIN CMS-----
-MIIWmgYJKoZIhvcNAQcCoIIWizCCFocCAQExCTAHBgUrDgMCGjCCFKcGCSqGSIb3
-DQEHAaCCFJgEghSUew0KICAgICJ0b2tlbiI6IHsNCiAgICAgICAgIm1ldGhvZHMi
-OiBbDQogICAgICAgICAgICAicGFzc3dvcmQiDQogICAgICAgIF0sDQogICAgICAg
-ICJyb2xlcyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiaWQi
-OiAiZjAzZmRhOGY4YTMyNDliMmE3MGZiMWYxNzZhN2I2MzEiLA0KICAgICAgICAg
-ICAgICAgICJuYW1lIjogInJvbGUxIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
-ICAgIHsNCiAgICAgICAgICAgICAgICAiaWQiOiAiZjAzZmRhOGY4YTMyNDliMmE3
-MGZiMWYxNzZhN2I2MzEiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogInJvbGUy
-Ig0KICAgICAgICAgICAgfQ0KICAgICAgICBdLA0KICAgICAgICAiaXNzdWVkX2F0
-IjogIjIwMDItMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgImV4cGlyZXNfYXQi
-OiAiMjAzOC0wMS0xOFQyMToxNDowN1oiLA0KICAgICAgICAicHJvamVjdCI6IHsN
-CiAgICAgICAgICAgICJpZCI6ICJ0ZW5hbnRfaWQxIiwNCiAgICAgICAgICAgICJk
-b21haW4iOiB7DQogICAgICAgICAgICAgICAgImlkIjogImRvbWFpbl9pZDEiLA0K
-ICAgICAgICAgICAgICAgICJuYW1lIjogImRvbWFpbl9uYW1lMSINCiAgICAgICAg
-ICAgIH0sDQogICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAgICAgICAg
-ICAiZGVzY3JpcHRpb24iOiBudWxsLA0KICAgICAgICAgICAgIm5hbWUiOiAidGVu
-YW50X25hbWUxIg0KICAgICAgICB9LA0KICAgICAgICAiY2F0YWxvZyI6IFsNCiAg
-ICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0KICAg
-ICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQi
-OiAiM2I1ZTU1NGJjZjExNGYyNDgzZThhMWJlN2EwNTA2ZDEiLA0KICAgICAgICAg
-ICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAgICAg
+MIIW7gYJKoZIhvcNAQcCoIIW3zCCFtsCAQExDTALBglghkgBZQMEAgEwghTzBgkq
+hkiG9w0BBwGgghTkBIIU4HsNCiAgICAidG9rZW4iOiB7DQogICAgICAgICJtZXRo
+b2RzIjogWw0KICAgICAgICAgICAgInBhc3N3b3JkIg0KICAgICAgICBdLA0KICAg
+ICAgICAicm9sZXMiOiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAg
+ImlkIjogImYwM2ZkYThmOGEzMjQ5YjJhNzBmYjFmMTc2YTdiNjMxIiwNCiAgICAg
+ICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAgICAgICAgIH0sDQogICAg
+ICAgICAgICB7DQogICAgICAgICAgICAgICAgImlkIjogImYwM2ZkYThmOGEzMjQ5
+YjJhNzBmYjFmMTc2YTdiNjMxIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJy
+b2xlMiINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgImlzc3Vl
+ZF9hdCI6ICIyMDAyLTAxLTE4VDIxOjE0OjA3WiIsDQogICAgICAgICJleHBpcmVz
+X2F0IjogIjIwMzgtMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgImF1ZGl0X2lk
+cyI6IFsiVmN4VTJKWXFUOE96ZlVWdnJqRUlUUSIsICJxTlVUSUpudFR6TzEtWFVr
+NVNUeWJ3Il0sDQogICAgICAgICJwcm9qZWN0Ijogew0KICAgICAgICAgICAgImlk
+IjogInRlbmFudF9pZDEiLA0KICAgICAgICAgICAgImRvbWFpbiI6IHsNCiAgICAg
+ICAgICAgICAgICAiaWQiOiAiZG9tYWluX2lkMSIsDQogICAgICAgICAgICAgICAg
+Im5hbWUiOiAiZG9tYWluX25hbWUxIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
+ICAgICJlbmFibGVkIjogdHJ1ZSwNCiAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6
+IG51bGwsDQogICAgICAgICAgICAibmFtZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAg
+ICAgIH0sDQogICAgICAgICJjYXRhbG9nIjogWw0KICAgICAgICAgICAgew0KICAg
+ICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAg
+IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICIzYjVlNTU0YmNmMTE0
+ZjI0ODNlOGExYmU3YTA1MDZkMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAi
+aW50ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1
+cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4
+YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdp
+b24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAg
+ICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQiOiAi
+NTRhYmQyZGM0NjNjNGJhNGE3MjkxNTQ5OGY4ZWNhZDEiLA0KICAgICAgICAgICAg
+ICAgICAgICAgICAgImludGVyZmFjZSI6ICJpbnRlcm5hbCIsDQogICAgICAgICAg
ICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82
NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAg
ICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAg
ICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg
-ICAgICAgICAgImlkIjogIjU0YWJkMmRjNDYzYzRiYTRhNzI5MTU0OThmOGVjYWQx
-IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAiaW50ZXJu
-YWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3
-LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2Ei
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUi
-DQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAgICAgIHsN
-CiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICI3MGE3ZWZhNGIxYjk0MTk2
-ODM1N2NjNDNhZTE0MTllZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
-ZXJmYWNlIjogInB1YmxpYyIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJs
-IjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2
-MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9u
-IjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAg
-ICAgICAgIF0sDQogICAgICAgICAgICAgICAgImlkIjogIjU3MDdjM2ZjMGEyOTQ3
-MDNhM2M2MzhlOWNmNmE2YzNhIiwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJ2
-b2x1bWUiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogInZvbHVtZSINCiAgICAg
-ICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBv
-aW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg
-ICAgICAgICAgImlkIjogIjkyMjE3YTNiOTUzOTQ0OTI4NTliYzQ5ZmQ0NzQzODJm
-IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAiYWRtaW4i
-LA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAu
-MC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6
-ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAg
-ICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpZCI6ICJmMjA1
-NjNiZGY2NmY0ZWZhOGExZjExZDk5YjY3MmJlMSIsDQogICAgICAgICAgICAgICAg
-ICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAg
-ICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAg
-ICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
-ICAgICAgICAgICAgICAgICAgICAiaWQiOiAiMzc1ZjliYTQ1OWE0NDc3MzhmYjYw
-ZmU1ZmMyNmU5YWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFj
-ZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJo
-dHRwOi8vMTI3LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAg
-ICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0N
-CiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJpZCI6ICIxNWMy
-MWFhZTZiMjc0YThkYTUyZTBhMDY4ZTkwOGFhYyIsDQogICAgICAgICAgICAgICAg
-InR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogImdsYW5j
-ZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAg
-ICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAg
-ICAgICAgICAgICAgICAgICAgImlkIjogImVkYmQ5ZjUwZjY2NzQ2YWU5ZWQxMWRj
-M2IxYWUzNWRhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2Ui
-OiAiYWRtaW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRw
-Oi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5
-YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJl
-Z2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAg
-ICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogIjllMDNjNDZj
-ODBhMzRhMTU5Y2IzOWY1Y2IwNDk4YjkyIiwNCiAgICAgICAgICAgICAgICAgICAg
-ICAgICJpbnRlcmZhY2UiOiAiaW50ZXJuYWwiLA0KICAgICAgICAgICAgICAgICAg
+ICAgICAgICAgImlkIjogIjcwYTdlZmE0YjFiOTQxOTY4MzU3Y2M0M2FlMTQxOWVl
+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAicHVibGlj
+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4w
+LjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwN
+CiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0K
+ICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAg
+ICAgICAgICAgICAiaWQiOiAiNTcwN2MzZmMwYTI5NDcwM2EzYzYzOGU5Y2Y2YTZj
+M2EiLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQogICAgICAg
+ICAgICAgICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwNCiAgICAg
+ICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAg
+ICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQiOiAi
+OTIyMTdhM2I5NTM5NDQ5Mjg1OWJjNDlmZDQ3NDM4MmYiLA0KICAgICAgICAgICAg
+ICAgICAgICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAg
+ICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQog
+ICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAg
+ICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAg
+ICAgICAgICAgICAgICAgICAgICAgImlkIjogImYyMDU2M2JkZjY2ZjRlZmE4YTFm
+MTFkOTliNjcyYmUxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZh
+Y2UiOiAiaW50ZXJuYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6
+ICJodHRwOi8vMTI3LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAg
+ICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAg
+IH0sDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAg
+ICAgICJpZCI6ICIzNzVmOWJhNDU5YTQ0NzczOGZiNjBmZTVmYzI2ZTlhYSIsDQog
+ICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogInB1YmxpYyIsDQog
+ICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6
+OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJl
+Z2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAg
+IF0sDQogICAgICAgICAgICAgICAgImlkIjogIjE1YzIxYWFlNmIyNzRhOGRhNTJl
+MGEwNjhlOTA4YWFjIiwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpbWFnZSIs
+DQogICAgICAgICAgICAgICAgIm5hbWUiOiAiZ2xhbmNlIg0KICAgICAgICAgICAg
+fSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjog
+Ww0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAg
+ICAiaWQiOiAiZWRiZDlmNTBmNjY3NDZhZTllZDExZGMzYjFhZTM1ZGEiLA0KICAg
+ICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAg
+ICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3
+NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAg
+ICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAg
+ICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAg
+ICAgICAgICAgICAgICAgICAiaWQiOiAiOWUwM2M0NmM4MGEzNGExNTljYjM5ZjVj
+YjA0OThiOTIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6
+ICJpbnRlcm5hbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0
+dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNm
+ODliYjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAi
+cmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAg
+ICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaWQiOiAiMWRmMGI0
+NGQ5MjYzNGQ1OWJkMGUwZDYwY2Y3Y2U0MzIiLA0KICAgICAgICAgICAgICAgICAg
+ICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAgICAg
ICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNm
YmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAg
ICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAg
-fSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAg
-ICAgImlkIjogIjFkZjBiNDRkOTI2MzRkNTliZDBlMGQ2MGNmN2NlNDMyIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAicHVibGljIiwNCiAg
-ICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4
-Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAg
-ICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAg
-ICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAg
-ICAgICAgICJpZCI6ICIyZjQwNGZkYjg5MTU0YzU4OWVmYmMxMDcyNmIwMjllYyIs
-DQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIsDQogICAgICAgICAg
-ICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg
-ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAg
-ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogImE0NTAx
-ZTE0MWE0YjRlMTRiZjI4MmU3YmZmZDgxZGM1IiwNCiAgICAgICAgICAgICAgICAg
-ICAgICAgICJpbnRlcmZhY2UiOiAiYWRtaW4iLA0KICAgICAgICAgICAgICAgICAg
-ICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAg
-ICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAg
-ICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAg
-ICAgICAgICAgICAgICAgICAiaWQiOiAiM2QxN2UzMjI3YmZjNDQ4M2I1OGRlNWVh
-YTU4NGUzNjAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6
-ICJpbnRlcm5hbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0
+fQ0KICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgImlkIjogIjJm
+NDA0ZmRiODkxNTRjNTg5ZWZiYzEwNzI2YjAyOWVjIiwNCiAgICAgICAgICAgICAg
+ICAidHlwZSI6ICJjb21wdXRlIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJu
+b3ZhIg0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAg
+ICAgICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
+ICAgICAgICAgICAgICAgICAgICAiaWQiOiAiYTQ1MDFlMTQxYTRiNGUxNGJmMjgy
+ZTdiZmZkODFkYzUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFj
+ZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0
dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjMiLA0KICAgICAgICAgICAgICAgICAgICAg
ICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0s
DQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAg
-ICJpZCI6ICI4Y2Q0Yjk1NzA5MGY0Y2E1ODQyYTIyZTlhNzQwOTljZCIsDQogICAg
-ICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogInB1YmxpYyIsDQogICAg
-ICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6NTAw
-MC92MyIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lv
-bk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s
-DQogICAgICAgICAgICAgICAgImlkIjogImM1ZDkyNmQ1NjY0MjRlNGZiYTRmODBj
-Mzc5MTZjZGU1IiwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpZGVudGl0eSIs
-DQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUiDQogICAgICAgICAg
-ICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0KICAgICAgICAgICAg
-ImRvbWFpbiI6IHsNCiAgICAgICAgICAgICAgICAiaWQiOiAiZG9tYWluX2lkMSIs
-DQogICAgICAgICAgICAgICAgIm5hbWUiOiAiZG9tYWluX25hbWUxIg0KICAgICAg
-ICAgICAgfSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAg
-ICAgICAgICAgImlkIjogInVzZXJfaWQxIg0KICAgICAgICB9DQogICAgfQ0KfQ0K
-MYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD
-VQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sx
-ETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu
-c3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkq
-hkiG9w0BAQEFAASCAQCPCzpknZOfDONpHDWGrYTeyirjGGjrJem2EF2qsJ4K1x/V
-guNLX1AfRnRUC95wSpGS5VCQ+OSfSFmLjJQOnMqLZ1L2MkVfn0CIkqig19sgRZ+O
-hpi+0TpJ6XlCWRERJEICCOAHZ/M2iiiVFbFkIGtaJLw3HcXFreV+nEBuQSeIGH/H
-FjnmocYu9vy612YT47HcyQKNMaku3QBLzFTSTiGkS4ft9yT2pNMbHZsMmysaRKWl
-SfuA/DZHT6zi5D4lkxDBCexf3JAw4kOQSf/dirfDUKmIy4VPeAOuO1u86hN/coIS
-JvgAJGOVUxtZCQ9256dUvKa1pLpQAgW/Ok3oPulS
+ICJpZCI6ICIzZDE3ZTMyMjdiZmM0NDgzYjU4ZGU1ZWFhNTg0ZTM2MCIsDQogICAg
+ICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAg
+ICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMToz
+NTM1Ny92MyIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogIlJl
+Z2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAg
+ICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlkIjogIjhjZDRiOTU3
+MDkwZjRjYTU4NDJhMjJlOWE3NDA5OWNkIiwNCiAgICAgICAgICAgICAgICAgICAg
+ICAgICJpbnRlcmZhY2UiOiAicHVibGljIiwNCiAgICAgICAgICAgICAgICAgICAg
+ICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YzIiwNCiAgICAgICAg
+ICAgICAgICAgICAgICAgICJyZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAgICAg
+ICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAg
+ICAiaWQiOiAiYzVkOTI2ZDU2NjQyNGU0ZmJhNGY4MGMzNzkxNmNkZTUiLA0KICAg
+ICAgICAgICAgICAgICJ0eXBlIjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAg
+ICAibmFtZSI6ICJrZXlzdG9uZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwN
+CiAgICAgICAgInVzZXIiOiB7DQogICAgICAgICAgICAiZG9tYWluIjogew0KICAg
+ICAgICAgICAgICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAgICAgICAgICAgICAg
+ICAibmFtZSI6ICJkb21haW5fbmFtZTEiDQogICAgICAgICAgICB9LA0KICAgICAg
+ICAgICAgIm5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAgICAgICAiaWQiOiAi
+dXNlcl9pZDEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCB
+njEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQH
+DAlTdW5ueXZhbGUxEjAQBgNVBAoMCU9wZW5TdGFjazERMA8GA1UECwwIS2V5c3Rv
+bmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNV
+BAMMC1NlbGYgU2lnbmVkAgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASC
+AQAKyFuKuktH9YR3TfKG4NAEBXDkEAkWA+fVWREyEnYoCYE2YDiqrVRwpFqR6p0V
+PGRUPcDLTtPw+6p+ywNbP3F3AU0LNqjs3zl8HxvHij91CzZOQIykUcX4ToLJhBAD
+shZzSucjk5y9zTLN4bl+AX/NJ/GYT2chFVjYJUW+sbIVoT5u0V9K602OV9OAyvpY
+a0YzFmnEzplkg2U0qzZjx5b143ASQnaCtaf4rK7HCOIz11I6aaL3yhGSxnqE6yyA
+9FdYOwB14E1GWeLVx0xeM8D/qMesqANsk0WQ19LnvKB7ry5EnDCGeBRYTMR+u0B2
+gnCYSRs9m+gg1rL889d53c/q
-----END CMS-----
diff --git a/examples/pki/cms/revocation_list.pem b/examples/pki/cms/revocation_list.pem
index 0e81998b8..e37f9de4a 100644
--- a/examples/pki/cms/revocation_list.pem
+++ b/examples/pki/cms/revocation_list.pem
@@ -1,20 +1,20 @@
-----BEGIN CMS-----
-MIIDTwYJKoZIhvcNAQcCoIIDQDCCAzwCAQExCTAHBgUrDgMCGjCCAVwGCSqGSIb3
-DQEHAaCCAU0EggFJeyJyZXZva2VkIjogW3siZXhwaXJlcyI6ICIyMTEyLTA4LTE0
-VDE3OjU4OjQ4WiIsICJpZCI6ICJkYjk4ZWQyYWY2YzY3MDdiZWM2ZGM2YzY4OTI3
-ODlhMCJ9LCB7ImV4cGlyZXMiOiAiMjExMi0wOC0xNFQxNzo1ODo0OFoiLCAiaWQi
-OiAiMTVjZTA1ZmQ0OTFiNzk3OTEwNjhlZDgwYTljN2Y1ZTcifSwgeyJleHBpcmVz
-IjogIjIxMTItMDgtMTRUMTc6NTg6NDhaIiwgImlkIjogImRiOThlZDJhZjZjNjcw
-N2JlYzZkYzZjNjg5Mjc4OWEwIn0sIHsiZXhwaXJlcyI6ICIyMTEyLTA4LTE0VDE3
-OjU4OjQ4WiIsICJpZCI6ICIxNWNlMDVmZDQ5MWI3OTc5MTA2OGVkODBhOWM3ZjVl
-NyJ9XX0xggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMx
-CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5T
-dGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25l
-QG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIa
-MA0GCSqGSIb3DQEBAQUABIIBAGn4kryxJudTZYMf32gKnoNHeAXRb97CoCXiTgs2
-gu/blX/fwMdrL8GLg2puYR07XBgjo56vMsD94ZIRyhcS1lFti9veQHt7Xp8kbR8l
-nbx9fsOhMxUHLRnxioieA9T1ykP8ZvYV3hYCeXkIYhPgD4lAAAmNq99ZxBRS3csE
-DP+Xz1+UYvT6Qm/NWRuj7WIjofneIB7gT6L5irsU0qtMCQeqI3dsP9GSsy4HJvBR
-BBIzQ7fEMRCGTADbk4ml+6Dx+Jm5SO80NvinzxCjO3DbkcEG1pQ3RGVEn3gyzg2a
-ssaRU4ycbYACA99K5UzCtSj8glGXFa1cnx42nSn2LbfJP1M=
+MIIDVwYJKoZIhvcNAQcCoIIDSDCCA0QCAQExDTALBglghkgBZQMEAgEwggFcBgkq
+hkiG9w0BBwGgggFNBIIBSXsicmV2b2tlZCI6IFt7ImV4cGlyZXMiOiAiMjExMi0w
+OC0xNFQxNzo1ODo0OFoiLCAiaWQiOiAiZGI5OGVkMmFmNmM2NzA3YmVjNmRjNmM2
+ODkyNzg5YTAifSwgeyJleHBpcmVzIjogIjIxMTItMDgtMTRUMTc6NTg6NDhaIiwg
+ImlkIjogIjE1Y2UwNWZkNDkxYjc5NzkxMDY4ZWQ4MGE5YzdmNWU3In0sIHsiZXhw
+aXJlcyI6ICIyMTEyLTA4LTE0VDE3OjU4OjQ4WiIsICJpZCI6ICJkYjk4ZWQyYWY2
+YzY3MDdiZWM2ZGM2YzY4OTI3ODlhMCJ9LCB7ImV4cGlyZXMiOiAiMjExMi0wOC0x
+NFQxNzo1ODo0OFoiLCAiaWQiOiAiMTVjZTA1ZmQ0OTFiNzk3OTEwNjhlZDgwYTlj
+N2Y1ZTcifV19MYIBzjCCAcoCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2YWxlMRIwEAYDVQQKDAlP
+cGVuU3RhY2sxETAPBgNVBAsMCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlz
+dG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDDAtTZWxmIFNpZ25lZAIBETALBglg
+hkgBZQMEAgEwDQYJKoZIhvcNAQEBBQAEggEAVsD6Zy+bXz9D9ZJ32CbG4ggTisgs
+4vZw9xemVMQ9J8+3iLWE2Z+NrqO1T4Q81iu9cKZ/zTFuu99B5X9ZHE57QLrOd+Jb
+Ld3E8HYVj8ZpGQfXAcq3ybIkT2SeEddQmW+MlHHkkfu41D1dQ8jgkIcbLjpeRCFk
+GA5Zj6Xdnozos/qMLqd1o4ufJ+dQAeFH/fviLkS5fiTPK6GmhqkwBQgffkOHTo/S
+xZQeq7GhFKijg5p60AZRc1Q+WlrmkY9W0FrX7bt6iJodWBc2YSEZ5Mr7BpvIu5JH
+rg282z/D4Xwj+USzn7jvqZFlmkG9o6s6YKjsrIpnPFH92EWv0+D5NuOuOA==
-----END CMS-----
diff --git a/examples/pki/gen_cmsz.py b/examples/pki/gen_cmsz.py
index 6840c08e5..35a6a8f8c 100644
--- a/examples/pki/gen_cmsz.py
+++ b/examples/pki/gen_cmsz.py
@@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import json
import os
+from oslo_serialization import jsonutils
+
from keystoneclient.common import cms
from keystoneclient import utils
@@ -44,7 +45,7 @@ def generate_revocation_list():
'id': id,
"expires": "2112-08-14T17:58:48Z"
})
- revoked_json = json.dumps({"revoked": revoked_list})
+ revoked_json = jsonutils.dumps({"revoked": revoked_list})
with open(make_filename('cms', 'revocation_list.json'), 'w') as f:
f.write(revoked_json)
encoded = cms.pkiz_sign(revoked_json,
@@ -83,6 +84,7 @@ def generate_der_form(name):
SIGNING_KEY_FILE_NAME, cms.PKIZ_CMS_FORM)
f.write(derform)
+
for name in EXAMPLE_TOKENS:
json_file = make_filename('cms', name + '.json')
pkiz_file = make_filename('cms', name + '.pkiz')
@@ -91,12 +93,12 @@ def generate_der_form(name):
# validate the JSON
try:
- token_data = json.loads(string_data)
+ token_data = jsonutils.loads(string_data)
except ValueError as v:
raise SystemExit('%s while processing token data from %s: %s' %
(v, json_file, string_data))
- text = json.dumps(token_data).encode('utf-8')
+ text = jsonutils.dumps(token_data).encode('utf-8')
# Uncomment to record the token uncompressed,
# useful for debugging
diff --git a/examples/pki/gen_pki.sh b/examples/pki/gen_pki.sh
index 8e2b59f98..f3a3fddb0 100755
--- a/examples/pki/gen_pki.sh
+++ b/examples/pki/gen_pki.sh
@@ -42,7 +42,7 @@ function generate_ca_conf {
[ req ]
default_bits = 2048
default_keyfile = cakey.pem
-default_md = default
+default_md = sha256
prompt = no
distinguished_name = ca_distinguished_name
@@ -69,7 +69,7 @@ function generate_ssl_req_conf {
[ req ]
default_bits = 2048
default_keyfile = keystonekey.pem
-default_md = default
+default_md = sha256
prompt = no
distinguished_name = distinguished_name
@@ -90,7 +90,7 @@ function generate_cms_signing_req_conf {
[ req ]
default_bits = 2048
default_keyfile = keystonekey.pem
-default_md = default
+default_md = sha256
prompt = no
distinguished_name = distinguished_name
@@ -122,7 +122,7 @@ private_key = $dir/private/cakey.pem
default_days = 21360
default_crl_days = 30
-default_md = default
+default_md = sha256
policy = policy_any
@@ -157,14 +157,14 @@ function check_error {
function generate_ca {
echo 'Generating New CA Certificate ...'
- openssl req -x509 -newkey rsa:2048 -days 21360 -out $CERTS_DIR/cacert.pem -keyout $PRIVATE_DIR/cakey.pem -outform PEM -config ca.conf -nodes
+ openssl req -x509 -newkey rsa:2048 -sha256 -days 21360 -out $CERTS_DIR/cacert.pem -keyout $PRIVATE_DIR/cakey.pem -outform PEM -config ca.conf -nodes
check_error $?
}
function ssl_cert_req {
echo 'Generating SSL Certificate Request ...'
generate_ssl_req_conf
- openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/ssl_key.pem -keyform PEM -out ssl_req.pem -outform PEM -config ssl_req.conf -nodes
+ openssl req -newkey rsa:2048 -sha256 -keyout $PRIVATE_DIR/ssl_key.pem -keyform PEM -out ssl_req.pem -outform PEM -config ssl_req.conf -nodes
check_error $?
#openssl req -in req.pem -text -noout
}
@@ -172,7 +172,7 @@ function ssl_cert_req {
function cms_signing_cert_req {
echo 'Generating CMS Signing Certificate Request ...'
generate_cms_signing_req_conf
- openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/signing_key.pem -keyform PEM -out cms_signing_req.pem -outform PEM -config cms_signing_req.conf -nodes
+ openssl req -newkey rsa:2048 -sha256 -keyout $PRIVATE_DIR/signing_key.pem -keyform PEM -out cms_signing_req.pem -outform PEM -config cms_signing_req.conf -nodes
check_error $?
#openssl req -in req.pem -text -noout
}
diff --git a/examples/pki/private/cakey.pem b/examples/pki/private/cakey.pem
index 1c93ee18c..9c204c500 100644
--- a/examples/pki/private/cakey.pem
+++ b/examples/pki/private/cakey.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl8906EaRpibQF
-cCBWfxzLi5x/XpZ9iL6UX92NrSJxcDbaGws7s+GtjgDy8UOEonesRWTeqQEZtHpC
-3/UHHOnsA8F6ha/pq9LioqT7RehCnZCLBJwh5Ct+lclpWs15SkjJD2LTDkjox0eA
-9nOBx+XDlWyU/GAyqx5Wsvg/Kxr0iod9/4IcJdnSdUjq4v0Cxg/zNk08XPJX+F0b
-UDhgdUf7JrAmmS5LA8wphRnbIgtVsf6VN9HrbqtHAJDxh8gEfuwdhEW1df1fBtZ+
-6WMIF3IRSbIsZELFB6sqcyRj7HhMoWMkdEyPb2f8mq61MzTgE6lJGIyTRvEoFie7
-qtGADIofAgMBAAECggEBAJ47X3y2xaU7f0KQHsVafgI2JAnuDl+zusOOhJlJs8Wl
-0Sc1EgjjAxOQiqcaE96rap//qqYDTuFLjCenkuItV32KNzizr3+GLZWaruRHS6X4
-xpFG2/gUrsQL3fdudOxpP+01lmzW+f25xRvZ4VilWRabquSDntWxA0R3cOwKFbGD
-uuwbTw3pBrRfCk/2IdpQtRrvvkVIFiYT6b/zeCQzhp4RETbC0oxqcEEOIUGmimAV
-9cbwafinxCo54cOfX4JAh3j7Mp3eQUymoFk5gnmIeVe0QmpH2VkN7eItrhEvHKOk
-On7a5xvQ8s3wqPV5ZawHQcqar/p3QnGkiT6a+8LkIMECgYEA2iJ2DprTGZFRN0M7
-Yj4WLsSC3/GKK8eYsKG3TvMrmPqUDaiWLIvBoc1Le59x9eoF7Mha+WX+cAFL+GTg
-1sB+PUZZStpf1R1tGvMldvpQ+5GplUBpuQe4J0n5rCG6+5jkvSr7xO+G1B+C3GFq
-KR3iltiW5WJRVwh2k8yGvx3agyUCgYEAwsKFX82F7O+9IVud1JSQWmZMiyEK+DEX
-JRnwx4HBuWr+AZqbb0grRRb6x8JTUOD4T7DZGxTaAdfzzRjKU2sBAO8VCgaj2Auv
-5nsbvfXvrmDDCqwoaD2PMy+kgFvE0QTh65tzuGXl1IgpIYSC1JwnP6kOeUDbqE+k
-UXzfVZzDdvMCgYByk9dfJIPt0h7O4Em4+NO+DQqRhtYE2PqjDM60cZZc7IIICp2X
-GHHFA4i6jq3Vde9WyIbAqYpUWtoExzgylTm6BdGxN7NOxf4hQcZUEHepLIHfG85s
-mlloibrTZ4RH06+SjZlhgE9Z7JNYHvMcVc5HXc0k/9ep15AxYiUFDjFQ4QKBgG7i
-k089U4/X2wWgBNdgkmN1tQTNllJCmNvdzhG41dQ8j0vYe8C7BS+76qJLCGaW/6lX
-lfRuRcUg78UI5UDjPloKxR7FMwmxdb+yvdPEr2bH3qQ36nWW/u30pSMTnJYownwD
-MLp/AYCk2U4lBNwJ3+rF1ODCRY2pcnOWtg0nSL5zAoGAWRoOinogEnOodJzO7eB3
-TmL6M9QMyrAPBDsCnduJ8yW5mMUNod139YbSDxZPYwTLhK/GiHP/7OvLV5hg0s4s
-QKnNaMeEowX7dyEO4ehnbfzysxXPKLRVhWhN6MCUc71NMxqr7QkuCXAjJS6/G21+
-Im3+Xb3Scq+UZghR+jiEZF0=
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC//gLFHKshdm/9
+4GhxrVGcfpkXl9kDL/oF5ltilI9Qk5kk8RlwmnqCeTezwOgXgQ/xyVak4AqP6Dbh
+5joLWK4EZ4MlqQASLbfTjUZkwq9gLwNtwGSI31HcEWXHkR3+ux+jdTTrba/CBZLk
+BYUwCrkRyRnFzajTCazb9r+YWtxjXgIcWXfeuaJPQRknfob4m42dpgwWfJIifQRn
++d0w4nv84PquQpIKiwK4Ed9KRgnvmS1zy64XpKcnrQUd4Lik1djzAniIe2IP7kyT
+HttqmfOzOkNQ6LEigv9Zfv9QKwb3uprHPCRBJZ3N9hyezbk0ya3mShLz5lCNqE3H
+b6JFl7UbAgMBAAECggEAVCmMm03S8utRcrBB+LsqkHiqsb3+AriwWI+/tbo8DO12
+78vFBCij1bg/o8vHsi4AiFRjaAlSd/0queJLxZeNSR77TbIE9vMVp2ZB2n/Bk19o
+mF8Dc0C6SMdTn6VMydLLrsL9fMrrhhkdaFnHJeU9db97Tcu22zRdk1taZ/ZEsEXN
+5Ij4GSaylemUsdi2GKWCydDje3M60rGRWiVlMAsgyLhGRjBS0dfi2VRSbjE/Mi+d
+vrHGWyKfh/Dgmt5XdljubZE6fbogXtksBl/dvHytQIyYddSTYHWJoCHb0DhBV25V
+/m5SNTRoBeRtTy9s7UdMxTR9mpPscWCAonCZVh3nQQKBgQDqwE80+CaYInrNlZIM
+6rX3sdHgcnlP8a2gSRfkmpTQbf5os6jHBwBp3UAqTpKZd6mjrbXXel4Hj8ccZMW9
+SqReQJiJwENxhvT5Bz7YGERZbVGvchXeeQBjhOy8D+Smv85I+F+cP/7efutrzFgf
+M5mwlic5z58ijJlloGzgP4GquwKBgQDRXuJFzfbjY7DS0vgoz5Gh8GTfB/EPZkNL
+ULt22Zz6coMpZ+en8HBrc7gSlAjvf3C4MAon344VIaW6bK1tx4amuJVK3gbbk7Kg
+9YOkXUg60WaBeX9zed+eljV3LIcgRJ10Zu5rJ8ZCLgp1DTF1kh7afmqyufU5828b
+vOOpN+5pIQKBgQC7qpGnntn7tVTHFVN00A44vgcyj1E7/9D12nknYAyns8c2nKnI
+smg6OY4aREYeOfN7zlsYr9KL6P0cTdNmyE0urCVFulYwY9tjWc97oarCcwpiX6nr
++H+/D3zRu0Lnq16WJzkICIEQDhbWTr4D85Rh/yfMp5ZoYE4hWGaxvxNCEQKBgQCL
+bD4N8fworGhB3E95DdCTIDxr8SPr91N0wgw0NvG8Lal+Vz0CrrCOPX8kkAPrSNhN
+L2Bz8QDyvXdZT6ml4yqdt2ljc7rpWc+oNBY3zA6fbHZwXfIrecsaFjkAZVyOdmLL
+8wdtwAzcYUCBdgmrm2SEZ46x+fd9Ychplj2coCxZQQKBgEtdtXU93fZ6vUUTN6Rj
+DbWQPxktPClfBvxEr7jfdMLO33UziVQU9ZoXpj5fplWFtjLw09W1bNa6VYKGkcVK
+ZYCHni/J440p7v9NvHZHX8kqYkFvzs0djFXzkLTzSKk6ErDMjvWUcQq7IvB3JLNo
+xrS0SJBTBskGUKX/1OEP69B1
-----END PRIVATE KEY-----
diff --git a/examples/pki/private/signing_key.pem b/examples/pki/private/signing_key.pem
index 758c0ffe1..ddf3066d5 100644
--- a/examples/pki/private/signing_key.pem
+++ b/examples/pki/private/signing_key.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDM+VrILLl962VH
-S8EKWVzdkaOy0OoxGZ63gajM7VTm8AbgtVnYibIOnVZQuz1XbftIGNXPFhYNUypr
-LnMXrEEsnxgD4PvU/4bETG+stdricX6d1oKqsNFNR7F7zImiR/OzGhp7dONwccxf
-kfX4QHA5Ogso+XMfSdC72SRDszeCeGUcjuo/w2WSLW95SuVvcZLqE/pk3Q2TkCZ1
-8hvNfLoln43QpC469a7srUXATqOJ2mPNvL6E/wOyPefmAoCoG44lFoR3k2jZjBEI
-hstJxmH7XgvqErBzpcWd29dms8xz5PNwYdns9CIfb3GaHvQ6r5RTl37/avDrGHOW
-KOoD01xLAgMBAAECggEAaIi22qWsh+JYCW9B6NRAPyN6V8Sh2x6UykOO4cwb45b/
-+vOh+YPn0fo9vfhvxTnq0A8SY4WBA5SpanYK7kTEDEyqw7em1y7l/RB6V5t7IMb+
-6uIuS3zXkVEB3AApJSEK0Ql7/gBTydHPh+H5jnzWfujyLhhhtNBBarvH+drZcWio
-lWx8RERN4cH+3DZD/xxjH2Ff+X1XMvb8Xcup7MlWi2FtREg7LttLNWNK25iWjciP
-QwfWQIrURRJrD2IrOr9V2nuIEvRqRRBoO+pxJT2sC48NJ3hiKV2GtSQe2nRpQJ47
-f9MEsF5KVQOOn+aQ60EKOI0MpNPmpiCZ5hFvBrNuOQKBgQD6vueEdI9eJgz5YN+t
-XWdpNippv35RTD8R4bQcE6GqIUXOmtQFS2wPJLn7nisZUsGMNEs36Yl0T9iow63r
-5GNAfgzpqN1XZqaSMwAdxKmlBNYpAkVXHhv+1jN+9diDYmoj9T+3Q6Zvk5e/Liyp
-6i+TsDppwmmr2utWajhyJ7owFwKBgQDRROncTztGDYLfRcrIoYsPo79KQ8tqwd2a
-07Usch2kplTqojCUmmhMMFgV2eZPPiCjnEy2bAYh9I/oj7xG6EwApXTshZdCpivC
-rbUV64MakRTUP8IvM6PdI+apkJRsRUi/bSyIbcRlvEoCMNZhfj/5VY6w/jlwrPJj
-oBOCXBlB7QKBgQDGEbEeX1i03UfYYh6uep7qbEAaooqsu5cCkBDPMO6+TmQvLPyY
-Zhio6bEEQs/2w/lhwBk+xHqw5zXVMiWbtiB03F1k4eBeXxbrW+AWo7gCQ4zMfh+6
-Dm284wVwn9D1D/OaDevT31uEvcjb2ySq3/PPLSEnU8xXVaoa6/NEsX8Q5wKBgQCm
-2smULWBXZKJ6n00mVxdnqun0rsVcI6Mrta14+KwGAdEnG5achdivFsTE924YtLKV
-gSPxN4RUQokTprc52jHvOf1WMNYAADpYCOSfy55G6nKvIP8VX5lB00Qw4uRUx5FP
-gB7H0K2NaGmiAYqNRXqAtOUG3kyyOFMzeAjWIdTJqQKBgQCHzY1c7sS1vv7mPEkr
-6CpwoaEbZeFnWoHBA8Rd82psqfYsVJIRwk5Id8zgDSEmoEi8hQ9UrYbrFpLK77xq
-EYSxLQHTNlM0G3lyEsv/gJhwYYhdTYiW3Cx3F6Y++jyn9O/+hFMyQvuesAL7DUYE
-ptEfvzFprpQUpByXkIpuJub6fg==
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCexnPwhsvNj1jp
+pRg/gvHeisN0NWaHTs/RHboV3nHyzfsx13fUHd+X+YR3+HPI9MgMSPKn3mm45znn
+xJKBwuFvg007FMKtcexbwDx2053Eh83j6gRPMCqeKXxbmQITMT+eZ0yQvzfLdTNZ
+VKmEwDYEwgMrLcjibi7jHNN1AajvGzhswibAHXLAT6XWJH8nK1r+WaLHWh39zpmp
+D7Vspo0j0PP5TOMeRZuRmqGFKm/ZqG7rDKdLXuzDJM1mIpUqmQVh8e3bBkex6DeM
+zKmpbbQtIpyRnNMJ7rDa5Hm94nrl8FOk91d6RN8k07h8uh3GWXf/Jtzvy/RdaHcw
+51B9dD45AgMBAAECggEAVYj/6LIVlTYGZkiEmaKHfqYuyaoDBB3XIwbquuFNbcq9
+6onzihhV3l+Tl7YHWllUdBnQb9MIDY6zyUJC0xkTramEr7Ftd1cKSBt192Xldnza
+1E+75pVCQFaFIit5zLEZXtKzkr8Q5dDLyvIrKNMLxuBmKJrPv/wv0jYzTLOKONUO
+BRxEb2c13lvq/RqT4xpxU8wadk/tC4N1tvLGdUnq/+1+GcmswwChBPnYafY+pzF3
+ylyoQUtirIZ0TAkSBwZZGkZC137OPs6CmbBqxLcPT2swUSQpUSAglwG7PklRAW1u
+2Qin1gka7J3l6erIYfeJ87C7day+3+uGtlYxplMRIQKBgQDJobPdn/YZakdI4ZaH
+YNL67qtO5A410vb0Sm6UXWASAyfRq7nMG1CyWvlfTpPTeao9bBD0oKKIteW7RTo5
+mSozpKOt2Rgb3auyOkuswFbSxRuufgRDayUnyYMaHfhfp/pHEpXg/aiwNckiZ6Mi
+iOwIlLN+ytyzadfXZSrlPtVpvQKBgQDJlnD1hnOtWRgWeB4uUXzJPa9MJBK7JLRW
++FSMrUxssw14vScmLO3kV/pN1J++FMkq7Y5ZmOpy34sGc3iMaM+H4JuNCvP5SwtG
+626rOm5enH2sKd4BubiZcln5zrjgw/RV/a7aQQep4cQpaEgNoyTAu6BuU0fid6xc
+jVQJAXnILQKBgQDII7YB2vHRMGkpsqJUJovFgHqSiFSCoLF4sxkoM7dUqcUwniCC
+tOpY32yAaeLaGv4ckdQSvhAXW1Z5mLG+0oXNVTMTMVZ48oOnGa5b/18vP2/GuFdL
+BGORJrj3h6AucvI+8ffLqH10yy6m8/A+K2L+8Xtp87s2a21P5J+7ha8YkQKBgB4m
+fBqc02xX6PxjVtBCq9FFgpR2yL5ozPg9CBhKSyXu2dL3J4XULnh6mBtP89xwK25a
+PXI1Jsurl5WNa7hEbNW7yEgeHUNp7/PZfqHpiVxpN3qqgGPtrSh2K/Lq8kfbxw2d
+dat7EnRcKgSvbidsATE6XtJhblz23TayhKEcMWS5AoGBAItYfoHpgnQXk1gXal6e
+incHFVTgrUQlDKZ5UQn5/HvK1Gb3mAtPbLWJZ2Ej70lW5BQnBrCLI8188Z6PJY3w
+8KJ4T2KOu+9qClnezLy2A+bZ+MU+XZrVv+65vjJ5oGhARmRLmYlasBmxwUEEKqlO
+ovIe7UVLD9CyaB+MFxFpFwE6
-----END PRIVATE KEY-----
diff --git a/examples/pki/private/ssl_key.pem b/examples/pki/private/ssl_key.pem
index 363ce94bd..d339ea213 100644
--- a/examples/pki/private/ssl_key.pem
+++ b/examples/pki/private/ssl_key.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDL06AaJROwHPgJ
-9tcySSBepzJ81jYars2sMvLjyuvdiIBbhWvbS/a9Tw3WgL8H6OALkHiOU/f0A6Rp
-v8dGDIDsxZQVjT/4SLaQUOeDM+9bfkKHpSd9G3CsdSSZgOH08n+MyZ7slPHfUHLY
-Wso0SJD0vAi1gmGDlSM/mmhhHTpCDGo6Wbwqare6JNeTCGJTJYwrxtoMCh/W1Zrs
-lPC5lFvlHD7KBBf6IU2A8Xh/dUa3p5pmQeHPW8Em90DzIB1qH0DRXl3KANc24xYR
-R45pPCVkk6vFsy6P0JwwpnkszB+LcK6CEsJhLsOYvQFsiQfSZ8m7YGhgrMLxtop4
-YEPirGGrAgMBAAECggEATwvbY0hNwlb5uqOIAXBqpUqiQdexU9fG26lGmSDxKBDv
-9o5frcRgBDrMWwvDCgY+HT4CAvB9kJx4/qnpVjkzJp/ZNiJ5VIiehIlbv348rXbh
-xkk+bz5dDATCFOXuu1fwL2FhyM5anwhMAav0DyK1VLQ3jGzr9GO6L8hqAn+bQFFu
-6ngiODwfhBMl5aRoL9UOBEhccK07znrH0JGRz+3+5Cdz59Xw91Bv210LhNNDL58+
-0JD0N+YztVOQd2bgwo0bQbOEijzmYq+0mjoqAnJh1/++y7PlIPs0AnPgqSnFPx9+
-6FsQEVRgk5Uq3kvPLaP4nT2y6MDZSp+ujYldvJhyQQKBgQDuX2pZIJMZ4aFnkG+K
-TmJ5wsLa/u9an0TmvAL9RLtBpVpQNKD8cQ+y8PUZavXDbAIt5NWqZVnTbCR79Dnd
-mZKblwcHhtsyA5f89el5KcxY2BREWdHdTnJpNd7XRlUECmzvX1zGj77lA982PhII
-yflRBRV3vqLkgC8vfoYgRyRElwKBgQDa5jnLdx/RahfYMOgn1HE5o4hMzLR4Y0Dd
-+gELshcUbPqouoP5zOb8WOagVJIgZVOSN+/VqbilVYrqRiNTn2rnoxs+HHRdaJNN
-3eXllD4J2HfC2BIj1xSpIdyh2XewAJqw9IToHNB29QUhxOtgwseHciPG6JaKH2ik
-kqGKH/EKDQKBgFFAftygiOPCkCTgC9UmANUmOQsy6N2H+pF3tsEj43xt44oBVnqW
-A1boYXNnjRwuvdNs9BPf9i1l6E3EItFRXrLgWQoMwryakv0ryYh+YeRKyyW9RBbe
-fYs1TJ8unx4Ae79gTxxztQsVNcmkgLs0NWKTjAzEE3w14V+cDhYEie1DAoGBAJdI
-V5cLrBzBstsB6eBlDR9lqrRRIUS2a8U9m+1mVlcSfiWQSdehSd4K3tDdwePLw3ch
-W4qR8n+pYAlLEe0gFvUhn5lMdwt7U5qUCeehjUKmrRYm2FqWsbu2IFJnBjXIJSC4
-zQXRrC0aZ0KQYpAL7XPpaVp1slyhGmPqxuO78Y0dAoGBAMHo3EIMwu9rfuGwFodr
-GFsOZhfJqgo5GDNxxf89Q9WWpMDTCdX+wdBTrN/wsMbBuwIDHrUuRnk6D5CWRjSk
-/ikCgHN3kOtrbL8zzqRomGAIIWKYGFEIGe1GHVGo5r//HXHdPxFXygvruQ/xbOA4
-RGvmDiji8vVDq7Shho8I6KuT
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD1i9+ydZSypNAk
+kVXdzIqZ8E62cqH7i0JGVGBuGdH8ZVF3MDcbi8VwqfNRWoWn9mrJUp5HYDV9t5WX
+z25Ej4EnqlJ3WLZvC1e+ldDIInmiULic3iIAgrWbumU3XNLHska/smoVJuLIuFUx
+EfRpwGOpguOzAO1M6BKCSwr+TBLYJZxc3F7v1vtwNhisyE5S2H6Q49K0UXHTPjp+
+fLZAHQ5+Yxqwf0KAJqAD3vMo8EwxXlgJu8pQyjjxwtrwnN2WHYoJGt/OOdkLBbzd
+upWH9CGcxeVc5hSJ1hEKuYS8AOZIeH6q2MKwT+QiepBsVfuy1JFt4raLht/RcX/W
+R8lIAzoFAgMBAAECggEAQbeB0z1s4rMBkgfjt0z6+2A5cNMVT0FiJ3iFpnH6pVZo
+i0G4PgMWgKS7nlZf1yg4RFF8UxYIuvDbdJnrpSXTJ06Ka66uhOHARh3KlwXDEBIS
+lslMyF4zRM6KMFsDfrbUAJI7mhWiNJ5BDrUDeRookkGZt1rUJ/UknwJ+mri5gmdo
+UYyHuelIcVZfX6mkDCKrVHCCNbdnUgWOkXtPi25n4lqjolwEeBx5y4cu4z6tkqxM
+2hcnKUyj0YKScnhnTqprkbiMpPST4y8I190Q3Eo0Q8w9hvgEUa1xezfVzICScUjG
+VXid7aRyq7sXGmCMWyMUAvc4+5/qanreEU1686CrMQKBgQD7FDKV1pcWGJMoL5VI
+xiJ8jpDpnRIL940732ODjCQRgH4K9u40OmZ36W880q6o5ZXLLoWQIYZf5Hs1lq7f
+3djqHFqqXtW7P7JU3mW5n/ejbMHlxra4uoTkjR6wUF+g2kW2y4ysI/t8HxSeaVjO
+E4cJfoaNufgmgpeKa1QnLrMpqwKBgQD6W+qgx7w2dBXSkYBDhjDoRrCwmqOuWKwG
+DMTDrlbu2j7hag6Xdy92CqjGAYXfhny4bpCkFLRjyrDZS4a/cObGKYYG4jVXTYfj
+5cqLUiLmQFrZiK0uA7ek+qMp06FJX45iyECJlXX4gNU8e/WMfujlFLwjZ+72znQE
+iTMW5xxbDwKBgEBa1vRtAmDZf66HM75peqFucVpPtjZ3By5XfcxT+VK7GpN442lj
+pqwJm0d9wOLtpc1kaTuePDEMAUClFMGwvU6UYfDVSfcqxmzWbEB97h1nXPOmUWNb
++4ARY9JRZ5F1IPVPiwj8WBNibAiGfAqmGrCmS5q8FgzY4DrMc89vOuDtAoGBAJfe
+aB6t6ssxcgdwwdi0LzjHoOkQdVgObBOjbTyypgNwGpLMrhtNblnxr12lkNr+Duwm
+DdGqyZ57VvoJaaz5xNPSXn4QfIEAA/3H6CzJX2hDA5lP4pW2JZGLhKybtwv2Tj43
+8YZERvK+3Bs7qsFWPtqv0Ey+AGRw6knSHE65VScbAoGBAPUwAUmBZ6F22M6ftNL7
+G/qZJsP6OmDSyvJDN9SXiLvbpXQVd6RrZrni6xzwKWAFncFMVo+HWmeAavM8zxsc
+a/XVSVvRj0kwg94HotHCF7/nHqYIqyF7hLZipdIphVGXx+c8dbKeVg0fgTnLRkzx
+tbxgs3HWa6pgQvxtVAN4Jl3W
-----END PRIVATE KEY-----
diff --git a/keystoneclient/access.py b/keystoneclient/access.py
index f8174f618..a93da0a1e 100644
--- a/keystoneclient/access.py
+++ b/keystoneclient/access.py
@@ -554,9 +554,9 @@ def scoped(self):
'scoped is deprecated as of the 1.7.0 release in favor of '
'project_scoped and may be removed in the 2.0.0 release.',
DeprecationWarning)
- if ('serviceCatalog' in self
- and self['serviceCatalog']
- and 'tenant' in self['token']):
+ if ('serviceCatalog' in self and
+ self['serviceCatalog'] and
+ 'tenant' in self['token']):
return True
return False
diff --git a/keystoneclient/auth/__init__.py b/keystoneclient/auth/__init__.py
index eeae768fa..c9acef819 100644
--- a/keystoneclient/auth/__init__.py
+++ b/keystoneclient/auth/__init__.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+# flake8: noqa: F405
from keystoneclient.auth.base import * # noqa
from keystoneclient.auth.cli import * # noqa
diff --git a/keystoneclient/auth/base.py b/keystoneclient/auth/base.py
index 0036b8cfe..b6753cdf1 100644
--- a/keystoneclient/auth/base.py
+++ b/keystoneclient/auth/base.py
@@ -14,7 +14,6 @@
from debtcollector import removals
from keystoneauth1 import plugin
-import six
import stevedore
from keystoneclient import exceptions
@@ -292,7 +291,7 @@ def register_argparse_arguments(cls, parser):
# select the first ENV that is not false-y or return None
env_vars = (os.environ.get(e) for e in envs)
- default = six.next(six.moves.filter(None, env_vars), None)
+ default = next(filter(None, env_vars), None)
parser.add_argument(*args,
default=default or opt.default,
diff --git a/keystoneclient/auth/identity/base.py b/keystoneclient/auth/identity/base.py
index 53a840828..b27d349e6 100644
--- a/keystoneclient/auth/identity/base.py
+++ b/keystoneclient/auth/identity/base.py
@@ -16,7 +16,6 @@
import warnings
from oslo_config import cfg
-import six
from keystoneclient import _discover
from keystoneclient.auth import base
@@ -31,8 +30,7 @@ def get_options():
]
-@six.add_metaclass(abc.ABCMeta)
-class BaseIdentityPlugin(base.BaseAuthPlugin):
+class BaseIdentityPlugin(base.BaseAuthPlugin, metaclass=abc.ABCMeta):
# we count a token as valid (not needing refreshing) if it is valid for at
# least this many seconds before the token expiry time
diff --git a/keystoneclient/auth/identity/generic/base.py b/keystoneclient/auth/identity/generic/base.py
index 98680ef91..1cf3e0a9a 100644
--- a/keystoneclient/auth/identity/generic/base.py
+++ b/keystoneclient/auth/identity/generic/base.py
@@ -12,10 +12,9 @@
import abc
import logging
+import urllib.parse as urlparse
from oslo_config import cfg
-import six
-import six.moves.urllib.parse as urlparse
from keystoneclient import _discover
from keystoneclient.auth.identity import base
@@ -42,8 +41,7 @@ def get_options():
]
-@six.add_metaclass(abc.ABCMeta)
-class BaseGenericPlugin(base.BaseIdentityPlugin):
+class BaseGenericPlugin(base.BaseIdentityPlugin, metaclass=abc.ABCMeta):
"""An identity plugin that is not version dependent.
Internally we will construct a version dependent plugin with the resolved
diff --git a/keystoneclient/auth/identity/v2.py b/keystoneclient/auth/identity/v2.py
index add1da4f5..b2ecb4b59 100644
--- a/keystoneclient/auth/identity/v2.py
+++ b/keystoneclient/auth/identity/v2.py
@@ -14,7 +14,6 @@
import logging
from oslo_config import cfg
-import six
from keystoneclient import access
from keystoneclient.auth.identity import base
@@ -24,8 +23,7 @@
_logger = logging.getLogger(__name__)
-@six.add_metaclass(abc.ABCMeta)
-class Auth(base.BaseIdentityPlugin):
+class Auth(base.BaseIdentityPlugin, metaclass=abc.ABCMeta):
"""Identity V2 Authentication Plugin.
:param string auth_url: Identity service endpoint for authorization.
diff --git a/keystoneclient/auth/identity/v3/__init__.py b/keystoneclient/auth/identity/v3/__init__.py
index f25bf5e22..abbaa658d 100644
--- a/keystoneclient/auth/identity/v3/__init__.py
+++ b/keystoneclient/auth/identity/v3/__init__.py
@@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+# flake8: noqa: F405
+
from keystoneclient.auth.identity.v3.base import * # noqa
from keystoneclient.auth.identity.v3.federated import * # noqa
from keystoneclient.auth.identity.v3.password import * # noqa
diff --git a/keystoneclient/auth/identity/v3/base.py b/keystoneclient/auth/identity/v3/base.py
index 51d16ea74..c055d4ff7 100644
--- a/keystoneclient/auth/identity/v3/base.py
+++ b/keystoneclient/auth/identity/v3/base.py
@@ -11,11 +11,10 @@
# under the License.
import abc
-import json
import logging
from oslo_config import cfg
-import six
+from oslo_serialization import jsonutils
from keystoneclient import access
from keystoneclient.auth.identity import base
@@ -27,8 +26,7 @@
__all__ = ('Auth', 'AuthMethod', 'AuthConstructor', 'BaseAuth')
-@six.add_metaclass(abc.ABCMeta)
-class BaseAuth(base.BaseIdentityPlugin):
+class BaseAuth(base.BaseIdentityPlugin, metaclass=abc.ABCMeta):
"""Identity V3 Authentication Plugin.
:param string auth_url: Identity service endpoint for authentication.
@@ -189,7 +187,7 @@ def get_auth_ref(self, session, **kwargs):
authenticated=False, log=False, **rkwargs)
try:
- _logger.debug(json.dumps(resp.json()))
+ _logger.debug(jsonutils.dumps(resp.json()))
resp_data = resp.json()['token']
except (KeyError, ValueError):
raise exceptions.InvalidResponse(response=resp)
@@ -198,8 +196,7 @@ def get_auth_ref(self, session, **kwargs):
**resp_data)
-@six.add_metaclass(abc.ABCMeta)
-class AuthMethod(object):
+class AuthMethod(object, metaclass=abc.ABCMeta):
"""One part of a V3 Authentication strategy.
V3 Tokens allow multiple methods to be presented when authentication
@@ -243,8 +240,7 @@ def get_auth_data(self, session, auth, headers, **kwargs):
pass # pragma: no cover
-@six.add_metaclass(abc.ABCMeta)
-class AuthConstructor(Auth):
+class AuthConstructor(Auth, metaclass=abc.ABCMeta):
"""Abstract base class for creating an Auth Plugin.
The Auth Plugin created contains only one authentication method. This
diff --git a/keystoneclient/auth/identity/v3/federated.py b/keystoneclient/auth/identity/v3/federated.py
index 97d83e8f9..755e7f51b 100644
--- a/keystoneclient/auth/identity/v3/federated.py
+++ b/keystoneclient/auth/identity/v3/federated.py
@@ -13,7 +13,6 @@
import abc
from oslo_config import cfg
-import six
from keystoneclient.auth.identity.v3 import base
from keystoneclient.auth.identity.v3 import token
@@ -21,8 +20,7 @@
__all__ = ('FederatedBaseAuth',)
-@six.add_metaclass(abc.ABCMeta)
-class FederatedBaseAuth(base.BaseAuth):
+class FederatedBaseAuth(base.BaseAuth, metaclass=abc.ABCMeta):
rescoping_plugin = token.Token
diff --git a/keystoneclient/base.py b/keystoneclient/base.py
index 67edfb4c5..4f3ed227a 100644
--- a/keystoneclient/base.py
+++ b/keystoneclient/base.py
@@ -20,18 +20,34 @@
import abc
import copy
import functools
+import urllib
import warnings
from keystoneauth1 import exceptions as ksa_exceptions
from keystoneauth1 import plugin
from oslo_utils import strutils
-import six
-from six.moves import urllib
from keystoneclient import exceptions as ksc_exceptions
from keystoneclient.i18n import _
+class Response(object):
+
+ def __init__(self, http_response, data):
+ self.request_ids = []
+ if isinstance(http_response, list):
+ # http_response is a list of in case
+ # of pagination
+ for resp_obj in http_response:
+ # Extract 'x-openstack-request-id' from headers
+ self.request_ids.append(resp_obj.headers.get(
+ 'x-openstack-request-id'))
+ else:
+ self.request_ids.append(http_response.headers.get(
+ 'x-openstack-request-id'))
+ self.data = data
+
+
def getid(obj):
"""Return id if argument is a Resource.
@@ -101,6 +117,11 @@ def api(self):
'may be removed in the 2.0.0 release', DeprecationWarning)
return self.client
+ def _prepare_return_value(self, http_response, data):
+ if self.client.include_metadata:
+ return Response(http_response, data)
+ return data
+
def _list(self, url, response_key, obj_class=None, body=None, **kwargs):
"""List the collection.
@@ -131,7 +152,8 @@ def _list(self, url, response_key, obj_class=None, body=None, **kwargs):
# are already returned in a list (so simply utilize that list)
pass
- return [obj_class(self, res, loaded=True) for res in data if res]
+ return self._prepare_return_value(
+ resp, [obj_class(self, res, loaded=True) for res in data if res])
def _get(self, url, response_key, **kwargs):
"""Get an object from collection.
@@ -142,7 +164,8 @@ def _get(self, url, response_key, **kwargs):
:param kwargs: Additional arguments will be passed to the request.
"""
resp, body = self.client.get(url, **kwargs)
- return self.resource_class(self, body[response_key], loaded=True)
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body[response_key], loaded=True))
def _head(self, url, **kwargs):
"""Retrieve request headers for an object.
@@ -151,7 +174,7 @@ def _head(self, url, **kwargs):
:param kwargs: Additional arguments will be passed to the request.
"""
resp, body = self.client.head(url, **kwargs)
- return resp.status_code == 204
+ return self._prepare_return_value(resp, resp.status_code == 204)
def _post(self, url, body, response_key, return_raw=False, **kwargs):
"""Create an object.
@@ -168,7 +191,8 @@ def _post(self, url, body, response_key, return_raw=False, **kwargs):
resp, body = self.client.post(url, body=body, **kwargs)
if return_raw:
return body[response_key]
- return self.resource_class(self, body[response_key])
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body[response_key]))
def _put(self, url, body=None, response_key=None, **kwargs):
"""Update an object with PUT method.
@@ -184,9 +208,15 @@ def _put(self, url, body=None, response_key=None, **kwargs):
# PUT requests may not return a body
if body is not None:
if response_key is not None:
- return self.resource_class(self, body[response_key])
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body[response_key]))
else:
- return self.resource_class(self, body)
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body))
+ # In some cases (e.g. 'add_endpoint_to_project' from endpoint_filters
+ # resource), PUT request may not return a body so return None as
+ # response along with request_id if include_metadata is True.
+ return self._prepare_return_value(resp, body)
def _patch(self, url, body=None, response_key=None, **kwargs):
"""Update an object with PATCH method.
@@ -200,9 +230,11 @@ def _patch(self, url, body=None, response_key=None, **kwargs):
"""
resp, body = self.client.patch(url, body=body, **kwargs)
if response_key is not None:
- return self.resource_class(self, body[response_key])
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body[response_key]))
else:
- return self.resource_class(self, body)
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body))
def _delete(self, url, **kwargs):
"""Delete an object.
@@ -210,7 +242,8 @@ def _delete(self, url, **kwargs):
:param url: a partial URL, e.g., '/servers/my-server'
:param kwargs: Additional arguments will be passed to the request.
"""
- return self.client.delete(url, **kwargs)
+ resp, body = self.client.delete(url, **kwargs)
+ return resp, self._prepare_return_value(resp, body)
def _update(self, url, body=None, response_key=None, method="PUT",
**kwargs):
@@ -225,11 +258,13 @@ def _update(self, url, body=None, response_key=None, method="PUT",
% method)
# PUT requests may not return a body
if body:
- return self.resource_class(self, body[response_key])
+ return self._prepare_return_value(
+ resp, self.resource_class(self, body[response_key]))
+ else:
+ return self._prepare_return_value(resp, body)
-@six.add_metaclass(abc.ABCMeta)
-class ManagerWithFind(Manager):
+class ManagerWithFind(Manager, metaclass=abc.ABCMeta):
"""Manager with additional `find()`/`findall()` methods."""
@abc.abstractmethod
@@ -243,16 +278,20 @@ def find(self, **kwargs):
the Python side.
"""
rl = self.findall(**kwargs)
- num = len(rl)
- if num == 0:
+ if self.client.include_metadata:
+ base_response = rl
+ rl = rl.data
+ base_response.data = rl[0]
+
+ if len(rl) == 0:
msg = _("No %(name)s matching %(kwargs)s.") % {
'name': self.resource_class.__name__, 'kwargs': kwargs}
raise ksa_exceptions.NotFound(404, msg)
- elif num > 1:
+ elif len(rl) > 1:
raise ksc_exceptions.NoUniqueMatch
else:
- return rl[0]
+ return base_response if self.client.include_metadata else rl[0]
def findall(self, **kwargs):
"""Find all items with attributes matching ``**kwargs``.
@@ -263,15 +302,23 @@ def findall(self, **kwargs):
found = []
searches = kwargs.items()
- for obj in self.list():
- try:
- if all(getattr(obj, attr) == value
- for (attr, value) in searches):
- found.append(obj)
- except AttributeError:
- continue
+ def _extract_data(objs, response_data):
+ for obj in objs:
+ try:
+ if all(getattr(obj, attr) == value
+ for (attr, value) in searches):
+ response_data.append(obj)
+ except AttributeError:
+ continue
+ return response_data
+
+ objs = self.list()
+ if self.client.include_metadata:
+ # 'objs' is the object of 'Response' class.
+ objs.data = _extract_data(objs.data, found)
+ return objs
- return found
+ return _extract_data(objs, found)
class CrudManager(Manager):
@@ -370,6 +417,16 @@ def build_key_only_query(self, params_list):
@filter_kwargs
def list(self, fallback_to_auth=False, **kwargs):
+
+ def return_resp(resp, include_metadata=False):
+ base_response = None
+ list_data = resp
+ if include_metadata:
+ base_response = resp
+ list_data = resp.data
+ base_response.data = list_data
+ return base_response if include_metadata else list_data
+
if 'id' in kwargs.keys():
# Ensure that users are not trying to call things like
# ``domains.list(id='default')`` when they should have used
@@ -386,15 +443,16 @@ def list(self, fallback_to_auth=False, **kwargs):
try:
query = self._build_query(kwargs)
url_query = '%(url)s%(query)s' % {'url': url, 'query': query}
- return self._list(
- url_query,
- self.collection_key)
+ list_resp = self._list(url_query, self.collection_key)
+ return return_resp(list_resp,
+ include_metadata=self.client.include_metadata)
except ksa_exceptions.EmptyCatalog:
if fallback_to_auth:
- return self._list(
- url_query,
- self.collection_key,
- endpoint_filter={'interface': plugin.AUTH_INTERFACE})
+ list_resp = self._list(url_query, self.collection_key,
+ endpoint_filter={
+ 'interface': plugin.AUTH_INTERFACE})
+ return return_resp(
+ list_resp, include_metadata=self.client.include_metadata)
else:
raise
@@ -433,6 +491,11 @@ def find(self, **kwargs):
url_query,
self.collection_key)
+ if self.client.include_metadata:
+ base_response = elements
+ elements = elements.data
+ base_response.data = elements[0]
+
if not elements:
msg = _("No %(name)s matching %(kwargs)s.") % {
'name': self.resource_class.__name__, 'kwargs': kwargs}
@@ -440,7 +503,8 @@ def find(self, **kwargs):
elif len(elements) > 1:
raise ksc_exceptions.NoUniqueMatch
else:
- return elements[0]
+ return (base_response if self.client.include_metadata
+ else elements[0])
class Resource(object):
@@ -489,7 +553,7 @@ def _add_details(self, info):
except UnicodeEncodeError:
# This happens when we're running with Python version that
# does not support Unicode identifiers (e.g. Python 2.7).
- # In that case we can't help but not set this attrubute;
+ # In that case we can't help but not set this attribute;
# it'll be available in a dict representation though
pass
self._info[k] = v
@@ -498,7 +562,7 @@ def _add_details(self, info):
pass
def __getattr__(self, k):
- """Checking attrbiute existence."""
+ """Checking attribute existence."""
if k not in self.__dict__:
# NOTE(bcwaldon): disallow lazy-loading if already loaded once
if not self.is_loaded():
diff --git a/keystoneclient/common/cms.py b/keystoneclient/common/cms.py
index 9c3e0bdfb..2ee8b52ae 100644
--- a/keystoneclient/common/cms.py
+++ b/keystoneclient/common/cms.py
@@ -26,7 +26,6 @@
import zlib
from debtcollector import removals
-import six
from keystoneclient import exceptions
from keystoneclient.i18n import _
@@ -38,7 +37,8 @@
PKIZ_PREFIX = 'PKIZ_'
PKIZ_CMS_FORM = 'DER'
PKI_ASN1_FORM = 'PEM'
-DEFAULT_TOKEN_DIGEST_ALGORITHM = 'sha256'
+# Adding nosec since this fails bandit B105, 'Possible hardcoded password'.
+DEFAULT_TOKEN_DIGEST_ALGORITHM = 'sha256' # nosec
# The openssl cms command exits with these status codes.
@@ -115,7 +115,7 @@ def _process_communicate_handle_oserror(process, data, files):
retcode, err = _check_files_accessible(files)
if process.stderr:
msg = process.stderr.read()
- if isinstance(msg, six.binary_type):
+ if isinstance(msg, bytes):
msg = msg.decode('utf-8')
if err:
err = (_('Hit OSError in '
@@ -132,7 +132,7 @@ def _process_communicate_handle_oserror(process, data, files):
else:
retcode = process.poll()
if err is not None:
- if isinstance(err, six.binary_type):
+ if isinstance(err, bytes):
err = err.decode('utf-8')
return output, err, retcode
@@ -161,8 +161,8 @@ def cms_verify(formatted, signing_cert_file_name, ca_file_name,
properly.
"""
_ensure_subprocess()
- if isinstance(formatted, six.string_types):
- data = bytearray(formatted, _encoding_for_form(inform))
+ if isinstance(formatted, str):
+ data = bytes(formatted, _encoding_for_form(inform))
else:
data = formatted
process = subprocess.Popen(['openssl', 'cms', '-verify',
@@ -355,8 +355,8 @@ def cms_sign_data(data_to_sign, signing_cert_file_name, signing_key_file_name,
"""
_ensure_subprocess()
- if isinstance(data_to_sign, six.string_types):
- data = bytearray(data_to_sign, encoding='utf-8')
+ if isinstance(data_to_sign, str):
+ data = bytes(data_to_sign, encoding='utf-8')
else:
data = data_to_sign
process = subprocess.Popen(['openssl', 'cms', '-sign',
@@ -436,7 +436,7 @@ def cms_hash_token(token_id, mode='md5'):
return None
if is_asn1_token(token_id) or is_pkiz(token_id):
hasher = hashlib.new(mode)
- if isinstance(token_id, six.text_type):
+ if isinstance(token_id, str):
token_id = token_id.encode('utf-8')
hasher.update(token_id)
return hasher.hexdigest()
diff --git a/keystoneclient/contrib/auth/v3/saml2.py b/keystoneclient/contrib/auth/v3/saml2.py
index 85beabb2c..acf3f0513 100644
--- a/keystoneclient/contrib/auth/v3/saml2.py
+++ b/keystoneclient/contrib/auth/v3/saml2.py
@@ -11,11 +11,11 @@
# under the License.
import datetime
+import urllib.parse
import uuid
from lxml import etree # nosec(cjschaef): used to create xml, not parse it
from oslo_config import cfg
-from six.moves import urllib
from keystoneclient import access
from keystoneclient.auth.identity import v3
diff --git a/keystoneclient/contrib/ec2/utils.py b/keystoneclient/contrib/ec2/utils.py
index 1ef5df4da..f7cefa1bf 100644
--- a/keystoneclient/contrib/ec2/utils.py
+++ b/keystoneclient/contrib/ec2/utils.py
@@ -20,9 +20,7 @@
import hashlib
import hmac
import re
-
-import six
-from six.moves import urllib
+import urllib.parse
from keystoneclient.i18n import _
@@ -106,9 +104,9 @@ def generate(self, credentials):
@staticmethod
def _get_utf8_value(value):
"""Get the UTF8-encoded version of a value."""
- if not isinstance(value, (six.binary_type, six.text_type)):
+ if not isinstance(value, (str, bytes)):
value = str(value)
- if isinstance(value, six.text_type):
+ if isinstance(value, str):
return value.encode('utf-8')
else:
return value
@@ -121,9 +119,7 @@ def _calc_signature_0(self, params):
def _calc_signature_1(self, params):
"""Generate AWS signature version 1 string."""
- keys = list(params)
- keys.sort(key=six.text_type.lower)
- for key in keys:
+ for key in sorted(params, key=str.lower):
self.hmac.update(key.encode('utf-8'))
val = self._get_utf8_value(params[key])
self.hmac.update(val)
@@ -225,7 +221,7 @@ def canonical_header_str():
# port if we detect an old boto version. FIXME: remove when all
# distros package boto >= 2.9.3, this is a transitional workaround
user_agent = headers_lower.get('user-agent', '')
- strip_port = re.match('Boto/2\.[0-9]\.[0-2]', user_agent)
+ strip_port = re.match(r'Boto/2\.[0-9]\.[0-2]', user_agent)
header_list = []
sh_str = auth_param('SignedHeaders')
diff --git a/keystoneclient/discover.py b/keystoneclient/discover.py
index 0c129b3a0..16174162d 100644
--- a/keystoneclient/discover.py
+++ b/keystoneclient/discover.py
@@ -232,8 +232,8 @@ def raw_version_data(self, unstable=False, **kwargs):
>>> disc = discover.Discovery(auth_url='http://localhost:5000')
>>> disc.raw_version_data()
[{'id': 'v3.0',
- 'links': [{'href': u'http://127.0.0.1:5000/v3/',
- 'rel': u'self'}],
+ 'links': [{'href': 'http://127.0.0.1:5000/v3/',
+ 'rel': 'self'}],
'media-types': [
{'base': 'application/json',
'type': 'application/vnd.openstack.identity-v3+json'},
@@ -242,11 +242,11 @@ def raw_version_data(self, unstable=False, **kwargs):
'status': 'stable',
'updated': '2013-03-06T00:00:00Z'},
{'id': 'v2.0',
- 'links': [{'href': u'http://127.0.0.1:5000/v2.0/',
- 'rel': u'self'},
- {'href': u'...',
- 'rel': u'describedby',
- 'type': u'application/pdf'}],
+ 'links': [{'href': 'http://127.0.0.1:5000/v2.0/',
+ 'rel': 'self'},
+ {'href': '...',
+ 'rel': 'describedby',
+ 'type': 'application/pdf'}],
'media-types': [
{'base': 'application/json',
'type': 'application/vnd.openstack.identity-v2.0+json'},
diff --git a/keystoneclient/exceptions.py b/keystoneclient/exceptions.py
index 5b06be9bb..034e5c977 100644
--- a/keystoneclient/exceptions.py
+++ b/keystoneclient/exceptions.py
@@ -376,6 +376,7 @@ def __init__(self, output):
msg = _('Unable to sign or verify data.')
super(CMSError, self).__init__(msg)
+
EmptyCatalog = _exc.EmptyCatalog
"""The service catalog is empty.
@@ -398,6 +399,7 @@ def __init__(self, output):
class MethodNotImplemented(ClientException):
"""Method not implemented by the keystoneclient API."""
+
MissingAuthPlugin = _exc.MissingAuthPlugin
"""An authenticated request is required but no plugin available.
diff --git a/keystoneclient/fixture/__init__.py b/keystoneclient/fixture/__init__.py
index 768f96912..92034a0da 100644
--- a/keystoneclient/fixture/__init__.py
+++ b/keystoneclient/fixture/__init__.py
@@ -28,6 +28,8 @@
"""
+# flake8: noqa: F405
+
import warnings
from keystoneclient.fixture.discovery import * # noqa
diff --git a/keystoneclient/generic/client.py b/keystoneclient/generic/client.py
index e6b58339b..7c82c195f 100644
--- a/keystoneclient/generic/client.py
+++ b/keystoneclient/generic/client.py
@@ -14,9 +14,9 @@
# under the License.
import logging
+import urllib.parse as urlparse
from debtcollector import removals
-from six.moves.urllib import parse as urlparse
from keystoneclient import exceptions
from keystoneclient import httpclient
diff --git a/keystoneclient/httpclient.py b/keystoneclient/httpclient.py
index 50d393ad0..8c38d1596 100644
--- a/keystoneclient/httpclient.py
+++ b/keystoneclient/httpclient.py
@@ -17,6 +17,7 @@
# under the License.
"""OpenStack Client interface. Handles the REST calls and responses."""
+import importlib.metadata
import logging
import warnings
@@ -24,7 +25,7 @@
from debtcollector import renames
from keystoneauth1 import adapter
from oslo_serialization import jsonutils
-import pkg_resources
+import packaging.version
import requests
try:
@@ -33,9 +34,10 @@
# NOTE(sdague): The conditional keyring import needs to only
# trigger if it's a version of keyring that's supported in global
# requirements. Update _min and _bad when that changes.
- keyring_v = pkg_resources.parse_version(
- pkg_resources.get_distribution("keyring").version)
- keyring_min = pkg_resources.parse_version('5.5.1')
+ keyring_v = packaging.version.Version(
+ importlib.metadata.version('keyring')
+ )
+ keyring_min = packaging.version.Version('5.5.1')
# This is a list of versions, e.g., pkg_resources.parse_version('3.3')
keyring_bad = []
@@ -43,7 +45,7 @@
import keyring
else:
keyring = None
-except (ImportError, pkg_resources.DistributionNotFound):
+except (ImportError, importlib.metadata.PackageNotFoundError):
keyring = None
pickle = None
@@ -221,7 +223,7 @@ class HTTPClient(baseclient.Client, base.BaseAuthPlugin):
:param string service_name: The default service_name for URL discovery.
default: None (optional)
:param string interface: The default interface for URL discovery.
- default: admin (optional)
+ default: admin (v2), public (v3). (optional)
:param string endpoint_override: Always use this endpoint URL for requests
for this client. (optional)
:param auth: An auth plugin to use instead of the session one. (optional)
@@ -248,7 +250,7 @@ def __init__(self, username=None, tenant_id=None, tenant_name=None,
domain_name=None, project_id=None, project_name=None,
project_domain_id=None, project_domain_name=None,
trust_id=None, session=None, service_name=None,
- interface='admin', endpoint_override=None, auth=None,
+ interface='default', endpoint_override=None, auth=None,
user_agent=USER_AGENT, connect_retries=None, **kwargs):
# set baseline defaults
self.user_id = None
@@ -372,12 +374,21 @@ def __init__(self, username=None, tenant_id=None, tenant_name=None,
self.session = session
self.domain = ''
- # NOTE(jamielennox): unfortunately we can't just use **kwargs here as
- # it would incompatibly limit the kwargs that can be passed to __init__
- # try and keep this list in sync with adapter.Adapter.__init__
version = (
_discover.normalize_version_number(self.version) if self.version
else None)
+
+ # NOTE(frickler): If we know we have v3, use the public interface as
+ # default, otherwise keep the historic default of admin
+ if interface == 'default':
+ if version == (3, 0):
+ interface = 'public'
+ else:
+ interface = 'admin'
+
+ # NOTE(jamielennox): unfortunately we can't just use **kwargs here as
+ # it would incompatibly limit the kwargs that can be passed to __init__
+ # try and keep this list in sync with adapter.Adapter.__init__
self._adapter = _KeystoneAdapter(session,
service_type='identity',
service_name=service_name,
@@ -389,6 +400,11 @@ def __init__(self, username=None, tenant_id=None, tenant_name=None,
user_agent=user_agent,
connect_retries=connect_retries)
+ # NOTE(dstanek): This allows me to not have to change keystoneauth or
+ # to write an adapter to the adapter here. Splitting thing into
+ # multiple project isn't always all sunshine and roses.
+ self._adapter.include_metadata = kwargs.pop('include_metadata', False)
+
# keyring setup
if use_keyring and keyring is None:
_logger.warning('Failed to load keyring modules.')
diff --git a/keystoneclient/service_catalog.py b/keystoneclient/service_catalog.py
index cf4bc8642..afbefc0ae 100644
--- a/keystoneclient/service_catalog.py
+++ b/keystoneclient/service_catalog.py
@@ -19,14 +19,11 @@
import abc
import warnings
-import six
-
from keystoneclient import exceptions
from keystoneclient.i18n import _
-@six.add_metaclass(abc.ABCMeta)
-class ServiceCatalog(object):
+class ServiceCatalog(object, metaclass=abc.ABCMeta):
"""Helper methods for dealing with a Keystone Service Catalog.
.. warning::
diff --git a/keystoneclient/session.py b/keystoneclient/session.py
index dfac42401..4944d45f6 100644
--- a/keystoneclient/session.py
+++ b/keystoneclient/session.py
@@ -17,6 +17,7 @@
import os
import socket
import time
+import urllib.parse
import warnings
from debtcollector import removals
@@ -26,8 +27,6 @@
from oslo_utils import importutils
from oslo_utils import strutils
import requests
-import six
-from six.moves import urllib
from keystoneclient import exceptions
from keystoneclient.i18n import _
@@ -191,7 +190,7 @@ def _http_log_request(self, url, method=None, data=None,
# so we need to actually check that this is False.
if self.verify is False:
string_parts.append('--insecure')
- elif isinstance(self.verify, six.string_types):
+ elif isinstance(self.verify, str):
string_parts.append('--cacert "%s"' % self.verify)
if method:
@@ -205,7 +204,7 @@ def _http_log_request(self, url, method=None, data=None,
% self._process_header(header))
if data:
- if isinstance(data, six.binary_type):
+ if isinstance(data, bytes):
try:
data = data.decode("ascii")
except UnicodeDecodeError:
diff --git a/keystoneclient/tests/functional/base.py b/keystoneclient/tests/functional/base.py
index a8a12e01e..76355099f 100644
--- a/keystoneclient/tests/functional/base.py
+++ b/keystoneclient/tests/functional/base.py
@@ -10,10 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from openstack import config as occ
+import openstack.exceptions
import testtools
from keystoneclient import client
-import os_client_config
IDENTITY_CLIENT = 'identity'
OPENSTACK_CLOUDS = ('functional_admin', 'devstack-admin', 'envvars')
@@ -22,8 +23,8 @@
def get_client(version):
"""Create a keystoneclient instance to run functional tests.
- The client is instantiated via os-client-config either based on a
- clouds.yaml config file or from the environment variables.
+ The client is instantiated either based on a clouds.yaml config file or
+ from the environment variables.
First, look for a 'functional_admin' cloud, as this is a cloud that the
user may have defined for functional testing with admin credentials. If
@@ -33,12 +34,14 @@ def get_client(version):
"""
for cloud in OPENSTACK_CLOUDS:
try:
- cloud_config = os_client_config.get_config(
+ cloud_config = occ.OpenStackConfig().get_one(
cloud=cloud, identity_api_version=version)
- return cloud_config.get_legacy_client(service_key=IDENTITY_CLIENT,
- constructor=client.Client)
-
- except os_client_config.exceptions.OpenStackConfigException:
+ endpoint = cloud_config.get_session_endpoint(IDENTITY_CLIENT)
+ return client.Client(
+ version=version,
+ session=cloud_config.get_session(),
+ endpoint=endpoint)
+ except openstack.exceptions.ConfigException:
pass
raise Exception("Could not find any cloud definition for clouds named"
diff --git a/keystoneclient/tests/functional/hooks/post_test_hook.sh b/keystoneclient/tests/functional/hooks/post_test_hook.sh
deleted file mode 100755
index a0adfd6a8..000000000
--- a/keystoneclient/tests/functional/hooks/post_test_hook.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash -xe
-
-# 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.
-
-# This script is executed inside post_test_hook function in devstack gate.
-
-function generate_testr_results {
- if [ -f .testrepository/0 ]; then
- sudo .tox/functional/bin/testr last --subunit > $WORKSPACE/testrepository.subunit
- sudo mv $WORKSPACE/testrepository.subunit $BASE/logs/testrepository.subunit
- sudo /usr/os-testr-env/bin/subunit2html $BASE/logs/testrepository.subunit $BASE/logs/testr_results.html
- sudo gzip -9 $BASE/logs/testrepository.subunit
- sudo gzip -9 $BASE/logs/testr_results.html
- sudo chown $USER:$USER $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz
- sudo chmod a+r $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz
- fi
-}
-
-export KEYSTONECLIENT_DIR="$BASE/new/python-keystoneclient"
-
-# Get admin credentials
-cd $BASE/new/devstack
-source openrc admin admin
-
-# Go to the keystoneclient dir
-cd $KEYSTONECLIENT_DIR
-
-sudo chown -R $USER:stack $KEYSTONECLIENT_DIR
-
-# Run tests
-echo "Running keystoneclient functional test suite"
-set +e
-# Preserve env for OS_ credentials
-sudo -E -H -u $USER tox -efunctional
-EXIT_CODE=$?
-set -e
-
-# Collect and parse result
-generate_testr_results
-exit $EXIT_CODE
diff --git a/keystoneclient/tests/functional/v3/test_implied_roles.py b/keystoneclient/tests/functional/v3/test_implied_roles.py
index 0d5dbc5fa..4a8b446ea 100644
--- a/keystoneclient/tests/functional/v3/test_implied_roles.py
+++ b/keystoneclient/tests/functional/v3/test_implied_roles.py
@@ -28,11 +28,7 @@
"test_project_observer",
"test_member"]
-inference_rules = {"test_admin": "test_id_manager",
- "test_admin": "test_resource_manager",
- "test_admin": "test_role_manager",
- "test_admin": "test_catalog_manager",
- "test_admin": "test_policy_manager",
+inference_rules = {"test_admin": "test_policy_manager",
"test_id_manager": "test_project_observer",
"test_resource_manager": "test_project_observer",
"test_role_manager": "test_project_observer",
diff --git a/keystoneclient/tests/functional/v3/test_projects.py b/keystoneclient/tests/functional/v3/test_projects.py
index c40da5030..a7f082db1 100644
--- a/keystoneclient/tests/functional/v3/test_projects.py
+++ b/keystoneclient/tests/functional/v3/test_projects.py
@@ -118,10 +118,10 @@ def test_get_hierarchy_as_list(self):
parents_as_list=True)
self.check_project(project_ret, project.ref)
- self.assertItemsEqual(
+ self.assertCountEqual(
[{'project': self.test_project.entity.to_dict()}],
project_ret.parents)
- self.assertItemsEqual(
+ self.assertCountEqual(
[{'project': child_project.entity.to_dict()}],
project_ret.subtree)
@@ -138,8 +138,8 @@ def test_get_hierarchy_as_ids(self):
subtree_as_ids=True,
parents_as_ids=True)
- self.assertItemsEqual([self.test_project.id], project_ret.parents)
- self.assertItemsEqual([child_project.id], project_ret.subtree)
+ self.assertCountEqual([self.test_project.id], project_ret.parents)
+ self.assertCountEqual([child_project.id], project_ret.subtree)
def test_list_projects(self):
project_one = fixtures.Project(self.client, self.test_domain.id)
@@ -157,6 +157,30 @@ def test_list_projects(self):
self.assertIn(project_one.entity, projects)
self.assertIn(project_two.entity, projects)
+ def test_list_subprojects(self):
+ parent_project = fixtures.Project(self.client, self.test_domain.id)
+ self.useFixture(parent_project)
+
+ child_project_one = fixtures.Project(self.client, self.test_domain.id,
+ parent=parent_project.id)
+ self.useFixture(child_project_one)
+
+ child_project_two = fixtures.Project(self.client, self.test_domain.id,
+ parent=parent_project.id)
+ self.useFixture(child_project_two)
+
+ projects = self.client.projects.list(parent=parent_project.id)
+
+ # All projects are valid
+ for project in projects:
+ self.check_project(project)
+
+ self.assertIn(child_project_one.entity, projects)
+ self.assertIn(child_project_two.entity, projects)
+
+ # Parent project should not be included in the result
+ self.assertNotIn(parent_project.entity, projects)
+
def test_update_project(self):
project = fixtures.Project(self.client, self.test_domain.id)
self.useFixture(project)
diff --git a/keystoneclient/tests/functional/v3/test_roles.py b/keystoneclient/tests/functional/v3/test_roles.py
index d2bc7a25b..6dba6ffa3 100644
--- a/keystoneclient/tests/functional/v3/test_roles.py
+++ b/keystoneclient/tests/functional/v3/test_roles.py
@@ -168,7 +168,7 @@ def test_user_domain_grant_and_revoke(self):
self.client.roles.grant(role, user=user.id, domain=domain.id)
roles_after_grant = self.client.roles.list(user=user.id,
domain=domain.id)
- self.assertItemsEqual(roles_after_grant, [role.entity])
+ self.assertCountEqual(roles_after_grant, [role.entity])
self.client.roles.revoke(role, user=user.id, domain=domain.id)
roles_after_revoke = self.client.roles.list(user=user.id,
@@ -188,7 +188,7 @@ def test_user_project_grant_and_revoke(self):
self.client.roles.grant(role, user=user.id, project=project.id)
roles_after_grant = self.client.roles.list(user=user.id,
project=project.id)
- self.assertItemsEqual(roles_after_grant, [role.entity])
+ self.assertCountEqual(roles_after_grant, [role.entity])
self.client.roles.revoke(role, user=user.id, project=project.id)
roles_after_revoke = self.client.roles.list(user=user.id,
@@ -208,7 +208,7 @@ def test_group_domain_grant_and_revoke(self):
self.client.roles.grant(role, group=group.id, domain=domain.id)
roles_after_grant = self.client.roles.list(group=group.id,
domain=domain.id)
- self.assertItemsEqual(roles_after_grant, [role.entity])
+ self.assertCountEqual(roles_after_grant, [role.entity])
self.client.roles.revoke(role, group=group.id, domain=domain.id)
roles_after_revoke = self.client.roles.list(group=group.id,
@@ -228,7 +228,7 @@ def test_group_project_grant_and_revoke(self):
self.client.roles.grant(role, group=group.id, project=project.id)
roles_after_grant = self.client.roles.list(group=group.id,
project=project.id)
- self.assertItemsEqual(roles_after_grant, [role.entity])
+ self.assertCountEqual(roles_after_grant, [role.entity])
self.client.roles.revoke(role, group=group.id, project=project.id)
roles_after_revoke = self.client.roles.list(group=group.id,
diff --git a/keystoneclient/tests/unit/auth/test_auth.py b/keystoneclient/tests/unit/auth/test_auth.py
index f2884350c..3a56fb2aa 100644
--- a/keystoneclient/tests/unit/auth/test_auth.py
+++ b/keystoneclient/tests/unit/auth/test_auth.py
@@ -10,29 +10,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-from keystoneclient import auth
-from keystoneclient.auth import identity
from keystoneclient.tests.unit.auth import utils
class AuthTests(utils.TestCase):
def test_plugin_names_in_available(self):
- with self.deprecations.expect_deprecations_here():
- plugins = auth.get_available_plugin_names()
-
- for p in ('password', 'v2password', 'v3password',
- 'token', 'v2token', 'v3token'):
- self.assertIn(p, plugins)
+ pass
def test_plugin_classes_in_available(self):
- with self.deprecations.expect_deprecations_here():
- plugins = auth.get_available_plugin_classes()
-
- self.assertIs(plugins['password'], identity.Password)
- self.assertIs(plugins['v2password'], identity.V2Password)
- self.assertIs(plugins['v3password'], identity.V3Password)
-
- self.assertIs(plugins['token'], identity.Token)
- self.assertIs(plugins['v2token'], identity.V2Token)
- self.assertIs(plugins['v3token'], identity.V3Token)
+ pass
diff --git a/keystoneclient/tests/unit/auth/test_cli.py b/keystoneclient/tests/unit/auth/test_cli.py
index b6fefa7c7..b2a2f6ae8 100644
--- a/keystoneclient/tests/unit/auth/test_cli.py
+++ b/keystoneclient/tests/unit/auth/test_cli.py
@@ -11,10 +11,10 @@
# under the License.
import argparse
+from unittest import mock
import uuid
import fixtures
-import mock
from oslo_config import cfg
from keystoneclient.auth import base
diff --git a/keystoneclient/tests/unit/auth/test_conf.py b/keystoneclient/tests/unit/auth/test_conf.py
index 47bf75900..bea37a4f1 100644
--- a/keystoneclient/tests/unit/auth/test_conf.py
+++ b/keystoneclient/tests/unit/auth/test_conf.py
@@ -10,17 +10,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
import uuid
-import mock
from oslo_config import cfg
from oslo_config import fixture as config
-import stevedore
from keystoneclient.auth import base
from keystoneclient.auth import conf
-from keystoneclient.auth.identity import v2 as v2_auth
-from keystoneclient.auth.identity import v3 as v3_auth
from keystoneclient import exceptions
from keystoneclient.tests.unit.auth import utils
@@ -39,58 +36,10 @@ def setUp(self):
conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP)
def test_loading_v2(self):
- section = uuid.uuid4().hex
- username = uuid.uuid4().hex
- password = uuid.uuid4().hex
- trust_id = uuid.uuid4().hex
- tenant_id = uuid.uuid4().hex
-
- self.conf_fixture.config(auth_section=section, group=self.GROUP)
- conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP)
-
- self.conf_fixture.register_opts(v2_auth.Password.get_options(),
- group=section)
-
- self.conf_fixture.config(auth_plugin=self.V2PASS,
- username=username,
- password=password,
- trust_id=trust_id,
- tenant_id=tenant_id,
- group=section)
-
- a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP)
-
- self.assertEqual(username, a.username)
- self.assertEqual(password, a.password)
- self.assertEqual(trust_id, a.trust_id)
- self.assertEqual(tenant_id, a.tenant_id)
+ pass
def test_loading_v3(self):
- section = uuid.uuid4().hex
- token = uuid.uuid4().hex
- trust_id = uuid.uuid4().hex
- project_id = uuid.uuid4().hex
- project_domain_name = uuid.uuid4().hex
-
- self.conf_fixture.config(auth_section=section, group=self.GROUP)
- conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP)
-
- self.conf_fixture.register_opts(v3_auth.Token.get_options(),
- group=section)
-
- self.conf_fixture.config(auth_plugin=self.V3TOKEN,
- token=token,
- trust_id=trust_id,
- project_id=project_id,
- project_domain_name=project_domain_name,
- group=section)
-
- a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP)
-
- self.assertEqual(token, a.auth_methods[0].token)
- self.assertEqual(trust_id, a.trust_id)
- self.assertEqual(project_id, a.project_id)
- self.assertEqual(project_domain_name, a.project_domain_name)
+ pass
def test_loading_invalid_plugin(self):
auth_plugin = uuid.uuid4().hex
@@ -155,15 +104,7 @@ def test_diff_section(self, m):
self.assertTestVals(a)
def test_plugins_are_all_opts(self):
- manager = stevedore.ExtensionManager(base.PLUGIN_NAMESPACE,
- invoke_on_load=False,
- propagate_map_exceptions=True)
-
- def inner(driver):
- for p in driver.plugin.get_options():
- self.assertIsInstance(p, cfg.Opt)
-
- manager.map(inner)
+ pass
def test_get_common(self):
opts = conf.get_common_conf_options()
@@ -172,7 +113,4 @@ def test_get_common(self):
self.assertEqual(2, len(opts))
def test_get_named(self):
- loaded_opts = conf.get_plugin_options('v2password')
- plugin_opts = v2_auth.Password.get_options()
-
- self.assertEqual(plugin_opts, loaded_opts)
+ pass
diff --git a/keystoneclient/tests/unit/auth/test_default_cli.py b/keystoneclient/tests/unit/auth/test_default_cli.py
index cb4603dc4..8afd2cde7 100644
--- a/keystoneclient/tests/unit/auth/test_default_cli.py
+++ b/keystoneclient/tests/unit/auth/test_default_cli.py
@@ -11,9 +11,9 @@
# under the License.
import argparse
+from unittest import mock
import uuid
-import mock
from keystoneclient.auth.identity.generic import cli
from keystoneclient import exceptions
diff --git a/keystoneclient/tests/unit/auth/test_identity_common.py b/keystoneclient/tests/unit/auth/test_identity_common.py
index be8a062de..3e8cc2b81 100644
--- a/keystoneclient/tests/unit/auth/test_identity_common.py
+++ b/keystoneclient/tests/unit/auth/test_identity_common.py
@@ -12,13 +12,12 @@
import abc
import datetime
+from unittest import mock
import uuid
from keystoneauth1 import fixture
from keystoneauth1 import plugin
-import mock
from oslo_utils import timeutils
-import six
from keystoneclient import access
from keystoneclient.auth import base
@@ -28,8 +27,7 @@
from keystoneclient.tests.unit import utils
-@six.add_metaclass(abc.ABCMeta)
-class CommonIdentityTests(object):
+class CommonIdentityTests(object, metaclass=abc.ABCMeta):
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
@@ -79,7 +77,8 @@ def stub_auth_data(self, **kwargs):
self.stub_auth(json=token)
- @abc.abstractproperty
+ @property
+ @abc.abstractmethod
def version(self):
"""The API version being tested."""
diff --git a/keystoneclient/tests/unit/auth/test_identity_v2.py b/keystoneclient/tests/unit/auth/test_identity_v2.py
index 8ef87c430..84f4f5194 100644
--- a/keystoneclient/tests/unit/auth/test_identity_v2.py
+++ b/keystoneclient/tests/unit/auth/test_identity_v2.py
@@ -12,9 +12,9 @@
import argparse
import copy
+from unittest import mock
import uuid
-import mock
from keystoneclient.auth.identity import v2
from keystoneclient import exceptions
@@ -84,7 +84,7 @@ def setUp(self):
self.TEST_RESPONSE_DICT = {
"access": {
"token": {
- "expires": "2020-01-01T00:00:10.000123Z",
+ "expires": "2999-01-01T00:00:10.000123Z",
"id": self.TEST_TOKEN,
"tenant": {
"id": self.TEST_TENANT_ID
diff --git a/keystoneclient/tests/unit/auth/test_identity_v3.py b/keystoneclient/tests/unit/auth/test_identity_v3.py
index 534e99747..fe7815ed2 100644
--- a/keystoneclient/tests/unit/auth/test_identity_v3.py
+++ b/keystoneclient/tests/unit/auth/test_identity_v3.py
@@ -12,10 +12,10 @@
import argparse
import copy
+from unittest import mock
import uuid
from keystoneauth1 import fixture
-import mock
from keystoneclient import access
from keystoneclient.auth.identity import v3
@@ -129,7 +129,7 @@ def setUp(self):
"password"
],
- "expires_at": "2020-01-01T00:00:10.000123Z",
+ "expires_at": "2999-01-01T00:00:10.000123Z",
"project": {
"domain": {
"id": self.TEST_DOMAIN_ID,
diff --git a/keystoneclient/tests/unit/auth/test_password.py b/keystoneclient/tests/unit/auth/test_password.py
index 020eb124c..93d2fb8ca 100644
--- a/keystoneclient/tests/unit/auth/test_password.py
+++ b/keystoneclient/tests/unit/auth/test_password.py
@@ -11,9 +11,9 @@
# under the License.
import argparse
+from unittest import mock
import uuid
-import mock
from keystoneclient.auth.identity.generic import password
from keystoneclient.auth.identity import v2
diff --git a/keystoneclient/tests/unit/auth/utils.py b/keystoneclient/tests/unit/auth/utils.py
index b6931728b..1e346e35c 100644
--- a/keystoneclient/tests/unit/auth/utils.py
+++ b/keystoneclient/tests/unit/auth/utils.py
@@ -11,10 +11,10 @@
# under the License.
import functools
+from unittest import mock
import uuid
from keystoneauth1 import fixture
-import mock
from oslo_config import cfg
from keystoneclient import access
diff --git a/keystoneclient/tests/unit/client_fixtures.py b/keystoneclient/tests/unit/client_fixtures.py
index 6da259c9c..c6c291984 100644
--- a/keystoneclient/tests/unit/client_fixtures.py
+++ b/keystoneclient/tests/unit/client_fixtures.py
@@ -23,7 +23,6 @@
from keystoneauth1 import session as ksa_session
from oslo_serialization import jsonutils
from oslo_utils import timeutils
-import six
import testresources
from keystoneclient.auth import identity as ksc_identity
@@ -204,7 +203,7 @@ def new_client(self):
def _hash_signed_token_safe(signed_text, **kwargs):
- if isinstance(signed_text, six.text_type):
+ if isinstance(signed_text, str):
signed_text = signed_text.encode('utf-8')
return utils.hash_signed_token(signed_text, **kwargs)
@@ -299,7 +298,7 @@ def setUp(self):
self.v3_UUID_TOKEN_UNKNOWN_BIND = '7ed9781b62cd4880b8d8c6788ab1d1e2'
revoked_token = self.REVOKED_TOKEN
- if isinstance(revoked_token, six.text_type):
+ if isinstance(revoked_token, str):
revoked_token = revoked_token.encode('utf-8')
self.REVOKED_TOKEN_HASH = utils.hash_signed_token(revoked_token)
self.REVOKED_TOKEN_HASH_SHA256 = utils.hash_signed_token(revoked_token,
@@ -310,7 +309,7 @@ def setUp(self):
self.REVOKED_TOKEN_LIST_JSON = jsonutils.dumps(self.REVOKED_TOKEN_LIST)
revoked_v3_token = self.REVOKED_v3_TOKEN
- if isinstance(revoked_v3_token, six.text_type):
+ if isinstance(revoked_v3_token, str):
revoked_v3_token = revoked_v3_token.encode('utf-8')
self.REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(revoked_v3_token)
hash = utils.hash_signed_token(revoked_v3_token, mode='sha256')
@@ -322,12 +321,12 @@ def setUp(self):
self.REVOKED_v3_TOKEN_LIST)
revoked_token_pkiz = self.REVOKED_TOKEN_PKIZ
- if isinstance(revoked_token_pkiz, six.text_type):
+ if isinstance(revoked_token_pkiz, str):
revoked_token_pkiz = revoked_token_pkiz.encode('utf-8')
self.REVOKED_TOKEN_PKIZ_HASH = utils.hash_signed_token(
revoked_token_pkiz)
revoked_v3_token_pkiz = self.REVOKED_v3_TOKEN_PKIZ
- if isinstance(revoked_v3_token_pkiz, six.text_type):
+ if isinstance(revoked_v3_token_pkiz, str):
revoked_v3_token_pkiz = revoked_v3_token_pkiz.encode('utf-8')
self.REVOKED_v3_PKIZ_TOKEN_HASH = utils.hash_signed_token(
revoked_v3_token_pkiz)
@@ -399,7 +398,7 @@ def setUp(self):
'access': {
'token': {
'id': self.UUID_TOKEN_DEFAULT,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
@@ -420,7 +419,7 @@ def setUp(self):
'access': {
'token': {
'id': self.VALID_DIABLO_TOKEN,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
'tenantId': 'tenant_id1',
},
'user': {
@@ -437,7 +436,7 @@ def setUp(self):
'access': {
'token': {
'id': self.UUID_TOKEN_UNSCOPED,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
},
'user': {
'id': 'user_id1',
@@ -453,7 +452,7 @@ def setUp(self):
'access': {
'token': {
'id': 'valid-token',
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
@@ -474,7 +473,7 @@ def setUp(self):
'token': {
'bind': {'kerberos': self.KERBEROS_BIND},
'id': self.UUID_TOKEN_BIND,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
@@ -496,7 +495,7 @@ def setUp(self):
'token': {
'bind': {'FOO': 'BAR'},
'id': self.UUID_TOKEN_UNKNOWN_BIND,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
@@ -515,7 +514,7 @@ def setUp(self):
},
self.v3_UUID_TOKEN_DEFAULT: {
'token': {
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'methods': ['password'],
'user': {
'id': 'user_id1',
@@ -542,7 +541,7 @@ def setUp(self):
},
self.v3_UUID_TOKEN_UNSCOPED: {
'token': {
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'methods': ['password'],
'user': {
'id': 'user_id1',
@@ -556,7 +555,7 @@ def setUp(self):
},
self.v3_UUID_TOKEN_DOMAIN_SCOPED: {
'token': {
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'methods': ['password'],
'user': {
'id': 'user_id1',
@@ -581,7 +580,7 @@ def setUp(self):
'access': {
'token': {
'id': self.SIGNED_TOKEN_SCOPED_KEY,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
},
'user': {
'id': 'user_id1',
@@ -599,7 +598,7 @@ def setUp(self):
'access': {
'token': {
'id': self.SIGNED_TOKEN_UNSCOPED_KEY,
- 'expires': '2020-01-01T00:00:10.000123Z',
+ 'expires': '2999-01-01T00:00:10.000123Z',
},
'user': {
'id': 'user_id1',
@@ -613,7 +612,7 @@ def setUp(self):
},
self.SIGNED_v3_TOKEN_SCOPED_KEY: {
'token': {
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'methods': ['password'],
'user': {
'id': 'user_id1',
@@ -642,7 +641,7 @@ def setUp(self):
'token': {
'bind': {'kerberos': self.KERBEROS_BIND},
'methods': ['password'],
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'user': {
'id': 'user_id1',
'name': 'user_name1',
@@ -669,7 +668,7 @@ def setUp(self):
self.v3_UUID_TOKEN_UNKNOWN_BIND: {
'token': {
'bind': {'FOO': 'BAR'},
- 'expires_at': '2020-01-01T00:00:10.000123Z',
+ 'expires_at': '2999-01-01T00:00:10.000123Z',
'methods': ['password'],
'user': {
'id': 'user_id1',
diff --git a/keystoneclient/tests/unit/test_base.py b/keystoneclient/tests/unit/test_base.py
index 0a0fde1c3..ca57dc469 100644
--- a/keystoneclient/tests/unit/test_base.py
+++ b/keystoneclient/tests/unit/test_base.py
@@ -11,14 +11,29 @@
# License for the specific language governing permissions and limitations
# under the License.
+import uuid
+
import fixtures
from keystoneauth1.identity import v2
from keystoneauth1 import session
+import requests
from keystoneclient import base
+from keystoneclient import exceptions
from keystoneclient.tests.unit import utils
+from keystoneclient import utils as base_utils
from keystoneclient.v2_0 import client
from keystoneclient.v2_0 import roles
+from keystoneclient.v3 import users
+
+TEST_REQUEST_ID = uuid.uuid4().hex
+TEST_REQUEST_ID_1 = uuid.uuid4().hex
+
+
+def create_response_with_request_id_header():
+ resp = requests.Response()
+ resp.headers['x-openstack-request-id'] = TEST_REQUEST_ID
+ return resp
class HumanReadable(base.Resource):
@@ -202,3 +217,209 @@ def test_update(self):
management=True)
put_mock.assert_called_once_with(self.url, management=True, body=None)
self.assertEqual(rsrc.hi, 1)
+
+
+class ManagerRequestIdTest(utils.TestCase):
+ url = "/test-url"
+ resp = create_response_with_request_id_header()
+
+ def setUp(self):
+ super(ManagerRequestIdTest, self).setUp()
+
+ auth = v2.Token(auth_url='http://127.0.0.1:5000',
+ token=self.TEST_TOKEN)
+ session_ = session.Session(auth=auth)
+ self.client = client.Client(session=session_,
+ include_metadata='True')._adapter
+
+ self.mgr = base.Manager(self.client)
+ self.mgr.resource_class = base.Resource
+
+ def mock_request_method(self, request_method, body):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, request_method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get(self):
+ body = {"hello": {"hi": 1}}
+ get_mock = self.mock_request_method('get', body)
+ rsrc = self.mgr._get(self.url, "hello")
+ get_mock.assert_called_once_with(self.url)
+ self.assertEqual(rsrc.data.hi, 1)
+ self.assertEqual(rsrc.request_ids[0], TEST_REQUEST_ID)
+
+ def test_list(self):
+ body = {"hello": [{"name": "admin"}, {"name": "admin"}]}
+ get_mock = self.mock_request_method('get', body)
+
+ returned_list = self.mgr._list(self.url, "hello")
+ self.assertEqual(returned_list.request_ids[0], TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(self.url)
+
+ def test_list_with_multiple_response_objects(self):
+ body = {"hello": [{"name": "admin"}, {"name": "admin"}]}
+ resp_1 = requests.Response()
+ resp_1.headers['x-openstack-request-id'] = TEST_REQUEST_ID
+ resp_2 = requests.Response()
+ resp_2.headers['x-openstack-request-id'] = TEST_REQUEST_ID_1
+
+ resp_result = [resp_1, resp_2]
+ get_mock = self.useFixture(fixtures.MockPatchObject(
+ self.client, 'get', autospec=True,
+ return_value=(resp_result, body))
+ ).mock
+
+ returned_list = self.mgr._list(self.url, "hello")
+ self.assertIn(returned_list.request_ids[0], [
+ TEST_REQUEST_ID, TEST_REQUEST_ID_1])
+ self.assertIn(returned_list.request_ids[1], [
+ TEST_REQUEST_ID, TEST_REQUEST_ID_1])
+ get_mock.assert_called_once_with(self.url)
+
+ def test_post(self):
+ body = {"hello": {"hi": 1}}
+ post_mock = self.mock_request_method('post', body)
+ rsrc = self.mgr._post(self.url, body, "hello")
+ post_mock.assert_called_once_with(self.url, body=body)
+ self.assertEqual(rsrc.data.hi, 1)
+
+ post_mock.reset_mock()
+
+ rsrc = self.mgr._post(self.url, body, "hello", return_raw=True)
+ post_mock.assert_called_once_with(self.url, body=body)
+ self.assertNotIsInstance(rsrc, base.Response)
+ self.assertEqual(rsrc["hi"], 1)
+
+ def test_put(self):
+ body = {"hello": {"hi": 1}}
+ put_mock = self.mock_request_method('put', body)
+ rsrc = self.mgr._put(self.url, body, "hello")
+ put_mock.assert_called_once_with(self.url, body=body)
+ self.assertEqual(rsrc.data.hi, 1)
+
+ put_mock.reset_mock()
+
+ rsrc = self.mgr._put(self.url, body)
+ put_mock.assert_called_once_with(self.url, body=body)
+ self.assertEqual(rsrc.data.hello["hi"], 1)
+ self.assertEqual(rsrc.request_ids[0], TEST_REQUEST_ID)
+
+ def test_head(self):
+ get_mock = self.mock_request_method('head', None)
+ rsrc = self.mgr._head(self.url)
+ get_mock.assert_called_once_with(self.url)
+ self.assertFalse(rsrc.data)
+ self.assertEqual(rsrc.request_ids[0], TEST_REQUEST_ID)
+
+ def test_delete(self):
+ delete_mock = self.mock_request_method('delete', None)
+ resp, base_resp = self.mgr._delete(self.url, name="hello")
+
+ delete_mock.assert_called_once_with('/test-url', name='hello')
+ self.assertEqual(base_resp.request_ids[0], TEST_REQUEST_ID)
+ self.assertEqual(base_resp.data, None)
+ self.assertIsInstance(resp, requests.Response)
+
+ def test_patch(self):
+ body = {"hello": {"hi": 1}}
+ patch_mock = self.mock_request_method('patch', body)
+ rsrc = self.mgr._patch(self.url, body, "hello")
+ patch_mock.assert_called_once_with(self.url, body=body)
+ self.assertEqual(rsrc.data.hi, 1)
+
+ patch_mock.reset_mock()
+
+ rsrc = self.mgr._patch(self.url, body)
+ patch_mock.assert_called_once_with(self.url, body=body)
+ self.assertEqual(rsrc.data.hello["hi"], 1)
+ self.assertEqual(rsrc.request_ids[0], TEST_REQUEST_ID)
+
+ def test_update(self):
+ body = {"hello": {"hi": 1}}
+ patch_mock = self.mock_request_method('patch', body)
+ put_mock = self.mock_request_method('put', body)
+
+ rsrc = self.mgr._update(
+ self.url, body=body, response_key="hello", method="PATCH",
+ management=False)
+ patch_mock.assert_called_once_with(
+ self.url, management=False, body=body)
+ self.assertEqual(rsrc.data.hi, 1)
+
+ rsrc = self.mgr._update(
+ self.url, body=None, response_key="hello", method="PUT",
+ management=True)
+ put_mock.assert_called_once_with(self.url, management=True, body=None)
+ self.assertEqual(rsrc.data.hi, 1)
+ self.assertEqual(rsrc.request_ids[0], TEST_REQUEST_ID)
+
+
+class ManagerWithFindRequestIdTest(utils.TestCase):
+ url = "/fakes"
+ resp = create_response_with_request_id_header()
+
+ def setUp(self):
+ super(ManagerWithFindRequestIdTest, self).setUp()
+
+ auth = v2.Token(auth_url='http://127.0.0.1:5000',
+ token=self.TEST_TOKEN)
+ session_ = session.Session(auth=auth)
+ self.client = client.Client(session=session_,
+ include_metadata='True')._adapter
+
+ def test_find_resource(self):
+ body = {"roles": [{"name": 'entity_one'}, {"name": 'entity_one_1'}]}
+ request_resp = requests.Response()
+ request_resp.headers['x-openstack-request-id'] = TEST_REQUEST_ID
+
+ get_mock = self.useFixture(fixtures.MockPatchObject(
+ self.client, 'get', autospec=True,
+ side_effect=[exceptions.NotFound, (request_resp, body)])
+ ).mock
+
+ mgr = roles.RoleManager(self.client)
+ mgr.resource_class = roles.Role
+ response = base_utils.find_resource(mgr, 'entity_one')
+ get_mock.assert_called_with('/OS-KSADM/roles')
+ self.assertEqual(response.request_ids[0], TEST_REQUEST_ID)
+
+
+class CrudManagerRequestIdTest(utils.TestCase):
+ resp = create_response_with_request_id_header()
+ request_resp = requests.Response()
+ request_resp.headers['x-openstack-request-id'] = TEST_REQUEST_ID
+
+ def setUp(self):
+ super(CrudManagerRequestIdTest, self).setUp()
+
+ auth = v2.Token(auth_url='http://127.0.0.1:5000',
+ token=self.TEST_TOKEN)
+ session_ = session.Session(auth=auth)
+ self.client = client.Client(session=session_,
+ include_metadata='True')._adapter
+
+ def test_find_resource(self):
+ body = {"users": [{"name": 'entity_one'}]}
+ get_mock = self.useFixture(fixtures.MockPatchObject(
+ self.client, 'get', autospec=True,
+ side_effect=[exceptions.NotFound, (self.request_resp, body)])
+ ).mock
+ mgr = users.UserManager(self.client)
+ mgr.resource_class = users.User
+ response = base_utils.find_resource(mgr, 'entity_one')
+ get_mock.assert_called_with('/users?name=entity_one')
+ self.assertEqual(response.request_ids[0], TEST_REQUEST_ID)
+
+ def test_list(self):
+ body = {"users": [{"name": "admin"}, {"name": "admin"}]}
+
+ get_mock = self.useFixture(fixtures.MockPatchObject(
+ self.client, 'get', autospec=True,
+ return_value=(self.request_resp, body))
+ ).mock
+ mgr = users.UserManager(self.client)
+ mgr.resource_class = users.User
+ returned_list = mgr.list()
+ self.assertEqual(returned_list.request_ids[0], TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('/users?')
diff --git a/keystoneclient/tests/unit/test_cms.py b/keystoneclient/tests/unit/test_cms.py
index 11078aeec..2671bcb49 100644
--- a/keystoneclient/tests/unit/test_cms.py
+++ b/keystoneclient/tests/unit/test_cms.py
@@ -13,8 +13,8 @@
import errno
import os
import subprocess
+from unittest import mock
-import mock
import testresources
from testtools import matchers
diff --git a/keystoneclient/tests/unit/test_discovery.py b/keystoneclient/tests/unit/test_discovery.py
index f9d5dbfac..57c7002cc 100644
--- a/keystoneclient/tests/unit/test_discovery.py
+++ b/keystoneclient/tests/unit/test_discovery.py
@@ -15,7 +15,6 @@
from keystoneauth1 import fixture
from oslo_serialization import jsonutils
-import six
from testtools import matchers
from keystoneclient import _discover
@@ -87,7 +86,7 @@
V2_AUTH_RESPONSE = jsonutils.dumps({
"access": {
"token": {
- "expires": "2020-01-01T00:00:10.000123Z",
+ "expires": "2999-01-01T00:00:10.000123Z",
"id": 'fakeToken',
"tenant": {
"id": '1'
@@ -105,7 +104,7 @@
V3_MEDIA_TYPES = V3_VERSION.media_types
V3_VERSION.updated_str = UPDATED
-V3_TOKEN = six.u('3e2813b7ba0b4006840c3825860b86ed'),
+V3_TOKEN = ('3e2813b7ba0b4006840c3825860b86ed',)
V3_AUTH_RESPONSE = jsonutils.dumps({
"token": {
"methods": [
@@ -113,7 +112,7 @@
"password"
],
- "expires_at": "2020-01-01T00:00:10.000123Z",
+ "expires_at": "2999-01-01T00:00:10.000123Z",
"project": {
"domain": {
"id": '1',
diff --git a/keystoneclient/tests/unit/test_ec2utils.py b/keystoneclient/tests/unit/test_ec2utils.py
index 1d8809b2e..12cf57531 100644
--- a/keystoneclient/tests/unit/test_ec2utils.py
+++ b/keystoneclient/tests/unit/test_ec2utils.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from __future__ import unicode_literals
-
import testtools
from keystoneclient.contrib.ec2 import utils
diff --git a/keystoneclient/tests/unit/test_http.py b/keystoneclient/tests/unit/test_http.py
index af9058f91..65a428aa6 100644
--- a/keystoneclient/tests/unit/test_http.py
+++ b/keystoneclient/tests/unit/test_http.py
@@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import io
import logging
-import six
from testtools import matchers
from keystoneclient import exceptions
@@ -153,7 +153,7 @@ class BasicRequestTests(utils.TestCase):
def setUp(self):
super(BasicRequestTests, self).setUp()
- self.logger_message = six.moves.cStringIO()
+ self.logger_message = io.StringIO()
handler = logging.StreamHandler(self.logger_message)
handler.setLevel(logging.DEBUG)
diff --git a/keystoneclient/tests/unit/test_https.py b/keystoneclient/tests/unit/test_https.py
index 4e8d260cf..315a17aaa 100644
--- a/keystoneclient/tests/unit/test_https.py
+++ b/keystoneclient/tests/unit/test_https.py
@@ -10,8 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
import requests
+from unittest import mock
from keystoneclient import httpclient
from keystoneclient.tests.unit import utils
diff --git a/keystoneclient/tests/unit/test_keyring.py b/keystoneclient/tests/unit/test_keyring.py
index 7d30d980c..0a5bf7150 100644
--- a/keystoneclient/tests/unit/test_keyring.py
+++ b/keystoneclient/tests/unit/test_keyring.py
@@ -11,8 +11,8 @@
# under the License.
import datetime
+from unittest import mock
-import mock
from oslo_utils import timeutils
from keystoneclient import access
diff --git a/keystoneclient/tests/unit/test_session.py b/keystoneclient/tests/unit/test_session.py
index e0d9b2868..71a8e2743 100644
--- a/keystoneclient/tests/unit/test_session.py
+++ b/keystoneclient/tests/unit/test_session.py
@@ -13,16 +13,16 @@
# under the License.
import argparse
+from io import StringIO
import itertools
import logging
+from unittest import mock
import uuid
-import mock
from oslo_config import cfg
from oslo_config import fixture as config
from oslo_serialization import jsonutils
import requests
-import six
from testtools import matchers
from keystoneclient import adapter
@@ -243,33 +243,12 @@ def test_unicode_data_in_debug_output(self):
session = client_session.Session(verify=False)
body = 'RESP'
- data = u'αβγδ'
+ data = 'αβγδ'
self.stub_url('POST', text=body)
session.post(self.TEST_URL, data=data)
self.assertIn("'%s'" % data, self.logger.output)
- def test_binary_data_not_in_debug_output(self):
- """Verify that non-ascii-encodable data causes replacement."""
- if six.PY2:
- data = "my data" + chr(255)
- else:
- # Python 3 logging handles binary data well.
- return
-
- session = client_session.Session(verify=False)
-
- body = 'RESP'
- self.stub_url('POST', text=body)
-
- # Forced mixed unicode and byte strings in request
- # elements to make sure that all joins are appropriately
- # handled (any join of unicode and byte strings should
- # raise a UnicodeDecodeError)
- session.post(six.text_type(self.TEST_URL), data=data)
-
- self.assertNotIn('my data', self.logger.output)
-
def test_logging_cacerts(self):
path_to_certs = '/path/to/certs'
session = client_session.Session(verify=path_to_certs)
@@ -328,11 +307,12 @@ def _ssl_error(request, context):
# The exception should contain the URL and details about the SSL error
msg = _('SSL exception connecting to %(url)s: %(error)s') % {
'url': self.TEST_URL, 'error': error}
- six.assertRaisesRegex(self,
- exceptions.SSLError,
- msg,
- session.get,
- self.TEST_URL)
+ self.assertRaisesRegex(
+ exceptions.SSLError,
+ msg,
+ session.get,
+ self.TEST_URL,
+ )
def test_mask_password_in_http_log_response(self):
session = client_session.Session()
@@ -807,7 +787,7 @@ def test_logger_object_passed(self):
logger.setLevel(logging.DEBUG)
logger.propagate = False
- io = six.StringIO()
+ io = StringIO()
handler = logging.StreamHandler(io)
logger.addHandler(handler)
@@ -828,7 +808,6 @@ def test_logger_object_passed(self):
self.assertIn(list(response.keys())[0], output)
self.assertIn(list(response.values())[0], output)
- self.assertNotIn(self.TEST_URL, self.logger.output)
self.assertNotIn(list(response.keys())[0], self.logger.output)
self.assertNotIn(list(response.values())[0], self.logger.output)
@@ -1004,7 +983,7 @@ def test_logger_object_passed(self):
logger.setLevel(logging.DEBUG)
logger.propagate = False
- io = six.StringIO()
+ io = StringIO()
handler = logging.StreamHandler(io)
logger.addHandler(handler)
@@ -1026,7 +1005,6 @@ def test_logger_object_passed(self):
self.assertIn(list(response.keys())[0], output)
self.assertIn(list(response.values())[0], output)
- self.assertNotIn(self.TEST_URL, self.logger.output)
self.assertNotIn(list(response.keys())[0], self.logger.output)
self.assertNotIn(list(response.values())[0], self.logger.output)
diff --git a/keystoneclient/tests/unit/test_utils.py b/keystoneclient/tests/unit/test_utils.py
index 01443314c..2aa5e92be 100644
--- a/keystoneclient/tests/unit/test_utils.py
+++ b/keystoneclient/tests/unit/test_utils.py
@@ -11,7 +11,6 @@
# under the License.
from keystoneauth1 import exceptions as ksa_exceptions
-import six
import testresources
from testtools import matchers
@@ -33,7 +32,7 @@ class FakeManager(object):
resources = {
'1234': {'name': 'entity_one'},
'8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0': {'name': 'entity_two'},
- '\xe3\x82\xbdtest': {'name': u'\u30bdtest'},
+ '\xe3\x82\xbdtest': {'name': '\u30bdtest'},
'5678': {'name': '9876'}
}
@@ -112,8 +111,7 @@ class HashSignedTokenTestCase(test_utils.TestCase,
def test_default_md5(self):
"""The default hash method is md5."""
token = self.examples.SIGNED_TOKEN_SCOPED
- if six.PY3:
- token = token.encode('utf-8')
+ token = token.encode('utf-8')
token_id_default = utils.hash_signed_token(token)
token_id_md5 = utils.hash_signed_token(token, mode='md5')
self.assertThat(token_id_default, matchers.Equals(token_id_md5))
@@ -123,8 +121,7 @@ def test_default_md5(self):
def test_sha256(self):
"""Can also hash with sha256."""
token = self.examples.SIGNED_TOKEN_SCOPED
- if six.PY3:
- token = token.encode('utf-8')
+ token = token.encode('utf-8')
token_id = utils.hash_signed_token(token, mode='sha256')
# sha256 hash is 64 chars.
self.assertThat(token_id, matchers.HasLength(64))
diff --git a/keystoneclient/tests/unit/utils.py b/keystoneclient/tests/unit/utils.py
index 6921b4b0e..4463213b1 100644
--- a/keystoneclient/tests/unit/utils.py
+++ b/keystoneclient/tests/unit/utils.py
@@ -12,6 +12,7 @@
import logging
import sys
+import urllib.parse as urlparse
import uuid
import fixtures
@@ -19,7 +20,6 @@
import requests
import requests_mock
from requests_mock.contrib import fixture
-from six.moves.urllib import parse as urlparse
import testscenarios
import testtools
diff --git a/keystoneclient/tests/unit/v2_0/client_fixtures.py b/keystoneclient/tests/unit/v2_0/client_fixtures.py
index 019b9445d..d3d8bcac3 100644
--- a/keystoneclient/tests/unit/v2_0/client_fixtures.py
+++ b/keystoneclient/tests/unit/v2_0/client_fixtures.py
@@ -9,8 +9,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-
-from __future__ import unicode_literals
import uuid
from keystoneauth1 import fixture
diff --git a/keystoneclient/tests/unit/v2_0/test_auth.py b/keystoneclient/tests/unit/v2_0/test_auth.py
index 64f2ea03d..b73352471 100644
--- a/keystoneclient/tests/unit/v2_0/test_auth.py
+++ b/keystoneclient/tests/unit/v2_0/test_auth.py
@@ -28,7 +28,7 @@ def setUp(self):
self.TEST_RESPONSE_DICT = {
"access": {
"token": {
- "expires": "2020-01-01T00:00:10.000123Z",
+ "expires": "2999-01-01T00:00:10.000123Z",
"id": self.TEST_TOKEN,
"tenant": {
"id": self.TEST_TENANT_ID
@@ -61,7 +61,7 @@ def test_authenticate_success_expired(self):
# Build a new response
TEST_TOKEN = "abcdef"
- resp_b['access']['token']['expires'] = '2020-01-01T00:00:10.000123Z'
+ resp_b['access']['token']['expires'] = '2999-01-01T00:00:10.000123Z'
resp_b['access']['token']['id'] = TEST_TOKEN
# return expired first, and then the new response
diff --git a/keystoneclient/tests/unit/v2_0/test_client.py b/keystoneclient/tests/unit/v2_0/test_client.py
index cddac4d2c..7fe9b1813 100644
--- a/keystoneclient/tests/unit/v2_0/test_client.py
+++ b/keystoneclient/tests/unit/v2_0/test_client.py
@@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import json
import uuid
+from oslo_serialization import jsonutils
+
from keystoneauth1 import fixture
from keystoneauth1 import session as auth_session
@@ -75,10 +76,10 @@ def test_auth_ref_load(self):
password='password',
project_name='exampleproject',
auth_url=self.TEST_URL)
- cache = json.dumps(cl.auth_ref)
+ cache = jsonutils.dumps(cl.auth_ref)
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
- new_client = client.Client(auth_ref=json.loads(cache))
+ new_client = client.Client(auth_ref=jsonutils.loads(cache))
self.assertIsNotNone(new_client.auth_ref)
with self.deprecations.expect_deprecations_here():
self.assertTrue(new_client.auth_ref.scoped)
@@ -100,11 +101,11 @@ def test_auth_ref_load_with_overridden_arguments(self):
password='password',
project_name='exampleproject',
auth_url=self.TEST_URL)
- cache = json.dumps(cl.auth_ref)
+ cache = jsonutils.dumps(cl.auth_ref)
new_auth_url = "http://new-public:5000/v2.0"
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
- new_client = client.Client(auth_ref=json.loads(cache),
+ new_client = client.Client(auth_ref=jsonutils.loads(cache),
auth_url=new_auth_url)
self.assertIsNotNone(new_client.auth_ref)
with self.deprecations.expect_deprecations_here():
diff --git a/keystoneclient/tests/unit/v3/client_fixtures.py b/keystoneclient/tests/unit/v3/client_fixtures.py
index 8e86208e9..e22e7da1c 100644
--- a/keystoneclient/tests/unit/v3/client_fixtures.py
+++ b/keystoneclient/tests/unit/v3/client_fixtures.py
@@ -9,8 +9,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-
-from __future__ import unicode_literals
import uuid
from keystoneauth1 import fixture
diff --git a/keystoneclient/tests/unit/v3/saml2_fixtures.py b/keystoneclient/tests/unit/v3/saml2_fixtures.py
index 3cf2e772a..17c1395a8 100644
--- a/keystoneclient/tests/unit/v3/saml2_fixtures.py
+++ b/keystoneclient/tests/unit/v3/saml2_fixtures.py
@@ -10,9 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
-SP_SOAP_RESPONSE = six.b("""
-""")
+"""
-SAML2_ASSERTION = six.b("""
+SAML2_ASSERTION = b"""
VALUE=
-""")
+"""
UNSCOPED_TOKEN_HEADER = 'UNSCOPED_TOKEN'
diff --git a/keystoneclient/tests/unit/v3/test_access_rules.py b/keystoneclient/tests/unit/v3/test_access_rules.py
new file mode 100644
index 000000000..d3e22f8dd
--- /dev/null
+++ b/keystoneclient/tests/unit/v3/test_access_rules.py
@@ -0,0 +1,41 @@
+# 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 uuid
+
+from keystoneclient import exceptions
+from keystoneclient.tests.unit.v3 import utils
+from keystoneclient.v3 import access_rules
+
+
+class AccessRuleTests(utils.ClientTestCase, utils.CrudTests):
+ def setUp(self):
+ super(AccessRuleTests, self).setUp()
+ self.key = 'access_rule'
+ self.collection_key = 'access_rules'
+ self.model = access_rules.AccessRule
+ self.manager = self.client.access_rules
+ self.path_prefix = 'users/%s' % self.TEST_USER_ID
+
+ def new_ref(self, **kwargs):
+ kwargs = super(AccessRuleTests, self).new_ref(**kwargs)
+ kwargs.setdefault('path', uuid.uuid4().hex)
+ kwargs.setdefault('method', uuid.uuid4().hex)
+ kwargs.setdefault('service', uuid.uuid4().hex)
+ return kwargs
+
+ def test_update(self):
+ self.assertRaises(exceptions.MethodNotImplemented, self.manager.update)
+
+ def test_create(self):
+ self.assertRaises(exceptions.MethodNotImplemented, self.manager.create)
diff --git a/keystoneclient/tests/unit/v3/test_application_credentials.py b/keystoneclient/tests/unit/v3/test_application_credentials.py
index be3c62ac0..6e4bba3e6 100644
--- a/keystoneclient/tests/unit/v3/test_application_credentials.py
+++ b/keystoneclient/tests/unit/v3/test_application_credentials.py
@@ -98,6 +98,27 @@ def test_create_unrestricted(self):
super(ApplicationCredentialTests, self).test_create(ref=ref,
req_ref=req_ref)
+ def test_create_with_access_rules(self):
+ ref = self.new_ref(user=uuid.uuid4().hex)
+ access_rules = [
+ {
+ 'method': 'GET',
+ 'path': '/v3/projects',
+ 'service': 'identity'
+ }
+ ]
+ ref['access_rules'] = access_rules
+ req_ref = ref.copy()
+ req_ref.pop('id')
+ user = req_ref.pop('user')
+
+ self.stub_entity('POST',
+ ['users', user, self.collection_key],
+ status_code=201, entity=req_ref)
+
+ super(ApplicationCredentialTests, self).test_create(ref=ref,
+ req_ref=req_ref)
+
def test_get(self):
ref = self.new_ref(user=uuid.uuid4().hex)
diff --git a/keystoneclient/tests/unit/v3/test_auth.py b/keystoneclient/tests/unit/v3/test_auth.py
index 6549080f3..d3c44adc7 100644
--- a/keystoneclient/tests/unit/v3/test_auth.py
+++ b/keystoneclient/tests/unit/v3/test_auth.py
@@ -28,7 +28,7 @@ def setUp(self):
"password"
],
- "expires_at": "2020-01-01T00:00:10.000123Z",
+ "expires_at": "2999-01-01T00:00:10.000123Z",
"project": {
"domain": {
"id": self.TEST_DOMAIN_ID,
@@ -232,7 +232,7 @@ def test_auth_url_token_authentication(self):
self.stub_auth(json=self.TEST_RESPONSE_DICT)
self.stub_url('GET', [fake_url], json=fake_resp,
- base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+ base_url=self.TEST_PUBLIC_IDENTITY_ENDPOINT)
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
@@ -335,7 +335,7 @@ def test_allow_override_of_auth_token(self):
self.stub_auth(json=self.TEST_RESPONSE_DICT)
self.stub_url('GET', [fake_url], json=fake_resp,
- base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
+ base_url=self.TEST_PUBLIC_IDENTITY_ENDPOINT)
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
diff --git a/keystoneclient/tests/unit/v3/test_auth_manager.py b/keystoneclient/tests/unit/v3/test_auth_manager.py
index 18579607a..dec8b0c05 100644
--- a/keystoneclient/tests/unit/v3/test_auth_manager.py
+++ b/keystoneclient/tests/unit/v3/test_auth_manager.py
@@ -62,3 +62,17 @@ def test_get_domains(self):
for d in domains:
self.assertIsInstance(d, auth.Domain)
+
+ def test_get_systems(self):
+ body = {'system': [{
+ 'all': True,
+ }]}
+
+ self.stub_url('GET', ['auth', 'system'], json=body)
+
+ systems = self.client.auth.systems()
+ system = systems[0]
+
+ self.assertEqual(1, len(systems))
+ self.assertIsInstance(system, auth.System)
+ self.assertTrue(system.all)
diff --git a/keystoneclient/tests/unit/v3/test_auth_oidc.py b/keystoneclient/tests/unit/v3/test_auth_oidc.py
index b0140dd07..278800bca 100644
--- a/keystoneclient/tests/unit/v3/test_auth_oidc.py
+++ b/keystoneclient/tests/unit/v3/test_auth_oidc.py
@@ -10,10 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+import urllib.parse
import uuid
from oslo_config import fixture as config
-from six.moves import urllib
+
import testtools
from keystoneclient.auth import conf
diff --git a/keystoneclient/tests/unit/v3/test_auth_saml2.py b/keystoneclient/tests/unit/v3/test_auth_saml2.py
index b74983af9..8c2f67daa 100644
--- a/keystoneclient/tests/unit/v3/test_auth_saml2.py
+++ b/keystoneclient/tests/unit/v3/test_auth_saml2.py
@@ -11,12 +11,12 @@
# under the License.
import os
+import urllib.parse
import uuid
from lxml import etree
from oslo_config import fixture as config
import requests
-from six.moves import urllib
from keystoneclient.auth import conf
from keystoneclient.contrib.auth.v3 import saml2
@@ -106,28 +106,7 @@ def setUp(self):
self.TEST_USER, self.TEST_TOKEN)
def test_conf_params(self):
- section = uuid.uuid4().hex
- identity_provider = uuid.uuid4().hex
- identity_provider_url = uuid.uuid4().hex
- username = uuid.uuid4().hex
- password = uuid.uuid4().hex
- self.conf_fixture.config(auth_section=section, group=self.GROUP)
- conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP)
-
- self.conf_fixture.register_opts(saml2.Saml2UnscopedToken.get_options(),
- group=section)
- self.conf_fixture.config(auth_plugin='v3unscopedsaml',
- identity_provider=identity_provider,
- identity_provider_url=identity_provider_url,
- username=username,
- password=password,
- group=section)
-
- a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP)
- self.assertEqual(identity_provider, a.identity_provider)
- self.assertEqual(identity_provider_url, a.identity_provider_url)
- self.assertEqual(username, a.username)
- self.assertEqual(password, a.password)
+ pass
def test_initial_sp_call(self):
"""Test initial call, expect SOAP message."""
@@ -465,31 +444,7 @@ def setUp(self):
self.ADFS_FAULT = _load_xml('ADFS_fault.xml')
def test_conf_params(self):
- section = uuid.uuid4().hex
- identity_provider = uuid.uuid4().hex
- identity_provider_url = uuid.uuid4().hex
- sp_endpoint = uuid.uuid4().hex
- username = uuid.uuid4().hex
- password = uuid.uuid4().hex
- self.conf_fixture.config(auth_section=section, group=self.GROUP)
- conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP)
-
- self.conf_fixture.register_opts(saml2.ADFSUnscopedToken.get_options(),
- group=section)
- self.conf_fixture.config(auth_plugin='v3unscopedadfs',
- identity_provider=identity_provider,
- identity_provider_url=identity_provider_url,
- service_provider_endpoint=sp_endpoint,
- username=username,
- password=password,
- group=section)
-
- a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP)
- self.assertEqual(identity_provider, a.identity_provider)
- self.assertEqual(identity_provider_url, a.identity_provider_url)
- self.assertEqual(sp_endpoint, a.service_provider_endpoint)
- self.assertEqual(username, a.username)
- self.assertEqual(password, a.password)
+ pass
def test_get_adfs_security_token(self):
"""Test ADFSUnscopedToken._get_adfs_security_token()."""
diff --git a/keystoneclient/tests/unit/v3/test_client.py b/keystoneclient/tests/unit/v3/test_client.py
index feb921a54..82088fdfc 100644
--- a/keystoneclient/tests/unit/v3/test_client.py
+++ b/keystoneclient/tests/unit/v3/test_client.py
@@ -11,9 +11,9 @@
# under the License.
import copy
-import json
import uuid
+from oslo_serialization import jsonutils
from keystoneauth1 import session as auth_session
from keystoneclient.auth import token_endpoint
@@ -90,10 +90,10 @@ def test_auth_ref_load(self):
password='password',
project_id=token.project_id,
auth_url=self.TEST_URL)
- cache = json.dumps(c.auth_ref)
+ cache = jsonutils.dumps(c.auth_ref)
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
- new_client = client.Client(auth_ref=json.loads(cache))
+ new_client = client.Client(auth_ref=jsonutils.loads(cache))
self.assertIsNotNone(new_client.auth_ref)
self.assertFalse(new_client.auth_ref.domain_scoped)
self.assertTrue(new_client.auth_ref.project_scoped)
@@ -124,10 +124,10 @@ def test_auth_ref_load_with_overridden_arguments(self):
password='password',
project_id=project_id,
auth_url=self.TEST_URL)
- cache = json.dumps(c.auth_ref)
+ cache = jsonutils.dumps(c.auth_ref)
# Creating a HTTPClient not using session is deprecated.
with self.deprecations.expect_deprecations_here():
- new_client = client.Client(auth_ref=json.loads(cache),
+ new_client = client.Client(auth_ref=jsonutils.loads(cache),
auth_url=new_auth_url)
self.assertIsNotNone(new_client.auth_ref)
self.assertFalse(new_client.auth_ref.domain_scoped)
diff --git a/keystoneclient/tests/unit/v3/test_federation.py b/keystoneclient/tests/unit/v3/test_federation.py
index a760ed7d8..08391c7c1 100644
--- a/keystoneclient/tests/unit/v3/test_federation.py
+++ b/keystoneclient/tests/unit/v3/test_federation.py
@@ -11,6 +11,7 @@
# under the License.
import copy
+import fixtures
import uuid
from keystoneauth1 import exceptions
@@ -18,7 +19,6 @@
from keystoneauth1.identity import v3
from keystoneauth1 import session
from keystoneauth1.tests.unit import k2k_fixtures
-import six
from testtools import matchers
from keystoneclient import access
@@ -422,7 +422,7 @@ def _mock_k2k_flow_urls(self):
self.requests_mock.register_uri(
'POST',
self.REQUEST_ECP_URL,
- content=six.b(k2k_fixtures.ECP_ENVELOPE),
+ content=k2k_fixtures.ECP_ENVELOPE.encode(),
headers={'Content-Type': 'application/vnd.paos+xml'},
status_code=200)
@@ -432,7 +432,7 @@ def _mock_k2k_flow_urls(self):
self.requests_mock.register_uri(
'POST',
self.SP_URL,
- content=six.b(k2k_fixtures.TOKEN_BASED_ECP),
+ content=k2k_fixtures.TOKEN_BASED_ECP.encode(),
headers={'Content-Type': 'application/vnd.paos+xml'},
status_code=302)
@@ -582,3 +582,244 @@ def test_create(self):
req_ref[attr],
'Expected different %s' % attr)
self.assertEntityRequestBodyIs(req_ref)
+
+
+class IdentityProviderRequestIdTests(utils.TestRequestId):
+
+ def setUp(self):
+ super(IdentityProviderRequestIdTests, self).setUp()
+ self.mgr = identity_providers.IdentityProviderManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_identity_provider(self):
+ body = {"identity_provider": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get("admin")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/admin')
+
+ def test_list_identity_provider(self):
+ body = {"identity_providers": [{"name": "admin"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.list()
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('OS-FEDERATION/identity_providers?')
+
+ def test_create_identity_provider(self):
+ body = {"identity_provider": {"name": "admin"}}
+ self._mock_request_method(method='post', body=body)
+ put_mock = self._mock_request_method(method='put', body=body)
+
+ response = self.mgr.create(id="admin", description='fake')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ put_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/admin',
+ body={'identity_provider': {'description': 'fake'}})
+
+ def test_update_identity_provider(self):
+ body = {"identity_provider": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+ self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.update("admin")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/admin', body={
+ 'identity_provider': {}})
+
+ def test_delete_identity_provider(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("admin")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/admin')
+
+
+class MappingRequestIdTests(utils.TestRequestId):
+
+ def setUp(self):
+ super(MappingRequestIdTests, self).setUp()
+ self.mgr = mappings.MappingManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_mapping(self):
+ body = {"mapping": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get("admin")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('OS-FEDERATION/mappings/admin')
+
+ def test_list_mapping(self):
+ body = {"mappings": [{"name": "admin"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.list()
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('OS-FEDERATION/mappings?')
+
+ def test_create_mapping(self):
+ body = {"mapping": {"name": "admin"}}
+ self._mock_request_method(method='post', body=body)
+ put_mock = self._mock_request_method(method='put', body=body)
+
+ response = self.mgr.create(mapping_id="admin", description='fake')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ put_mock.assert_called_once_with(
+ 'OS-FEDERATION/mappings/admin', body={
+ 'mapping': {'description': 'fake'}})
+
+ def test_update_mapping(self):
+ body = {"mapping": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+ self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.update("admin")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with(
+ 'OS-FEDERATION/mappings/admin', body={'mapping': {}})
+
+ def test_delete_mapping(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("admin")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('OS-FEDERATION/mappings/admin')
+
+
+class ProtocolRequestIdTests(utils.TestRequestId):
+
+ def setUp(self):
+ super(ProtocolRequestIdTests, self).setUp()
+ self.mgr = protocols.ProtocolManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_protocol(self):
+ body = {"protocol": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get("admin", "protocol")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/admin/protocols/protocol')
+
+ def test_list_protocol(self):
+ body = {"protocols": [{"name": "admin"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.list("identity_provider")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/identity_provider/protocols?')
+
+ def test_create_protocol(self):
+ body = {"protocol": {"name": "admin"}}
+ self._mock_request_method(method='post', body=body)
+ put_mock = self._mock_request_method(method='put', body=body)
+
+ response = self.mgr.create(
+ protocol_id="admin", identity_provider='fake', mapping='fake')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ put_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/fake/protocols/admin', body={
+ 'protocol': {'mapping_id': 'fake'}})
+
+ def test_update_protocol(self):
+ body = {"protocol": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+ self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.update(protocol="admin", identity_provider='fake',
+ mapping='fake')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/fake/protocols/admin', body={
+ 'protocol': {'mapping_id': 'fake'}})
+
+ def test_delete_protocol(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("identity_provider", "protocol")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/identity_providers/'
+ 'identity_provider/protocols/protocol')
+
+
+class ServiceProviderRequestIdTests(utils.TestRequestId):
+
+ def setUp(self):
+ super(ServiceProviderRequestIdTests, self).setUp()
+ self.mgr = service_providers.ServiceProviderManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_service_provider(self):
+ body = {"service_provider": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get("provider")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/service_providers/provider')
+
+ def test_list_service_provider(self):
+ body = {"service_providers": [{"name": "admin"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.list()
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('OS-FEDERATION/service_providers?')
+
+ def test_create_service_provider(self):
+ body = {"service_provider": {"name": "admin"}}
+ self._mock_request_method(method='post', body=body)
+ put_mock = self._mock_request_method(method='put', body=body)
+
+ response = self.mgr.create(id='provider')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ put_mock.assert_called_once_with(
+ 'OS-FEDERATION/service_providers/provider', body={
+ 'service_provider': {}})
+
+ def test_update_service_provider(self):
+ body = {"service_provider": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+ self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.update("provider")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with(
+ 'OS-FEDERATION/service_providers/provider', body={
+ 'service_provider': {}})
+
+ def test_delete_service_provider(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("provider")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ 'OS-FEDERATION/service_providers/provider')
diff --git a/keystoneclient/tests/unit/v3/test_oauth1.py b/keystoneclient/tests/unit/v3/test_oauth1.py
index f939244dd..a15d94b83 100644
--- a/keystoneclient/tests/unit/v3/test_oauth1.py
+++ b/keystoneclient/tests/unit/v3/test_oauth1.py
@@ -11,11 +11,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from unittest import mock
+
+import fixtures
+from urllib import parse as urlparse
import uuid
-import mock
-import six
-from six.moves.urllib import parse as urlparse
from testtools import matchers
from keystoneclient import session
@@ -104,7 +105,7 @@ def _validate_oauth_headers(self, auth_header, oauth_client):
self.assertEqual('HMAC-SHA1', parameters['oauth_signature_method'])
self.assertEqual('1.0', parameters['oauth_version'])
- self.assertIsInstance(parameters['oauth_nonce'], six.string_types)
+ self.assertIsInstance(parameters['oauth_nonce'], str)
self.assertEqual(oauth_client.client_key,
parameters['oauth_consumer_key'])
if oauth_client.resource_owner_key:
@@ -277,6 +278,53 @@ def test_oauth_authenticate_success(self):
oauth_client)
+class OauthRequestIdTests(utils.TestRequestId, TokenTests):
+
+ def setUp(self):
+ super(OauthRequestIdTests, self).setUp()
+ self.mgr = consumers.ConsumerManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_consumers(self):
+ body = {"consumer": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get("admin")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('/OS-OAUTH1/consumers/admin')
+
+ def test_create_consumers(self):
+ body = {"consumer": {"name": "admin"}}
+ post_mock = self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.create(name="admin", description="fake")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ post_mock.assert_called_once_with('/OS-OAUTH1/consumers', body={
+ 'consumer': {'name': 'admin', 'description': 'fake'}})
+
+ def test_update_consumers(self):
+ body = {"consumer": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+ self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.update("admin", "demo")
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with('/OS-OAUTH1/consumers/admin', body={
+ 'consumer': {'description': 'demo'}})
+
+ def test_delete_consumers(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("admin")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with('/OS-OAUTH1/consumers/admin')
+
+
class TestOAuthLibModule(utils.TestCase):
def test_no_oauthlib_installed(self):
diff --git a/keystoneclient/tests/unit/v3/test_projects.py b/keystoneclient/tests/unit/v3/test_projects.py
index 8933bbfd7..99186f17f 100644
--- a/keystoneclient/tests/unit/v3/test_projects.py
+++ b/keystoneclient/tests/unit/v3/test_projects.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import fixtures
import uuid
from keystoneauth1 import exceptions as ksa_exceptions
@@ -54,8 +55,7 @@ def test_list_projects_for_domain(self):
ref_list = [self.new_ref(), self.new_ref()]
domain_id = uuid.uuid4().hex
- self.stub_entity('GET', [self.collection_key],
- entity=ref_list)
+ self.stub_entity('GET', [self.collection_key], entity=ref_list)
returned_list = self.manager.list(domain=domain_id)
self.assertEqual(len(ref_list), len(returned_list))
@@ -63,6 +63,18 @@ def test_list_projects_for_domain(self):
self.assertQueryStringIs('domain_id=%s' % domain_id)
+ def test_list_projects_for_parent(self):
+ ref_list = [self.new_ref(), self.new_ref()]
+ parent_id = uuid.uuid4().hex
+
+ self.stub_entity('GET', [self.collection_key], entity=ref_list)
+
+ returned_list = self.manager.list(parent=parent_id)
+ self.assertEqual(len(ref_list), len(returned_list))
+ [self.assertIsInstance(r, self.model) for r in returned_list]
+
+ self.assertQueryStringIs('parent_id=%s' % parent_id)
+
def test_create_with_parent(self):
parent_ref = self.new_ref()
parent_ref['parent_id'] = uuid.uuid4().hex
@@ -395,3 +407,63 @@ def _build_project_response(self, tags):
"name": project_id}
]}
return ret
+
+
+class ProjectsRequestIdTests(utils.TestRequestId):
+
+ url = "/projects"
+
+ def setUp(self):
+ super(ProjectsRequestIdTests, self).setUp()
+ self.mgr = projects.ProjectManager(self.client)
+ self.mgr.resource_class = projects.Project
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_get_project(self):
+ body = {"project": {"name": "admin"}}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get(project='admin')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(self.url + '/admin')
+
+ def test_create_project(self):
+ body = {"project": {"name": "admin", "domain": "admin"}}
+ post_mock = self._mock_request_method(method='post', body=body)
+
+ response = self.mgr.create('admin', 'admin')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ post_mock.assert_called_once_with(self.url, body={'project': {
+ 'name': 'admin', 'enabled': True, 'domain_id': 'admin'}})
+
+ def test_list_project(self):
+ body = {"projects": [{"name": "admin"}, {"name": "admin"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ returned_list = self.mgr.list()
+ self.assertEqual(returned_list.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(self.url + '?')
+
+ def test_update_project(self):
+ body = {"project": {"name": "admin"}}
+ patch_mock = self._mock_request_method(method='patch', body=body)
+
+ put_mock = self._mock_request_method(method='put', body=body)
+
+ response = self.mgr.update("admin", domain='demo')
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ patch_mock.assert_called_once_with(self.url + '/admin', body={
+ 'project': {'domain_id': 'demo'}})
+ self.assertFalse(put_mock.called)
+
+ def test_delete_project(self):
+ get_mock = self._mock_request_method(method='delete')
+
+ _, resp = self.mgr.delete("admin")
+ self.assertEqual(resp.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(self.url + '/admin')
diff --git a/keystoneclient/tests/unit/v3/test_role_assignments.py b/keystoneclient/tests/unit/v3/test_role_assignments.py
index 45dd13d6c..39b4b2355 100644
--- a/keystoneclient/tests/unit/v3/test_role_assignments.py
+++ b/keystoneclient/tests/unit/v3/test_role_assignments.py
@@ -265,7 +265,7 @@ def test_include_names_assignments_list(self):
ref_list = self.TEST_ALL_RESPONSE_LIST
self.stub_entity('GET',
[self.collection_key,
- '?include_names'],
+ '?include_names=True'],
entity=ref_list)
returned_list = self.manager.list(include_names=True)
diff --git a/keystoneclient/tests/unit/v3/test_roles.py b/keystoneclient/tests/unit/v3/test_roles.py
index 51d9fc73f..0e531e736 100644
--- a/keystoneclient/tests/unit/v3/test_roles.py
+++ b/keystoneclient/tests/unit/v3/test_roles.py
@@ -656,7 +656,7 @@ def test_check(self):
implied_role_id = uuid.uuid4().hex
self.stub_url('HEAD',
['roles', prior_role_id, 'implies', implied_role_id],
- status_code=200)
+ status_code=204)
result = self.manager.check(prior_role_id, implied_role_id)
self.assertTrue(result)
diff --git a/keystoneclient/tests/unit/v3/test_simple_cert.py b/keystoneclient/tests/unit/v3/test_simple_cert.py
index 1c4a245d2..a059f08d7 100644
--- a/keystoneclient/tests/unit/v3/test_simple_cert.py
+++ b/keystoneclient/tests/unit/v3/test_simple_cert.py
@@ -11,10 +11,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+import fixtures
import testresources
from keystoneclient.tests.unit import client_fixtures
from keystoneclient.tests.unit.v3 import utils
+from keystoneclient.v3.contrib import simple_cert
class SimpleCertTests(utils.ClientTestCase, testresources.ResourcedTestCase):
@@ -36,5 +38,36 @@ def test_get_certificates(self):
self.assertEqual(self.examples.SIGNING_CERT, res)
+class SimpleCertRequestIdTests(utils.TestRequestId):
+
+ def setUp(self):
+ super(SimpleCertRequestIdTests, self).setUp()
+ self.mgr = simple_cert.SimpleCertManager(self.client)
+
+ def _mock_request_method(self, method=None, body=None):
+ return self.useFixture(fixtures.MockPatchObject(
+ self.client, method, autospec=True,
+ return_value=(self.resp, body))
+ ).mock
+
+ def test_list_ca_certificates(self):
+ body = {"certificates": [{"name": "admin"}, {"name": "admin2"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get_ca_certificates()
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ '/OS-SIMPLE-CERT/ca', authenticated=False)
+
+ def test_list_certificates(self):
+ body = {"certificates": [{"name": "admin"}, {"name": "admin2"}]}
+ get_mock = self._mock_request_method(method='get', body=body)
+
+ response = self.mgr.get_certificates()
+ self.assertEqual(response.request_ids[0], self.TEST_REQUEST_ID)
+ get_mock.assert_called_once_with(
+ '/OS-SIMPLE-CERT/certificates', authenticated=False)
+
+
def load_tests(loader, tests, pattern):
return testresources.OptimisingTestSuite(tests)
diff --git a/keystoneclient/tests/unit/v3/test_users.py b/keystoneclient/tests/unit/v3/test_users.py
index e0a34461e..a7f03f9ce 100644
--- a/keystoneclient/tests/unit/v3/test_users.py
+++ b/keystoneclient/tests/unit/v3/test_users.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
import uuid
from keystoneclient import exceptions
diff --git a/keystoneclient/tests/unit/v3/utils.py b/keystoneclient/tests/unit/v3/utils.py
index d9cb5a473..cb3839a9c 100644
--- a/keystoneclient/tests/unit/v3/utils.py
+++ b/keystoneclient/tests/unit/v3/utils.py
@@ -10,12 +10,16 @@
# License for the specific language governing permissions and limitations
# under the License.
+import requests
import uuid
-from six.moves.urllib import parse as urlparse
+from urllib import parse as urlparse
+from keystoneauth1.identity import v3
+from keystoneauth1 import session
from keystoneclient.tests.unit import client_fixtures
from keystoneclient.tests.unit import utils
+from keystoneclient.v3 import client
def parameterize(ref):
@@ -44,6 +48,7 @@ class UnauthenticatedTestCase(utils.TestCase):
class TestCase(UnauthenticatedTestCase):
TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v3"
+ TEST_PUBLIC_IDENTITY_ENDPOINT = "http://127.0.0.1:5000/v3"
TEST_SERVICE_CATALOG = [{
"endpoints": [{
@@ -221,6 +226,8 @@ def assertEntityRequestBodyIs(self, entity):
self.assertRequestBodyIs(json=self.encode(entity))
def test_create(self, ref=None, req_ref=None):
+ deprecations = self.useFixture(client_fixtures.Deprecations())
+ deprecations.expect_deprecations()
ref = ref or self.new_ref()
manager_ref = ref.copy()
manager_ref.pop('id')
@@ -273,7 +280,7 @@ def _get_expected_path(self, expected_path=None):
return expected_path
def test_list_by_id(self, ref=None, **filter_kwargs):
- """Test ``entities.list(id=x)`` being rewritten as ``GET /v3/entities/x``.
+ """Test ``entities.list(id=x)`` being rewritten as ``GET /v3/entities/x``. # noqa
This tests an edge case of each manager's list() implementation, to
ensure that it "does the right thing" when users call ``.list()``
@@ -343,6 +350,8 @@ def test_find(self, ref=None):
self.assertQueryStringIs('')
def test_update(self, ref=None, req_ref=None):
+ deprecations = self.useFixture(client_fixtures.Deprecations())
+ deprecations.expect_deprecations()
ref = ref or self.new_ref()
self.stub_entity('PATCH', id=ref['id'], entity=ref)
@@ -371,3 +380,17 @@ def test_delete(self, ref=None):
self.stub_entity('DELETE', id=ref['id'], status_code=204)
self.manager.delete(ref['id'])
+
+
+class TestRequestId(TestCase):
+ resp = requests.Response()
+ TEST_REQUEST_ID = uuid.uuid4().hex
+ resp.headers['x-openstack-request-id'] = TEST_REQUEST_ID
+
+ def setUp(self):
+ super(TestRequestId, self).setUp()
+ auth = v3.Token(auth_url='http://127.0.0.1:5000',
+ token=self.TEST_TOKEN)
+ session_ = session.Session(auth=auth)
+ self.client = client.Client(session=session_,
+ include_metadata='True')._adapter
diff --git a/keystoneclient/utils.py b/keystoneclient/utils.py
index d71974b55..1c31f2bd3 100644
--- a/keystoneclient/utils.py
+++ b/keystoneclient/utils.py
@@ -16,7 +16,6 @@
from keystoneauth1 import exceptions as ksa_exceptions
from oslo_utils import timeutils
-import six
from keystoneclient import exceptions as ksc_exceptions
@@ -27,12 +26,12 @@ def find_resource(manager, name_or_id):
try:
return manager.get(name_or_id)
except (ksa_exceptions.NotFound): # nosec(cjschaef): try to find
- # 'name_or_id' as a six.binary_type instead
+ # 'name_or_id' as a bytes instead
pass
# finally try to find entity by name
try:
- if isinstance(name_or_id, six.binary_type):
+ if isinstance(name_or_id, bytes):
name_or_id = name_or_id.decode('utf-8', 'strict')
return manager.find(name=name_or_id)
except ksa_exceptions.NotFound:
diff --git a/keystoneclient/v2_0/tenants.py b/keystoneclient/v2_0/tenants.py
index 1b43990dd..91731c45e 100644
--- a/keystoneclient/v2_0/tenants.py
+++ b/keystoneclient/v2_0/tenants.py
@@ -15,7 +15,7 @@
# under the License.
from keystoneauth1 import plugin
-from six.moves import urllib
+import urllib.parse
from keystoneclient import base
from keystoneclient import exceptions
diff --git a/keystoneclient/v2_0/users.py b/keystoneclient/v2_0/users.py
index f663626ac..706dafcdc 100644
--- a/keystoneclient/v2_0/users.py
+++ b/keystoneclient/v2_0/users.py
@@ -14,9 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six.moves import urllib
-
from keystoneclient import base
+import urllib.parse
class User(base.Resource):
diff --git a/keystoneclient/v3/access_rules.py b/keystoneclient/v3/access_rules.py
new file mode 100644
index 000000000..78fd0159e
--- /dev/null
+++ b/keystoneclient/v3/access_rules.py
@@ -0,0 +1,118 @@
+# Copyright 2019 SUSE LLC
+#
+# 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.
+
+from keystoneclient import base
+from keystoneclient import exceptions
+from keystoneclient.i18n import _
+
+
+class AccessRule(base.Resource):
+ """Represents an Identity access rule for application credentials.
+
+ Attributes:
+ * id: a uuid that identifies the access rule
+ * method: The request method that the application credential is
+ permitted to use for a given API endpoint
+ * path: The API path that the application credential is permitted to
+ access
+ * service: The service type identifier for the service that the
+ application credential is permitted to access
+
+ """
+
+ pass
+
+
+class AccessRuleManager(base.CrudManager):
+ """Manager class for manipulating Identity access rules."""
+
+ resource_class = AccessRule
+ collection_key = 'access_rules'
+ key = 'access_rule'
+
+ def get(self, access_rule, user=None):
+ """Retrieve an access rule.
+
+ :param access_rule: the access rule to be retrieved from the
+ server
+ :type access_rule: str or
+ :class:`keystoneclient.v3.access_rules.AccessRule`
+ :param string user: User ID
+
+ :returns: the specified access rule
+ :rtype:
+ :class:`keystoneclient.v3.access_rules.AccessRule`
+
+ """
+ user = user or self.client.user_id
+ self.base_url = '/users/%(user)s' % {'user': user}
+
+ return super(AccessRuleManager, self).get(
+ access_rule_id=base.getid(access_rule))
+
+ def list(self, user=None, **kwargs):
+ """List access rules.
+
+ :param string user: User ID
+
+ :returns: a list of access rules
+ :rtype: list of
+ :class:`keystoneclient.v3.access_rules.AccessRule`
+ """
+ user = user or self.client.user_id
+ self.base_url = '/users/%(user)s' % {'user': user}
+
+ return super(AccessRuleManager, self).list(**kwargs)
+
+ def find(self, user=None, **kwargs):
+ """Find an access rule with attributes matching ``**kwargs``.
+
+ :param string user: User ID
+
+ :returns: a list of matching access rules
+ :rtype: list of
+ :class:`keystoneclient.v3.access_rules.AccessRule`
+ """
+ user = user or self.client.user_id
+ self.base_url = '/users/%(user)s' % {'user': user}
+
+ return super(AccessRuleManager, self).find(**kwargs)
+
+ def delete(self, access_rule, user=None):
+ """Delete an access rule.
+
+ :param access_rule: the access rule to be deleted
+ :type access_rule: str or
+ :class:`keystoneclient.v3.access_rules.AccessRule`
+ :param string user: User ID
+
+ :returns: response object with 204 status
+ :rtype: :class:`requests.models.Response`
+
+ """
+ user = user or self.client.user_id
+ self.base_url = '/users/%(user)s' % {'user': user}
+
+ return super(AccessRuleManager, self).delete(
+ access_rule_id=base.getid(access_rule))
+
+ def update(self):
+ raise exceptions.MethodNotImplemented(
+ _('Access rules are immutable, updating is not'
+ ' supported.'))
+
+ def create(self):
+ raise exceptions.MethodNotImplemented(
+ _('Access rules can only be created as attributes of application '
+ 'credentials.'))
diff --git a/keystoneclient/v3/application_credentials.py b/keystoneclient/v3/application_credentials.py
index 0fc94aff7..3e9286279 100644
--- a/keystoneclient/v3/application_credentials.py
+++ b/keystoneclient/v3/application_credentials.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
from keystoneclient import base
from keystoneclient import exceptions
from keystoneclient.i18n import _
@@ -33,6 +31,8 @@ class ApplicationCredential(base.Resource):
* roles: role assignments on the project
* unrestricted: whether the application credential has restrictions
applied
+ * access_rules: a list of access rules defining what API requests the
+ application credential may be used for
"""
@@ -48,7 +48,7 @@ class ApplicationCredentialManager(base.CrudManager):
def create(self, name, user=None, secret=None, description=None,
expires_at=None, roles=None,
- unrestricted=False, **kwargs):
+ unrestricted=False, access_rules=None, **kwargs):
"""Create a credential.
:param string name: application credential name
@@ -60,6 +60,7 @@ def create(self, name, user=None, secret=None, description=None,
or a list of dicts specifying role name and domain
:param bool unrestricted: whether the application credential has
restrictions applied
+ :param List access_rules: a list of dicts representing access rules
:returns: the created application credential
:rtype:
@@ -75,7 +76,7 @@ def create(self, name, user=None, secret=None, description=None,
if not isinstance(roles, list):
roles = [roles]
for role in roles:
- if isinstance(role, six.string_types):
+ if isinstance(role, str):
role_list.extend([{'id': role}])
elif isinstance(role, dict):
role_list.extend([role])
@@ -99,6 +100,7 @@ def create(self, name, user=None, secret=None, description=None,
expires_at=expires_str,
roles=role_list,
unrestricted=unrestricted,
+ access_rules=access_rules,
**kwargs)
def get(self, application_credential, user=None):
@@ -135,7 +137,7 @@ def list(self, user=None, **kwargs):
return super(ApplicationCredentialManager, self).list(**kwargs)
def find(self, user=None, **kwargs):
- """Find an application credential with attributes matching ``**kwargs``.
+ """Find an application credential with attributes matching ``**kwargs``. # noqa
:param string user: User ID
diff --git a/keystoneclient/v3/auth.py b/keystoneclient/v3/auth.py
index 6b8d6e9d1..4d85e24ea 100644
--- a/keystoneclient/v3/auth.py
+++ b/keystoneclient/v3/auth.py
@@ -16,10 +16,12 @@
from keystoneclient import base
from keystoneclient.v3 import domains
from keystoneclient.v3 import projects
+from keystoneclient.v3 import system
Domain = domains.Domain
Project = projects.Project
+System = system.System
class AuthManager(base.Manager):
@@ -31,6 +33,7 @@ class AuthManager(base.Manager):
_PROJECTS_URL = '/auth/projects'
_DOMAINS_URL = '/auth/domains'
+ _SYSTEM_URL = '/auth/system'
def projects(self):
"""List projects that the specified token can be rescoped to.
@@ -67,3 +70,23 @@ def domains(self):
'domains',
obj_class=Domain,
endpoint_filter=endpoint_filter)
+
+ def systems(self):
+ """List Systems that the specified token can be rescoped to.
+
+ At the moment this is either empty or "all".
+
+ :returns: a list of systems.
+ :rtype: list of :class:`keystoneclient.v3.systems.System`.
+
+ """
+ try:
+ return self._list(self._SYSTEM_URL,
+ 'system',
+ obj_class=System)
+ except exceptions.EndpointNotFound:
+ endpoint_filter = {'interface': plugin.AUTH_INTERFACE}
+ return self._list(self._SYSTEM_URL,
+ 'system',
+ obj_class=System,
+ endpoint_filter=endpoint_filter)
diff --git a/keystoneclient/v3/client.py b/keystoneclient/v3/client.py
index 89ba5ac1b..e99b06549 100644
--- a/keystoneclient/v3/client.py
+++ b/keystoneclient/v3/client.py
@@ -22,6 +22,7 @@
from keystoneclient import exceptions
from keystoneclient import httpclient
from keystoneclient.i18n import _
+from keystoneclient.v3 import access_rules
from keystoneclient.v3 import application_credentials
from keystoneclient.v3 import auth
from keystoneclient.v3.contrib import endpoint_filter
@@ -223,6 +224,9 @@ def __init__(self, **kwargs):
'deprecated as of the 1.7.0 release and may be removed in '
'the 2.0.0 release.', DeprecationWarning)
+ self.access_rules = (
+ access_rules.AccessRuleManager(self._adapter)
+ )
self.application_credentials = (
application_credentials.ApplicationCredentialManager(self._adapter)
)
diff --git a/keystoneclient/v3/contrib/endpoint_policy.py b/keystoneclient/v3/contrib/endpoint_policy.py
index 24148c1ac..c65b1fbc7 100644
--- a/keystoneclient/v3/contrib/endpoint_policy.py
+++ b/keystoneclient/v3/contrib/endpoint_policy.py
@@ -39,17 +39,17 @@ def _act_on_policy_association_for_endpoint(
def create_policy_association_for_endpoint(self, policy, endpoint):
"""Create an association between a policy and an endpoint."""
- self._act_on_policy_association_for_endpoint(
+ return self._act_on_policy_association_for_endpoint(
policy, endpoint, self._put)
def check_policy_association_for_endpoint(self, policy, endpoint):
"""Check an association between a policy and an endpoint."""
- self._act_on_policy_association_for_endpoint(
+ return self._act_on_policy_association_for_endpoint(
policy, endpoint, self._head)
def delete_policy_association_for_endpoint(self, policy, endpoint):
"""Delete an association between a policy and an endpoint."""
- self._act_on_policy_association_for_endpoint(
+ return self._act_on_policy_association_for_endpoint(
policy, endpoint, self._delete)
def _act_on_policy_association_for_service(self, policy, service, action):
@@ -67,17 +67,17 @@ def _act_on_policy_association_for_service(self, policy, service, action):
def create_policy_association_for_service(self, policy, service):
"""Create an association between a policy and a service."""
- self._act_on_policy_association_for_service(
+ return self._act_on_policy_association_for_service(
policy, service, self._put)
def check_policy_association_for_service(self, policy, service):
"""Check an association between a policy and a service."""
- self._act_on_policy_association_for_service(
+ return self._act_on_policy_association_for_service(
policy, service, self._head)
def delete_policy_association_for_service(self, policy, service):
"""Delete an association between a policy and a service."""
- self._act_on_policy_association_for_service(
+ return self._act_on_policy_association_for_service(
policy, service, self._delete)
def _act_on_policy_association_for_region_and_service(
@@ -99,19 +99,19 @@ def _act_on_policy_association_for_region_and_service(
def create_policy_association_for_region_and_service(
self, policy, region, service):
"""Create an association between a policy and a service in a region."""
- self._act_on_policy_association_for_region_and_service(
+ return self._act_on_policy_association_for_region_and_service(
policy, region, service, self._put)
def check_policy_association_for_region_and_service(
self, policy, region, service):
"""Check an association between a policy and a service in a region."""
- self._act_on_policy_association_for_region_and_service(
+ return self._act_on_policy_association_for_region_and_service(
policy, region, service, self._head)
def delete_policy_association_for_region_and_service(
self, policy, region, service):
"""Delete an association between a policy and a service in a region."""
- self._act_on_policy_association_for_region_and_service(
+ return self._act_on_policy_association_for_region_and_service(
policy, region, service, self._delete)
def get_policy_for_endpoint(self, endpoint):
@@ -130,9 +130,10 @@ def get_policy_for_endpoint(self, endpoint):
'endpoint_id': endpoint_id,
'ext_name': self.OS_EP_POLICY_EXT}
- _resp, body = self.client.get(url)
- return policies.Policy(
- self, body[policies.PolicyManager.key], loaded=True)
+ resp, body = self.client.get(url)
+ return self._prepare_return_value(
+ resp, policies.Policy(self, body[policies.PolicyManager.key],
+ loaded=True))
def list_endpoints_for_policy(self, policy):
"""List endpoints with the effective association to a policy.
diff --git a/keystoneclient/v3/contrib/federation/base.py b/keystoneclient/v3/contrib/federation/base.py
index 98567a232..c09bc2267 100644
--- a/keystoneclient/v3/contrib/federation/base.py
+++ b/keystoneclient/v3/contrib/federation/base.py
@@ -14,18 +14,17 @@
from keystoneauth1 import exceptions
from keystoneauth1 import plugin
-import six
from keystoneclient import base
-@six.add_metaclass(abc.ABCMeta)
-class EntityManager(base.Manager):
+class EntityManager(base.Manager, metaclass=abc.ABCMeta):
"""Manager class for listing federated accessible objects."""
resource_class = None
- @abc.abstractproperty
+ @property
+ @abc.abstractmethod
def object_type(self):
raise exceptions.MethodNotImplemented
diff --git a/keystoneclient/v3/contrib/federation/identity_providers.py b/keystoneclient/v3/contrib/federation/identity_providers.py
index 8e009b930..221ec11f4 100644
--- a/keystoneclient/v3/contrib/federation/identity_providers.py
+++ b/keystoneclient/v3/contrib/federation/identity_providers.py
@@ -45,8 +45,8 @@ def create(self, id, **kwargs):
PUT /OS-FEDERATION/identity_providers/$identity_provider
:param id: unique id of the identity provider.
- :param kwargs: optional attributes: description (str), enabled
- (boolean) and remote_ids (list).
+ :param kwargs: optional attributes: description (str), domain_id (str),
+ enabled (boolean) and remote_ids (list).
:returns: an IdentityProvider resource object.
:rtype: :py:class:`keystoneclient.v3.federation.IdentityProvider`
diff --git a/keystoneclient/v3/contrib/federation/saml.py b/keystoneclient/v3/contrib/federation/saml.py
index 9be657a57..435e45dc6 100644
--- a/keystoneclient/v3/contrib/federation/saml.py
+++ b/keystoneclient/v3/contrib/federation/saml.py
@@ -37,7 +37,7 @@ def create_saml_assertion(self, service_provider, token_id):
headers, body = self._create_common_request(service_provider, token_id)
resp, body = self.client.post(SAML2_ENDPOINT, json=body,
headers=headers)
- return resp.text
+ return self._prepare_return_value(resp, resp.text)
def create_ecp_assertion(self, service_provider, token_id):
"""Create an ECP wrapped SAML assertion from a token.
@@ -56,7 +56,7 @@ def create_ecp_assertion(self, service_provider, token_id):
headers, body = self._create_common_request(service_provider, token_id)
resp, body = self.client.post(ECP_ENDPOINT, json=body,
headers=headers)
- return resp.text
+ return self._prepare_return_value(resp, resp.text)
def _create_common_request(self, service_provider, token_id):
headers = {'Content-Type': 'application/json'}
diff --git a/keystoneclient/v3/contrib/oauth1/access_tokens.py b/keystoneclient/v3/contrib/oauth1/access_tokens.py
index 37f194153..a64c5dddc 100644
--- a/keystoneclient/v3/contrib/oauth1/access_tokens.py
+++ b/keystoneclient/v3/contrib/oauth1/access_tokens.py
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import unicode_literals
-
from keystoneauth1 import plugin
from keystoneclient import base
@@ -48,4 +46,5 @@ def create(self, consumer_key, consumer_secret, request_key,
http_method='POST')
resp, body = self.client.post(endpoint, headers=headers)
token = utils.get_oauth_token_from_body(resp.content)
- return self.resource_class(self, token)
+ return self._prepare_return_value(resp,
+ self.resource_class(self, token))
diff --git a/keystoneclient/v3/contrib/oauth1/request_tokens.py b/keystoneclient/v3/contrib/oauth1/request_tokens.py
index 59f06bcba..7494e8349 100644
--- a/keystoneclient/v3/contrib/oauth1/request_tokens.py
+++ b/keystoneclient/v3/contrib/oauth1/request_tokens.py
@@ -11,10 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import unicode_literals
+import urllib.parse as urlparse
from keystoneauth1 import plugin
-from six.moves.urllib import parse as urlparse
from keystoneclient import base
from keystoneclient.v3.contrib.oauth1 import utils
@@ -70,4 +69,5 @@ def create(self, consumer_key, consumer_secret, project):
headers=headers)
resp, body = self.client.post(endpoint, headers=headers)
token = utils.get_oauth_token_from_body(resp.content)
- return self.resource_class(self, token)
+ return self._prepare_return_value(resp,
+ self.resource_class(self, token))
diff --git a/keystoneclient/v3/contrib/oauth1/utils.py b/keystoneclient/v3/contrib/oauth1/utils.py
index 3c5c9d48f..40a0632af 100644
--- a/keystoneclient/v3/contrib/oauth1/utils.py
+++ b/keystoneclient/v3/contrib/oauth1/utils.py
@@ -11,8 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import six
-from six.moves.urllib import parse as urlparse
+import urllib.parse as urlparse
OAUTH_PATH = '/OS-OAUTH1'
@@ -25,8 +24,7 @@ def get_oauth_token_from_body(body):
'oauth_token=12345&oauth_token_secret=67890' with
'oauth_expires_at=2013-03-30T05:27:19.463201' possibly there, too.
"""
- if six.PY3:
- body = body.decode('utf-8')
+ body = body.decode('utf-8')
credentials = urlparse.parse_qs(body)
key = credentials['oauth_token'][0]
diff --git a/keystoneclient/v3/contrib/simple_cert.py b/keystoneclient/v3/contrib/simple_cert.py
index 8168e67a3..6b58b27b3 100644
--- a/keystoneclient/v3/contrib/simple_cert.py
+++ b/keystoneclient/v3/contrib/simple_cert.py
@@ -11,12 +11,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+from keystoneclient import base
+
class SimpleCertManager(object):
"""Manager for the OS-SIMPLE-CERT extension."""
def __init__(self, client):
self._client = client
+ self.mgr = base.Manager(self._client)
def get_ca_certificates(self):
"""Get CA certificates.
@@ -27,7 +30,7 @@ def get_ca_certificates(self):
"""
resp, body = self._client.get('/OS-SIMPLE-CERT/ca',
authenticated=False)
- return resp.text
+ return self.mgr._prepare_return_value(resp, resp.text)
def get_certificates(self):
"""Get signing certificates.
@@ -38,4 +41,4 @@ def get_certificates(self):
"""
resp, body = self._client.get('/OS-SIMPLE-CERT/certificates',
authenticated=False)
- return resp.text
+ return self.mgr._prepare_return_value(resp, resp.text)
diff --git a/keystoneclient/v3/domains.py b/keystoneclient/v3/domains.py
index 221b50f2e..0f542b8b0 100644
--- a/keystoneclient/v3/domains.py
+++ b/keystoneclient/v3/domains.py
@@ -110,7 +110,7 @@ def update(self, domain, name=None,
**kwargs)
def delete(self, domain):
- """"Delete a domain.
+ """Delete a domain.
:param domain: the domain to be deleted on the server.
:type domain: str or :class:`keystoneclient.v3.domains.Domain`
diff --git a/keystoneclient/v3/limits.py b/keystoneclient/v3/limits.py
index 5d298a4a3..52b1b886c 100644
--- a/keystoneclient/v3/limits.py
+++ b/keystoneclient/v3/limits.py
@@ -70,7 +70,9 @@ def create(self, project, service, resource_name, resource_limit,
body = {self.collection_key: [limit_data]}
resp, body = self.client.post('/limits', body=body)
limit = body[self.collection_key].pop()
- return self.resource_class(self, limit)
+ return self._prepare_return_value(resp,
+ self.resource_class(
+ self, limit))
def update(self, limit, project=None, service=None, resource_name=None,
resource_limit=None, description=None, **kwargs):
diff --git a/keystoneclient/v3/policies.py b/keystoneclient/v3/policies.py
index 253d1b1c3..32de94e91 100644
--- a/keystoneclient/v3/policies.py
+++ b/keystoneclient/v3/policies.py
@@ -112,7 +112,7 @@ def update(self, policy, blob=None, type=None, **kwargs):
**kwargs)
def delete(self, policy):
- """"Delete a policy.
+ """Delete a policy.
:param policy: the policy to be deleted on the server.
:type policy: str or :class:`keystoneclient.v3.policies.Policy`
diff --git a/keystoneclient/v3/projects.py b/keystoneclient/v3/projects.py
index 79f8c93e5..4ba94bf03 100644
--- a/keystoneclient/v3/projects.py
+++ b/keystoneclient/v3/projects.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six.moves.urllib as urllib
+import urllib.parse
from keystoneclient import base
from keystoneclient import exceptions
@@ -112,7 +112,7 @@ def create(self, name, domain, description=None,
enabled=enabled,
**kwargs)
- def list(self, domain=None, user=None, **kwargs):
+ def list(self, domain=None, user=None, parent=None, **kwargs):
"""List projects.
:param domain: the domain of the projects to be filtered on.
@@ -120,6 +120,9 @@ def list(self, domain=None, user=None, **kwargs):
:param user: filter in projects the specified user has role
assignments on.
:type user: str or :class:`keystoneclient.v3.users.User`
+ :param parent: filter in projects the specified project is a parent
+ for
+ :type parent: str or :class:`keystoneclient.v3.projects.Project`
:param kwargs: any other attribute provided will filter projects on.
Project tags filter keyword: ``tags``, ``tags_any``,
``not_tags``, and ``not_tags_any``. tag attribute type
@@ -134,11 +137,24 @@ def list(self, domain=None, user=None, **kwargs):
projects = super(ProjectManager, self).list(
base_url=base_url,
domain_id=base.getid(domain),
+ parent_id=base.getid(parent),
fallback_to_auth=True,
**kwargs)
- for p in projects:
- p.tags = self._encode_tags(getattr(p, 'tags', []))
- return projects
+
+ base_response = None
+ list_data = projects
+ if self.client.include_metadata:
+ base_response = projects
+ list_data = projects.data
+ base_response.data = list_data
+
+ for p in list_data:
+ p.tags = getattr(p, 'tags', [])
+
+ if self.client.include_metadata:
+ base_response.data = list_data
+
+ return base_response if self.client.include_metadata else list_data
def _check_not_parents_as_ids_and_parents_as_list(self, parents_as_ids,
parents_as_list):
@@ -202,12 +218,12 @@ def get(self, project, subtree_as_list=False, parents_as_list=False,
dict_args = {'project_id': base.getid(project)}
url = self.build_url(dict_args_in_out=dict_args)
p = self._get(url + query, self.key)
- p.tags = self._encode_tags(getattr(p, 'tags', []))
+ p.tags = getattr(p, 'tags', [])
return p
def find(self, **kwargs):
p = super(ProjectManager, self).find(**kwargs)
- p.tags = self._encode_tags(getattr(p, 'tags', []))
+ p.tags = getattr(p, 'tags', [])
return p
def update(self, project, name=None, domain=None, description=None,
@@ -248,15 +264,6 @@ def delete(self, project):
return super(ProjectManager, self).delete(
project_id=base.getid(project))
- def _encode_tags(self, tags):
- """Encode tags to non-unicode string in python2.
-
- :param tags: list of unicode tags
-
- :returns: List of strings
- """
- return [str(t) for t in tags]
-
def add_tag(self, project, tag):
"""Add a tag to a project.
@@ -266,7 +273,7 @@ def add_tag(self, project, tag):
"""
url = "/projects/%s/tags/%s" % (base.getid(project),
urllib.parse.quote(tag))
- self.client.put(url)
+ return self._put(url)
def update_tags(self, project, tags):
"""Update tag list of a project.
@@ -283,7 +290,7 @@ def update_tags(self, project, tags):
for tag in tags:
tag = urllib.parse.quote(tag)
resp, body = self.client.put(url, body={"tags": tags})
- return body['tags']
+ return self._prepare_return_value(resp, body['tags'])
def delete_tag(self, project, tag):
"""Remove tag from project.
@@ -292,7 +299,7 @@ def delete_tag(self, project, tag):
:param tag: str name of tag to remove from project
"""
- self._delete(
+ return self._delete(
"/projects/%s/tags/%s" % (base.getid(project),
urllib.parse.quote(tag)))
@@ -306,7 +313,7 @@ def list_tags(self, project):
"""
url = "/projects/%s/tags" % base.getid(project)
resp, body = self.client.get(url)
- return self._encode_tags(body['tags'])
+ return self._prepare_return_value(resp, body['tags'])
def check_tag(self, project, tag):
"""Check if tag is associated with project.
@@ -320,9 +327,9 @@ def check_tag(self, project, tag):
url = "/projects/%s/tags/%s" % (base.getid(project),
urllib.parse.quote(tag))
try:
- self.client.head(url)
+ resp, body = self.client.head(url)
# no errors means found the tag
- return True
- except exceptions.NotFound:
- # 404 means tag not in project
- return False
+ return self._prepare_return_value(resp, True)
+ except exceptions.HttpError as ex:
+ # return false with request_id if include_metadata=True
+ return self._prepare_return_value(ex.response, False)
diff --git a/keystoneclient/v3/regions.py b/keystoneclient/v3/regions.py
index 7783b3fc9..0538a6656 100644
--- a/keystoneclient/v3/regions.py
+++ b/keystoneclient/v3/regions.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from debtcollector import removals
from keystoneclient import base
@@ -34,6 +35,11 @@ class RegionManager(base.CrudManager):
collection_key = 'regions'
key = 'region'
+ @removals.removed_kwarg(
+ 'enabled',
+ message='The enabled parameter is deprecated.',
+ version='3.18.0',
+ removal_version='4.0.0')
def create(self, id=None, description=None, enabled=True,
parent_region=None, **kwargs):
"""Create a region.
@@ -81,6 +87,11 @@ def list(self, **kwargs):
return super(RegionManager, self).list(
**kwargs)
+ @removals.removed_kwarg(
+ 'enabled',
+ message='The enabled parameter is deprecated.',
+ version='3.18.0',
+ removal_version='4.0.0')
def update(self, region, description=None, enabled=None,
parent_region=None, **kwargs):
"""Update a region.
diff --git a/keystoneclient/v3/registered_limits.py b/keystoneclient/v3/registered_limits.py
index 6593845d3..088aadc9e 100644
--- a/keystoneclient/v3/registered_limits.py
+++ b/keystoneclient/v3/registered_limits.py
@@ -69,7 +69,9 @@ def create(self, service, resource_name, default_limit,
body = {self.collection_key: [limit_data]}
resp, body = self.client.post('/registered_limits', body=body)
registered_limit = body[self.collection_key].pop()
- return self.resource_class(self, registered_limit)
+ return self._prepare_return_value(resp,
+ self.resource_class(
+ self, registered_limit))
def update(self, registered_limit, service=None, resource_name=None,
default_limit=None, description=None, region=None, **kwargs):
diff --git a/keystoneclient/v3/roles.py b/keystoneclient/v3/roles.py
index a84ab39a3..3364bd88b 100644
--- a/keystoneclient/v3/roles.py
+++ b/keystoneclient/v3/roles.py
@@ -455,7 +455,8 @@ def create(self, prior_role, implied_role):
"""
url_tail = self._implied_role_url_tail(prior_role, implied_role)
_resp, body = self.client.put("/roles" + url_tail)
- return self.resource_class(self, body['role_inference'])
+ return self._prepare_return_value(
+ _resp, self.resource_class(self, body['role_inference']))
def delete(self, prior_role, implied_role):
"""Delete an inference rule.
@@ -478,7 +479,7 @@ def delete(self, prior_role, implied_role):
"""
url_tail = self._implied_role_url_tail(prior_role, implied_role)
- return self.client.delete("/roles" + url_tail)
+ return self._delete("/roles" + url_tail)
def get(self, prior_role, implied_role):
"""Retrieve an inference rule.
@@ -499,7 +500,8 @@ def get(self, prior_role, implied_role):
"""
url_tail = self._implied_role_url_tail(prior_role, implied_role)
_resp, body = self.client.get("/roles" + url_tail)
- return self.resource_class(self, body['role_inference'])
+ return self._prepare_return_value(
+ _resp, self.resource_class(self, body['role_inference']))
def list(self, prior_role):
"""List all roles that a role may imply.
@@ -518,7 +520,8 @@ def list(self, prior_role):
"""
url_tail = ('/%s/implies' % base.getid(prior_role))
_resp, body = self.client.get("/roles" + url_tail)
- return self.resource_class(self, body['role_inference'])
+ return self._prepare_return_value(
+ _resp, self.resource_class(self, body['role_inference']))
def check(self, prior_role, implied_role):
"""Check if an inference rule exists.
@@ -538,7 +541,7 @@ def check(self, prior_role, implied_role):
"""
url_tail = self._implied_role_url_tail(prior_role, implied_role)
- return self.client.head("/roles" + url_tail)
+ return self._head("/roles" + url_tail)
def list_inference_roles(self):
"""List all rule inferences.
diff --git a/keystoneclient/v3/system.py b/keystoneclient/v3/system.py
new file mode 100644
index 000000000..8d3edafdd
--- /dev/null
+++ b/keystoneclient/v3/system.py
@@ -0,0 +1,26 @@
+# Copyright 2021 OpenStack Foundation
+# All Rights Reserved.
+#
+# 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.
+
+from keystoneclient import base
+
+
+class System(base.Resource):
+ """Represents the deployment system, with all the services in it.
+
+ Attributes:
+ * all: boolean
+ """
+
+ pass
diff --git a/keystoneclient/v3/tokens.py b/keystoneclient/v3/tokens.py
index 6e6fffdb2..7e0cb07a8 100644
--- a/keystoneclient/v3/tokens.py
+++ b/keystoneclient/v3/tokens.py
@@ -57,7 +57,8 @@ def get_revoked(self, audit_id_only=False):
resp, body = self._client.get(path)
return body
- def get_token_data(self, token, include_catalog=True, allow_expired=False):
+ def get_token_data(self, token, include_catalog=True, allow_expired=False,
+ access_rules_support=None):
"""Fetch the data about a token from the identity server.
:param str token: The ID of the token to be fetched.
@@ -65,11 +66,18 @@ def get_token_data(self, token, include_catalog=True, allow_expired=False):
included in the response.
:param allow_expired: If True the token will be validated and returned
if it has already expired.
+ :param access_rules_support: Version number indicating that the client
+ is capable of enforcing keystone
+ access rules, if unset this client
+ does not support access rules.
+ :type access_rules_support: float
:rtype: dict
"""
headers = {'X-Subject-Token': token}
+ if access_rules_support:
+ headers['OpenStack-Identity-Access-Rules'] = access_rules_support
flags = []
url = '/auth/tokens'
@@ -85,7 +93,8 @@ def get_token_data(self, token, include_catalog=True, allow_expired=False):
resp, body = self._client.get(url, headers=headers)
return body
- def validate(self, token, include_catalog=True, allow_expired=False):
+ def validate(self, token, include_catalog=True, allow_expired=False,
+ access_rules_support=None):
"""Validate a token.
:param token: The token to be validated.
@@ -95,6 +104,11 @@ def validate(self, token, include_catalog=True, allow_expired=False):
:param allow_expired: If True the token will be validated and returned
if it has already expired.
:type allow_expired: bool
+ :param access_rules_support: Version number indicating that the client
+ is capable of enforcing keystone
+ access rules, if unset this client
+ does not support access rules.
+ :type access_rules_support: float
:rtype: :class:`keystoneclient.access.AccessInfoV3`
@@ -102,5 +116,6 @@ def validate(self, token, include_catalog=True, allow_expired=False):
token_id = _calc_id(token)
body = self.get_token_data(token_id,
include_catalog=include_catalog,
- allow_expired=allow_expired)
+ allow_expired=allow_expired,
+ access_rules_support=access_rules_support)
return access.AccessInfo.factory(auth_token=token_id, body=body)
diff --git a/lower-constraints.txt b/lower-constraints.txt
deleted file mode 100644
index 885c61526..000000000
--- a/lower-constraints.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-appdirs==1.3.0
-asn1crypto==0.23.0
-Babel==2.3.4
-bandit==1.1.0
-cffi==1.7.0
-cliff==2.8.0
-cmd2==0.8.0
-coverage==4.0
-cryptography==2.1
-debtcollector==1.2.0
-extras==1.0.0
-fasteners==0.7.0
-fixtures==3.0.0
-flake8-docstrings==0.2.1.post1
-flake8==2.2.4
-future==0.16.0
-gitdb==0.6.4
-GitPython==1.0.1
-hacking==0.10.0
-idna==2.6
-iso8601==0.1.11
-jsonschema==2.6.0
-keyring==5.5.1
-keystoneauth1==3.4.0
-linecache2==1.0.0
-lxml==3.4.1
-mccabe==0.2.1
-mock==2.0.0
-monotonic==0.6
-mox3==0.20.0
-msgpack-python==0.4.0
-netaddr==0.7.18
-netifaces==0.10.4
-oauthlib==0.6.2
-os-client-config==1.28.0
-os-testr==1.0.0
-oslo.concurrency==3.25.0
-oslo.config==5.2.0
-oslo.context==2.19.2
-oslo.i18n==3.15.3
-oslo.log==3.36.0
-oslo.serialization==2.18.0
-oslo.utils==3.33.0
-oslotest==3.2.0
-paramiko==2.0.0
-pbr==2.0.0
-pep257==0.7.0
-pep8==1.5.7
-prettytable==0.7.2
-pyasn1==0.1.8
-pycparser==2.18
-pyflakes==0.8.1
-pyinotify==0.9.6
-pyparsing==2.1.0
-pyperclip==1.5.27
-python-dateutil==2.5.3
-python-mimeparse==1.6.0
-python-subunit==1.0.0
-pytz==2013.6
-PyYAML==3.12
-requests-mock==1.2.0
-requests==2.14.2
-requestsexceptions==1.2.0
-rfc3986==0.3.1
-six==1.10.0
-smmap==0.9.0
-stevedore==1.20.0
-tempest==17.1.0
-stestr==2.0.0
-testresources==2.0.0
-testscenarios==0.4
-testtools==2.2.0
-traceback2==1.4.0
-unittest2==1.1.0
-urllib3==1.21.1
-wrapt==1.7.0
diff --git a/playbooks/run-ds-tox.yaml b/playbooks/run-ds-tox.yaml
new file mode 100644
index 000000000..b414b747c
--- /dev/null
+++ b/playbooks/run-ds-tox.yaml
@@ -0,0 +1,5 @@
+- hosts: all
+ roles:
+ - run-devstack
+ - ensure-tox
+ - tox
diff --git a/playbooks/tox-post.yaml b/playbooks/tox-post.yaml
new file mode 100644
index 000000000..7f0cb1982
--- /dev/null
+++ b/playbooks/tox-post.yaml
@@ -0,0 +1,4 @@
+- hosts: all
+ roles:
+ - fetch-tox-output
+ - fetch-subunit-output
diff --git a/releasenotes/notes/bp-whitelist-extension-for-app-creds-d03526e52e3edcce.yaml b/releasenotes/notes/bp-whitelist-extension-for-app-creds-d03526e52e3edcce.yaml
new file mode 100644
index 000000000..9c7dc2bf1
--- /dev/null
+++ b/releasenotes/notes/bp-whitelist-extension-for-app-creds-d03526e52e3edcce.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Adds support for creating access rules as an attribute of application
+ credentials as well as for retrieving and deleting them.
diff --git a/releasenotes/notes/bug-1615076-26962c85aeaf288c.yaml b/releasenotes/notes/bug-1615076-26962c85aeaf288c.yaml
new file mode 100644
index 000000000..6af51e4f1
--- /dev/null
+++ b/releasenotes/notes/bug-1615076-26962c85aeaf288c.yaml
@@ -0,0 +1,5 @@
+---
+deprecations:
+ - |
+ The region resource in Keystone never support or contain "enabled" property.
+ Thus the property is deprecated and will be removed in future versions.
diff --git a/releasenotes/notes/drop-py-2-7-5ac18e82de83fcfa.yaml b/releasenotes/notes/drop-py-2-7-5ac18e82de83fcfa.yaml
new file mode 100644
index 000000000..b97748489
--- /dev/null
+++ b/releasenotes/notes/drop-py-2-7-5ac18e82de83fcfa.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ Python 2.7 support has been dropped. Last release of python-keystoneclient
+ to support python 2.7 is OpenStack Train. The minimum version of Python now
+ supported is Python 3.6.
\ No newline at end of file
diff --git a/releasenotes/notes/drop-python-3-6-and-3-7-ef1e107897dde8f4.yaml b/releasenotes/notes/drop-python-3-6-and-3-7-ef1e107897dde8f4.yaml
new file mode 100644
index 000000000..db420d739
--- /dev/null
+++ b/releasenotes/notes/drop-python-3-6-and-3-7-ef1e107897dde8f4.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ Python 3.6 & 3.7 support has been dropped. The minimum version of Python now
+ supported is Python 3.8.
diff --git a/releasenotes/notes/list_projects_filtered_by_the_parent_project-a873974f197c1e37.yaml b/releasenotes/notes/list_projects_filtered_by_the_parent_project-a873974f197c1e37.yaml
new file mode 100644
index 000000000..988dca5e3
--- /dev/null
+++ b/releasenotes/notes/list_projects_filtered_by_the_parent_project-a873974f197c1e37.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Now keystone client supports to list projects which belongs to the given
+ parent project.
diff --git a/releasenotes/notes/remove-py38-2e39854190447827.yaml b/releasenotes/notes/remove-py38-2e39854190447827.yaml
new file mode 100644
index 000000000..040316360
--- /dev/null
+++ b/releasenotes/notes/remove-py38-2e39854190447827.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ Support for Python 3.8 has been removed. Now the minimum python version
+ supported is 3.9 .
diff --git a/releasenotes/notes/remove-py39-a294c2d7335b646e.yaml b/releasenotes/notes/remove-py39-a294c2d7335b646e.yaml
new file mode 100644
index 000000000..eaf3014b9
--- /dev/null
+++ b/releasenotes/notes/remove-py39-a294c2d7335b646e.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ Support for Python 3.9 has been removed. Now Python 3.10 is the minimum
+ version supported.
diff --git a/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml b/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml
new file mode 100644
index 000000000..8ef4701db
--- /dev/null
+++ b/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml
@@ -0,0 +1,13 @@
+---
+features:
+ - >
+ [`blueprint return-request-id-to-caller
+ `_]
+ Instantiating client with ``include_metadata=True`` will cause manager response to return data
+ along with request_ids for better tracing. Refer [`using-api-v3
+ `_]
+
+
+ Added support to return "x-openstack-request-id" header in request_ids attribute if
+ ``include_metadata=True``. Also, for APIs which return response as None, client will return request_ids
+ as well if ``include_metadata`` is True.
\ No newline at end of file
diff --git a/releasenotes/notes/switch-default-interface-v3-dcd7167196ace531.yaml b/releasenotes/notes/switch-default-interface-v3-dcd7167196ace531.yaml
new file mode 100644
index 000000000..90709c097
--- /dev/null
+++ b/releasenotes/notes/switch-default-interface-v3-dcd7167196ace531.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ For sessions using the v3 Identity API, the default interface has been
+ switched from ``admin`` to ``public``. This allows deployments to get rid
+ of the admin endpoint, which functionally is no longer necessary with the
+ v3 API.
diff --git a/releasenotes/source/2023.1.rst b/releasenotes/source/2023.1.rst
new file mode 100644
index 000000000..2c9a36fae
--- /dev/null
+++ b/releasenotes/source/2023.1.rst
@@ -0,0 +1,6 @@
+===========================
+2023.1 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: unmaintained/2023.1
diff --git a/releasenotes/source/2023.2.rst b/releasenotes/source/2023.2.rst
new file mode 100644
index 000000000..a4838d7d0
--- /dev/null
+++ b/releasenotes/source/2023.2.rst
@@ -0,0 +1,6 @@
+===========================
+2023.2 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2023.2
diff --git a/releasenotes/source/2024.1.rst b/releasenotes/source/2024.1.rst
new file mode 100644
index 000000000..6896656be
--- /dev/null
+++ b/releasenotes/source/2024.1.rst
@@ -0,0 +1,6 @@
+===========================
+2024.1 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: unmaintained/2024.1
diff --git a/releasenotes/source/2024.2.rst b/releasenotes/source/2024.2.rst
new file mode 100644
index 000000000..aaebcbc8c
--- /dev/null
+++ b/releasenotes/source/2024.2.rst
@@ -0,0 +1,6 @@
+===========================
+2024.2 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2024.2
diff --git a/releasenotes/source/2025.1.rst b/releasenotes/source/2025.1.rst
new file mode 100644
index 000000000..3add0e53a
--- /dev/null
+++ b/releasenotes/source/2025.1.rst
@@ -0,0 +1,6 @@
+===========================
+2025.1 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2025.1
diff --git a/releasenotes/source/2026.1.rst b/releasenotes/source/2026.1.rst
new file mode 100644
index 000000000..3d2861580
--- /dev/null
+++ b/releasenotes/source/2026.1.rst
@@ -0,0 +1,6 @@
+===========================
+2026.1 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2026.1
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index f0235982a..f2ae6a44e 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -54,8 +54,7 @@
master_doc = 'index'
# General information about the project.
-project = u'keystoneclient Release Notes'
-copyright = u'2015, Keystone Developers'
+copyright = '2015, Keystone Developers'
# Release notes are version independent.
# The full version, including alpha/beta/rc tags.
@@ -93,7 +92,7 @@
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
@@ -142,11 +141,6 @@
# directly to the root of the documentation.
# html_extra_path = []
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-# html_last_updated_fmt = '%b %d, %Y'
-html_last_updated_fmt = '%Y-%m-%d %H:%M'
-
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
@@ -190,24 +184,13 @@
# -- Options for LaTeX output ---------------------------------------------
-latex_elements = {
- # The paper size ('letterpaper' or 'a4paper').
- # 'papersize': 'letterpaper',
-
- # The font size ('10pt', '11pt' or '12pt').
- # 'pointsize': '10pt',
-
- # Additional stuff for the LaTeX preamble.
- # 'preamble': '',
-}
-
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'keystoneclientReleaseNotes.tex',
- u'keystoneclient Release Notes Documentation',
- u'Keystone Developers', 'manual'),
+ 'keystoneclient Release Notes Documentation',
+ 'Keystone Developers', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -237,8 +220,8 @@
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'keystoneclientreleasenotes',
- u'keystoneclient Release Notes Documentation',
- [u'Keystone Developers'], 1)
+ 'keystoneclient Release Notes Documentation',
+ ['Keystone Developers'], 1)
]
# If true, show URL addresses after external links.
@@ -252,8 +235,8 @@
# dir menu entry, description, category)
texinfo_documents = [
('index', 'keystoneclientReleaseNotes',
- u'keystoneclient Release Notes Documentation',
- u'Keystone Developers', 'keystoneclientReleaseNotes',
+ 'keystoneclient Release Notes Documentation',
+ 'Keystone Developers', 'keystoneclientReleaseNotes',
'Python bindings for the OpenStack Identity service.',
'Miscellaneous'),
]
@@ -274,6 +257,6 @@
locale_dirs = ['locale/']
# -- Options for openstackdocstheme -------------------------------------------
-repository_name = 'openstack/python-keystoneclient'
-bug_project = 'python-keystoneclient'
-bug_tag = ''
+openstackdocs_repo_name = 'openstack/python-keystoneclient'
+openstackdocs_bug_project = 'python-keystoneclient'
+openstackdocs_bug_tag = ''
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 17a231d30..8f0142a8f 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,20 @@
:maxdepth: 1
unreleased
+ 2026.1
+ 2025.1
+ 2024.2
+ 2024.1
+ 2023.2
+ 2023.1
+ zed
+ yoga
+ xena
+ wallaby
+ victoria
+ ussuri
+ train
+ stein
rocky
queens
pike
diff --git a/releasenotes/source/stein.rst b/releasenotes/source/stein.rst
new file mode 100644
index 000000000..efaceb667
--- /dev/null
+++ b/releasenotes/source/stein.rst
@@ -0,0 +1,6 @@
+===================================
+ Stein Series Release Notes
+===================================
+
+.. release-notes::
+ :branch: stable/stein
diff --git a/releasenotes/source/train.rst b/releasenotes/source/train.rst
new file mode 100644
index 000000000..7fa1088ac
--- /dev/null
+++ b/releasenotes/source/train.rst
@@ -0,0 +1,6 @@
+===================================
+ Train Series Release Notes
+===================================
+
+.. release-notes::
+ :branch: stable/train
diff --git a/releasenotes/source/ussuri.rst b/releasenotes/source/ussuri.rst
new file mode 100644
index 000000000..e21e50e0c
--- /dev/null
+++ b/releasenotes/source/ussuri.rst
@@ -0,0 +1,6 @@
+===========================
+Ussuri Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/ussuri
diff --git a/releasenotes/source/victoria.rst b/releasenotes/source/victoria.rst
new file mode 100644
index 000000000..8ce933419
--- /dev/null
+++ b/releasenotes/source/victoria.rst
@@ -0,0 +1,6 @@
+=============================
+Victoria Series Release Notes
+=============================
+
+.. release-notes::
+ :branch: unmaintained/victoria
diff --git a/releasenotes/source/wallaby.rst b/releasenotes/source/wallaby.rst
new file mode 100644
index 000000000..bcf35c5f8
--- /dev/null
+++ b/releasenotes/source/wallaby.rst
@@ -0,0 +1,6 @@
+============================
+Wallaby Series Release Notes
+============================
+
+.. release-notes::
+ :branch: unmaintained/wallaby
diff --git a/releasenotes/source/xena.rst b/releasenotes/source/xena.rst
new file mode 100644
index 000000000..d19eda488
--- /dev/null
+++ b/releasenotes/source/xena.rst
@@ -0,0 +1,6 @@
+=========================
+Xena Series Release Notes
+=========================
+
+.. release-notes::
+ :branch: unmaintained/xena
diff --git a/releasenotes/source/yoga.rst b/releasenotes/source/yoga.rst
new file mode 100644
index 000000000..43cafdea8
--- /dev/null
+++ b/releasenotes/source/yoga.rst
@@ -0,0 +1,6 @@
+=========================
+Yoga Series Release Notes
+=========================
+
+.. release-notes::
+ :branch: unmaintained/yoga
diff --git a/releasenotes/source/zed.rst b/releasenotes/source/zed.rst
new file mode 100644
index 000000000..6cc2b1554
--- /dev/null
+++ b/releasenotes/source/zed.rst
@@ -0,0 +1,6 @@
+========================
+Zed Series Release Notes
+========================
+
+.. release-notes::
+ :branch: unmaintained/zed
diff --git a/requirements.txt b/requirements.txt
index 65e83de6b..1b69b9833 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,15 +1,14 @@
-# The order of packages is significant, because pip processes them in the order
-# of appearance. Changing the order has an impact on the overall integration
-# process, which may cause wedges in the gate later.
-
-pbr!=2.1.0,>=2.0.0 # Apache-2.0
+# Requirements lower bounds listed here are our best effort to keep them up to
+# date but we do not test them so no guarantee of having them all correct. If
+# you find any incorrect lower bounds, let us know or propose a fix.
+pbr>=2.0.0 # Apache-2.0
debtcollector>=1.2.0 # Apache-2.0
keystoneauth1>=3.4.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
-oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
+oslo.serialization>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
requests>=2.14.2 # Apache-2.0
-six>=1.10.0 # MIT
stevedore>=1.20.0 # Apache-2.0
+packaging>=20.4 # BSD
diff --git a/setup.cfg b/setup.cfg
index 8995a9cd5..037fe1c57 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,11 +1,12 @@
[metadata]
name = python-keystoneclient
summary = Client Library for OpenStack Identity
-description-file =
+description_file =
README.rst
author = OpenStack
-author-email = openstack-dev@lists.openstack.org
-home-page = https://docs.openstack.org/python-keystoneclient/latest/
+author_email = openstack-discuss@lists.openstack.org
+home_page = https://docs.openstack.org/python-keystoneclient/latest/
+python_requires = >=3.10
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -13,10 +14,10 @@ classifier =
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
- Programming Language :: Python :: 2
- Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
+ Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
+ Programming Language :: Python :: 3.12
[files]
packages =
@@ -35,35 +36,3 @@ keystoneclient.auth.plugin =
v3unscopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2UnscopedToken
v3scopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2ScopedToken
v3unscopedadfs = keystoneclient.contrib.auth.v3.saml2:ADFSUnscopedToken
-
-[build_sphinx]
-source-dir = doc/source
-build-dir = doc/build
-all_files = 1
-warning-is-error = 1
-
-[pbr]
-autodoc_tree_index_modules = True
-autodoc_tree_excludes =
- setup.py
- keystoneclient/tests/
-
-[upload_sphinx]
-upload-dir = doc/build/html
-
-[compile_catalog]
-directory = keystoneclient/locale
-domain = keystoneclient
-
-[update_catalog]
-domain = keystoneclient
-output_dir = keystoneclient/locale
-input_file = keystoneclient/locale/keystoneclient.pot
-
-[extract_messages]
-keywords = _ gettext ngettext l_ lazy_gettext
-mapping_file = babel.cfg
-output_file = keystoneclient/locale/keystoneclient.pot
-
-[wheel]
-universal = 1
diff --git a/setup.py b/setup.py
index 566d84432..cd35c3c35 100644
--- a/setup.py
+++ b/setup.py
@@ -13,17 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
-# In python < 2.7.4, a lazy loading of package `pbr` will break
-# setuptools if some other modules registered functions in `atexit`.
-# solution from: http://bugs.python.org/issue15881#msg170215
-try:
- import multiprocessing # noqa
-except ImportError:
- pass
-
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)
diff --git a/test-requirements.txt b/test-requirements.txt
index 92ffcf655..238690c65 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,16 +1,11 @@
-# The order of packages is significant, because pip processes them in the order
-# of appearance. Changing the order has an impact on the overall integration
-# process, which may cause wedges in the gate later.
+hacking>=6.1.0,<6.2.0 # Apache-2.0
-hacking<0.11,>=0.10.0
-flake8-docstrings==0.2.1.post1 # MIT
-
-coverage!=4.4,>=4.0 # Apache-2.0
+coverage>=4.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
keyring>=5.5.1 # MIT/PSF
-lxml!=3.7.0,>=3.4.1 # BSD
-mock>=2.0.0 # BSD
+lxml>=4.5.0 # BSD
oauthlib>=0.6.2 # BSD
+openstacksdk>=0.10.0 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0
requests-mock>=1.2.0 # Apache-2.0
tempest>=17.1.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index 4fd17d353..e69fc3559 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,52 +1,47 @@
[tox]
-minversion = 2.0
+minversion = 3.18.0
skipsdist = True
-envlist = py35,py27,pep8,releasenotes
+envlist = py3,pep8,releasenotes
+ignore_basepython_conflict = True
[testenv]
usedevelop = True
-install_command = pip install {opts} {packages}
-setenv = VIRTUAL_ENV={envdir}
- OS_STDOUT_NOCAPTURE=False
+setenv = OS_STDOUT_NOCAPTURE=False
OS_STDERR_NOCAPTURE=False
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
- -r{toxinidir}/requirements.txt
- -r{toxinidir}/test-requirements.txt
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
commands = find . -type f -name "*.pyc" -delete
stestr run --slowest {posargs}
-whitelist_externals = find
+allowlist_externals = find
+basepython = python3
[testenv:pep8]
-basepython = python3
commands =
flake8
bandit -r keystoneclient -x tests -n5
[testenv:bandit]
-basepython = python3
# NOTE(browne): This is required for the integration test job of the bandit
# project. Please do not remove.
commands = bandit -r keystoneclient -x tests -n5
[testenv:venv]
-basepython = python3
commands = {posargs}
[testenv:cover]
-basepython = python3
setenv =
PYTHON=coverage run --source keystoneclient --parallel-mode
commands =
- stestr run '{posargs}'
+ stestr run {posargs}
coverage combine
coverage html -d cover
coverage xml -o cover/coverage.xml
coverage report
[testenv:debug]
-basepython = python3
commands = oslo_debug_helper -t keystoneclient/tests {posargs}
[testenv:functional]
@@ -60,27 +55,42 @@ passenv = OS_*
# D102: Missing docstring in public method
# D103: Missing docstring in public function
# D104: Missing docstring in public package
+# D107: Missing docstring in __init__
# D203: 1 blank line required before class docstring (deprecated in pep257)
-ignore = D100,D101,D102,D103,D104,D203
+# D401 First line should be in imperative mood; try rephrasing
+# W504 line break after binary operator
+ignore = D100,D101,D102,D103,D104,D107,D203,D401,W504
show-source = True
exclude = .venv,.tox,dist,doc,*egg,build
[testenv:docs]
-basepython = python3
-commands = python setup.py build_sphinx
-deps = -r{toxinidir}/doc/requirements.txt
+commands = sphinx-build -W -b html doc/source doc/build/html
+deps =
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/doc/requirements.txt
+ -r{toxinidir}/requirements.txt
+
+[testenv:pdf-docs]
+deps = {[testenv:docs]deps}
+allowlist_externals =
+ make
+ rm
+commands =
+ rm -rf doc/build/pdf
+ sphinx-build -W -b latex doc/source doc/build/pdf
+ make -C doc/build/pdf
[testenv:releasenotes]
-basepython = python3
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
-deps = -r{toxinidir}/doc/requirements.txt
+deps =
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/doc/requirements.txt
[hacking]
import_exceptions =
keystoneclient.i18n
[testenv:bindep]
-basepython = python3
# Do not install any requirements. We want this to be fast and work even if
# system dependencies are missing, since it's used to tell you what system
# dependencies are missing! This also means that bindep must be installed
@@ -88,9 +98,3 @@ basepython = python3
deps = bindep
commands = bindep test
-[testenv:lower-constraints]
-basepython = python3
-deps =
- -c{toxinidir}/lower-constraints.txt
- -r{toxinidir}/test-requirements.txt
- -r{toxinidir}/requirements.txt