Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-oslo.middleware for 
openSUSE:Factory checked in at 2021-12-12 00:57:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-oslo.middleware (Old)
 and      /work/SRC/openSUSE:Factory/.python-oslo.middleware.new.2520 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-oslo.middleware"

Sun Dec 12 00:57:34 2021 rev:18 rq:939534 version:4.4.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-oslo.middleware/python-oslo.middleware.changes
    2021-05-10 15:39:50.057452706 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-oslo.middleware.new.2520/python-oslo.middleware.changes
  2021-12-12 00:57:39.550586423 +0100
@@ -1,0 +2,15 @@
+Tue Oct 26 22:08:34 UTC 2021 - [email protected]
+
+- update to version 4.4.0
+  - Add Python3 xena unit tests
+  - ignore reno generated artifacts
+  - Add new basic auth middleware
+  - setup.cfg: Replace dashes with underscores
+  - Fix requirements issues
+  - Upgrade the pre-commit-hooks version
+  - Warning about /healthcheck
+  - remove unicode from code
+  - Use py3 as the default runtime for tox
+  - Update master for stable/wallaby
+
+-------------------------------------------------------------------

Old:
----
  oslo.middleware-4.2.0.tar.gz

New:
----
  oslo.middleware-4.4.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-oslo.middleware.spec ++++++
--- /var/tmp/diff_new_pack.eUX0Aw/_old  2021-12-12 00:57:40.002586733 +0100
+++ /var/tmp/diff_new_pack.eUX0Aw/_new  2021-12-12 00:57:40.006586735 +0100
@@ -17,16 +17,17 @@
 
 
 Name:           python-oslo.middleware
-Version:        4.2.0
+Version:        4.4.0
 Release:        0
 Summary:        OpenStack oslo.middleware library
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://docs.openstack.org/oslo.middleware
-Source0:        
https://files.pythonhosted.org/packages/source/o/oslo.middleware/oslo.middleware-4.2.0.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/o/oslo.middleware/oslo.middleware-4.4.0.tar.gz
 BuildRequires:  openstack-macros
 BuildRequires:  python3-Jinja2 >= 2.10
 BuildRequires:  python3-WebOb >= 1.8.0
+BuildRequires:  python3-bcrypt >= 3.1.3
 BuildRequires:  python3-debtcollector >= 1.2.0
 BuildRequires:  python3-devel
 BuildRequires:  python3-fixtures
@@ -55,6 +56,7 @@
 Summary:        OpenStack oslo.middleware library
 Requires:       python3-Jinja2 >= 2.10
 Requires:       python3-WebOb >= 1.8.0
+Requires:       python3-bcrypt >= 3.1.3
 Requires:       python3-debtcollector >= 1.2.0
 Requires:       python3-oslo.config >= 5.2.0
 Requires:       python3-oslo.context >= 2.19.2
@@ -86,7 +88,7 @@
 This package contains the documentation.
 
 %prep
-%autosetup -p1 -n oslo.middleware-4.2.0
+%autosetup -p1 -n oslo.middleware-4.4.0
 %py_req_cleanup
 
 %build

++++++ _service ++++++
--- /var/tmp/diff_new_pack.eUX0Aw/_old  2021-12-12 00:57:40.034586755 +0100
+++ /var/tmp/diff_new_pack.eUX0Aw/_new  2021-12-12 00:57:40.034586755 +0100
@@ -1,8 +1,8 @@
 <services>
   <service mode="disabled" name="renderspec">
-    <param 
name="input-template">https://opendev.org/openstack/rpm-packaging/raw/branch/stable/wallaby/openstack/oslo.middleware/oslo.middleware.spec.j2</param>
+    <param 
name="input-template">https://opendev.org/openstack/rpm-packaging/raw/master/openstack/oslo.middleware/oslo.middleware.spec.j2</param>
     <param name="output-name">python-oslo.middleware.spec</param>
-    <param 
name="requirements">https://opendev.org/openstack/oslo.middleware/raw/branch/stable/wallaby/requirements.txt</param>
+    <param 
name="requirements">https://opendev.org/openstack/oslo.middleware/raw/master/requirements.txt</param>
     <param name="changelog-email">[email protected]</param>
     <param name="changelog-provider">gh,openstack,oslo.middleware</param>
   </service>

++++++ oslo.middleware-4.2.0.tar.gz -> oslo.middleware-4.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/.pre-commit-config.yaml 
new/oslo.middleware-4.4.0/.pre-commit-config.yaml
--- old/oslo.middleware-4.2.0/.pre-commit-config.yaml   2021-03-11 
21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/.pre-commit-config.yaml   2021-08-12 
10:36:30.000000000 +0200
@@ -9,7 +9,7 @@
 
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: ebc15addedad713c86ef18ae9632c88e187dd0af  # v3.1.0
+    rev: 9136088a246768144165fcc3ecc3d31bb686920a # v3.3.0
     hooks:
       - id: trailing-whitespace
       # Replaces or checks mixed line ending
@@ -27,9 +27,13 @@
       - id: debug-statements
       - id: check-yaml
         files: .*\.(yaml|yml)$
-  - repo: https://gitlab.com/pycqa/flake8
-    rev: 181bb46098dddf7e2d45319ea654b4b4d58c2840 # 3.8.3
+  - repo: local
     hooks:
       - id: flake8
+        name: flake8
         additional_dependencies:
           - hacking>=3.0.1,<3.1.0
+        language: python
+        entry: flake8
+        files: '^.*\.py$'
+        exclude: '^(doc|releasenotes|tools)/.*$'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/.zuul.yaml 
new/oslo.middleware-4.4.0/.zuul.yaml
--- old/oslo.middleware-4.2.0/.zuul.yaml        2021-03-11 21:41:04.000000000 
+0100
+++ new/oslo.middleware-4.4.0/.zuul.yaml        2021-08-12 10:36:30.000000000 
+0200
@@ -2,8 +2,7 @@
     templates:
       - check-requirements
       - lib-forward-testing-python3
-      - openstack-lower-constraints-jobs
-      - openstack-python3-wallaby-jobs
+      - openstack-python3-xena-jobs
       - periodic-stable-jobs
       - publish-openstack-docs-pti
       - release-notes-jobs-python3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/AUTHORS 
new/oslo.middleware-4.4.0/AUTHORS
--- old/oslo.middleware-4.2.0/AUTHORS   2021-03-11 21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/AUTHORS   2021-08-12 10:37:04.000000000 +0200
@@ -22,6 +22,7 @@
 Cyril Roelandt <[email protected]>
 Cyril Roelandt <[email protected]>
 Dan Prince <[email protected]>
+Daniel Bengtsson <[email protected]>
 Davanum Srinivas (dims) <[email protected]>
 Davanum Srinivas <[email protected]>
 Davanum Srinivas <[email protected]>
@@ -78,6 +79,7 @@
 Victor Sergeyev <[email protected]>
 Victor Stinner <[email protected]>
 Vu Cong Tuan <[email protected]>
+YuehuiLei <[email protected]>
 Yujun Zhang <[email protected]>
 Zhihai Song <[email protected]>
 ZhongShengping <[email protected]>
@@ -92,9 +94,12 @@
 lioplhp <[email protected]>
 melissaml <[email protected]>
 pengyuesheng <[email protected]>
+ramishra <[email protected]>
 ricolin <[email protected]>
 sonu.kumar <[email protected]>
 venkatamahesh <[email protected]>
+wu.shiming <[email protected]>
+xuanyandong <[email protected]>
 yan.haifeng <[email protected]>
 zhangboye <[email protected]>
 zhangguoqing <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/ChangeLog 
new/oslo.middleware-4.4.0/ChangeLog
--- old/oslo.middleware-4.2.0/ChangeLog 2021-03-11 21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/ChangeLog 2021-08-12 10:37:04.000000000 +0200
@@ -1,10 +1,29 @@
 CHANGES
 =======
 
+4.4.0
+-----
+
+* Add new basic auth middleware
+
+4.3.0
+-----
+
+* Upgrade the pre-commit-hooks version
+* setup.cfg: Replace dashes with underscores
+* Warning about /healthcheck
+* Add Python3 xena unit tests
+* Update master for stable/wallaby
+* Fix requirements issues
+* Fix requirements issues
+* remove unicode from code
+
 4.2.0
 -----
 
 * Use TOX\_CONSTRAINTS\_FILE
+* Use py3 as the default runtime for tox
+* ignore reno generated artifacts
 * Adding pre-commit
 * Add Python3 wallaby unit tests
 * Update master for stable/victoria
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/PKG-INFO 
new/oslo.middleware-4.4.0/PKG-INFO
--- old/oslo.middleware-4.2.0/PKG-INFO  2021-03-11 21:41:52.863160100 +0100
+++ new/oslo.middleware-4.4.0/PKG-INFO  2021-08-12 10:37:04.363057400 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: oslo.middleware
-Version: 4.2.0
+Version: 4.4.0
 Summary: Oslo Middleware library
 Home-page: https://docs.openstack.org/oslo.middleware/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/doc/source/conf.py 
new/oslo.middleware-4.4.0/doc/source/conf.py
--- old/oslo.middleware-4.2.0/doc/source/conf.py        2021-03-11 
21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/doc/source/conf.py        2021-08-12 
10:36:30.000000000 +0200
@@ -45,7 +45,7 @@
 master_doc = 'index'
 
 # General information about the project.
-copyright = u'2014, OpenStack Foundation'
+copyright = '2014, OpenStack Foundation'
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
 add_function_parentheses = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/lower-constraints.txt 
new/oslo.middleware-4.4.0/lower-constraints.txt
--- old/oslo.middleware-4.2.0/lower-constraints.txt     2021-03-11 
21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/lower-constraints.txt     1970-01-01 
01:00:00.000000000 +0100
@@ -1,43 +0,0 @@
-appdirs==1.3.0
-Babel==2.3.4
-bandit==1.4.0
-coverage==4.0
-debtcollector==1.2.0
-extras==1.0.0
-fixtures==3.0.0
-gitdb==0.6.4
-GitPython==1.0.1
-iso8601==0.1.11
-Jinja2==2.10
-keystoneauth1==3.4.0
-linecache2==1.0.0
-MarkupSafe==1.0
-mox3==0.20.0
-msgpack-python==0.4.0
-netaddr==0.7.18
-netifaces==0.10.4
-os-client-config==1.28.0
-oslo.config==5.2.0
-oslo.context==2.19.2
-oslo.i18n==3.15.3
-oslo.serialization==2.18.0
-oslo.utils==3.33.0
-oslotest==3.2.0
-pbr==2.0.0
-pyparsing==2.1.0
-python-mimeparse==1.6.0
-python-subunit==1.0.0
-pytz==2013.6
-PyYAML==3.12
-requests==2.14.2
-requestsexceptions==1.2.0
-rfc3986==0.3.1
-smmap==0.9.0
-statsd==3.2.1
-stestr==2.0.0
-stevedore==1.20.0
-testtools==2.2.0
-traceback2==1.4.0
-unittest2==1.1.0
-WebOb==1.8.0
-wrapt==1.7.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo.middleware.egg-info/PKG-INFO 
new/oslo.middleware-4.4.0/oslo.middleware.egg-info/PKG-INFO
--- old/oslo.middleware-4.2.0/oslo.middleware.egg-info/PKG-INFO 2021-03-11 
21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo.middleware.egg-info/PKG-INFO 2021-08-12 
10:37:04.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: oslo.middleware
-Version: 4.2.0
+Version: 4.4.0
 Summary: Oslo Middleware library
 Home-page: https://docs.openstack.org/oslo.middleware/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo.middleware.egg-info/SOURCES.txt 
new/oslo.middleware-4.4.0/oslo.middleware.egg-info/SOURCES.txt
--- old/oslo.middleware-4.2.0/oslo.middleware.egg-info/SOURCES.txt      
2021-03-11 21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo.middleware.egg-info/SOURCES.txt      
2021-08-12 10:37:04.000000000 +0200
@@ -9,7 +9,6 @@
 HACKING.rst
 LICENSE
 README.rst
-lower-constraints.txt
 requirements.txt
 setup.cfg
 setup.py
@@ -41,6 +40,7 @@
 oslo_middleware/__init__.py
 oslo_middleware/_i18n.py
 oslo_middleware/base.py
+oslo_middleware/basic_auth.py
 oslo_middleware/catch_errors.py
 oslo_middleware/correlation_id.py
 oslo_middleware/cors.py
@@ -61,6 +61,7 @@
 oslo_middleware/locale/en_GB/LC_MESSAGES/oslo_middleware.po
 oslo_middleware/locale/fr/LC_MESSAGES/oslo_middleware.po
 oslo_middleware/tests/__init__.py
+oslo_middleware/tests/test_auth_basic.py
 oslo_middleware/tests/test_base.py
 oslo_middleware/tests/test_catch_errors.py
 oslo_middleware/tests/test_correlation_id.py
@@ -74,6 +75,7 @@
 oslo_middleware/tests/test_ssl.py
 oslo_middleware/tests/test_stats.py
 releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml
+releasenotes/notes/basic-auth-middleware-5f812399e325425f.yaml
 releasenotes/notes/compat_headers-55a635b8ec01b6f1.yaml
 releasenotes/notes/drop-python27-support-a6361831195bf29c.yaml
 releasenotes/notes/global_request_id-a8ec7260fbd76444.yaml
@@ -89,6 +91,7 @@
 releasenotes/source/unreleased.rst
 releasenotes/source/ussuri.rst
 releasenotes/source/victoria.rst
+releasenotes/source/wallaby.rst
 releasenotes/source/_static/.placeholder
 releasenotes/source/_templates/.placeholder
 releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo.middleware.egg-info/pbr.json 
new/oslo.middleware-4.4.0/oslo.middleware.egg-info/pbr.json
--- old/oslo.middleware-4.2.0/oslo.middleware.egg-info/pbr.json 2021-03-11 
21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo.middleware.egg-info/pbr.json 2021-08-12 
10:37:04.000000000 +0200
@@ -1 +1 @@
-{"git_version": "6729192", "is_release": true}
\ No newline at end of file
+{"git_version": "da7987c", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo.middleware.egg-info/requires.txt 
new/oslo.middleware-4.4.0/oslo.middleware.egg-info/requires.txt
--- old/oslo.middleware-4.2.0/oslo.middleware.egg-info/requires.txt     
2021-03-11 21:41:52.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo.middleware.egg-info/requires.txt     
2021-08-12 10:37:04.000000000 +0200
@@ -1,5 +1,6 @@
 Jinja2>=2.10
 WebOb>=1.8.0
+bcrypt>=3.1.3
 debtcollector>=1.2.0
 oslo.config>=5.2.0
 oslo.context>=2.19.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/oslo_middleware/basic_auth.py 
new/oslo.middleware-4.4.0/oslo_middleware/basic_auth.py
--- old/oslo.middleware-4.2.0/oslo_middleware/basic_auth.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo_middleware/basic_auth.py     2021-08-12 
10:36:30.000000000 +0200
@@ -0,0 +1,203 @@
+# Copyright 2012 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.
+
+import base64
+import binascii
+import logging
+
+import bcrypt
+import webob
+
+from oslo_config import cfg
+from oslo_middleware import base
+
+LOG = logging.getLogger(__name__)
+
+OPTS = [
+    cfg.StrOpt('http_basic_auth_user_file',
+               default='/etc/htpasswd',
+               help="HTTP basic auth password file.")
+]
+
+cfg.CONF.register_opts(OPTS, group='oslo_middleware')
+
+
+class ConfigInvalid(Exception):
+    def __init__(self, error_msg):
+        super().__init__(
+            'Invalid configuration file. %(error_msg)s')
+
+
+class BasicAuthMiddleware(base.ConfigurableMiddleware):
+    """Middleware which performs HTTP basic authentication on requests"""
+
+    def __init__(self, application, conf=None):
+        super().__init__(application, conf)
+        self.auth_file = cfg.CONF.oslo_middleware.http_basic_auth_user_file
+        validate_auth_file(self.auth_file)
+
+    def format_exception(self, e):
+        result = {'error': {'message': str(e), 'code': 401}}
+        headers = [('Content-Type', 'application/json')]
+        return webob.Response(content_type='application/json',
+                              status_code=401,
+                              json_body=result,
+                              headerlist=headers)
+
+    @webob.dec.wsgify
+    def __call__(self, req):
+        try:
+            token = parse_header(req.environ)
+            username, password = parse_token(token)
+            req.environ.update(authenticate(
+                self.auth_file, username, password))
+            return self.application
+        except Exception as e:
+            response = self.format_exception(e)
+            return self.process_response(response)
+
+
+def authenticate(auth_file, username, password):
+    """Finds username and password match in Apache style user auth file
+
+    The user auth file format is expected to comply with Apache
+    documentation[1] however the bcrypt password digest is the *only*
+    digest format supported.
+
+    [1] https://httpd.apache.org/docs/current/misc/password_encryptions.html
+
+    :param: auth_file: Path to user auth file
+    :param: username: Username to authenticate
+    :param: password: Password encoded as bytes
+    :returns: A dictionary of WSGI environment values to append to the request
+    :raises: HTTPUnauthorized, if no file entries match username/password
+    """
+
+    line_prefix = username + ':'
+    try:
+        with open(auth_file, 'r') as f:
+            for line in f:
+                entry = line.strip()
+                if entry and entry.startswith(line_prefix):
+                    return auth_entry(entry, password)
+    except OSError as exc:
+        LOG.error('Problem reading auth file: %s', exc)
+        raise webob.exc.HTTPBadRequest(
+            detail='Problem reading auth file')
+    # reached end of file with no matches
+    LOG.info('User %s not found', username)
+    raise webob.exc.HTTPUnauthorized()
+
+
+def auth_entry(entry, password):
+    """Compare a password with a single user auth file entry
+
+    :param: entry: Line from auth user file to use for authentication
+    :param: password: Password encoded as bytes
+    :returns: A dictionary of WSGI environment values to append to the request
+    :raises: HTTPUnauthorized, if the entry doesn't match supplied password or
+        if the entry is crypted with a method other than bcrypt
+    """
+
+    username, crypted = parse_entry(entry)
+    if not bcrypt.checkpw(password, crypted):
+        LOG.info('Password for %s does not match', username)
+        raise webob.exc.HTTPUnauthorized()
+    return {
+        'HTTP_X_USER': username,
+        'HTTP_X_USER_NAME': username
+    }
+
+
+def validate_auth_file(auth_file):
+    """Read the auth user file and validate its correctness
+
+    :param: auth_file: Path to user auth file
+    :raises: ConfigInvalid on validation error
+    """
+
+    try:
+        with open(auth_file, 'r') as f:
+            for line in f:
+                entry = line.strip()
+                if entry and ':' in entry:
+                    parse_entry(entry)
+    except OSError:
+        raise ConfigInvalid(error_msg='Problem reading auth user file')
+
+
+def parse_entry(entry):
+    """Extrace the username and crypted password from a user auth file entry
+
+    :param: entry: Line from auth user file to use for authentication
+    :returns: a tuple of username and crypted password
+    :raises: ConfigInvalid if the password is not in the supported bcrypt
+    format
+    """
+
+    username, crypted_str = entry.split(':', maxsplit=1)
+    crypted = crypted_str.encode('utf-8')
+    if crypted[:4] not in (b'$2y$', b'$2a$', b'$2b$'):
+        error_msg = ('Only bcrypt digested passwords are supported for '
+                     '%(username)s') % {'username': username}
+        raise webob.exc.HTTPBadRequest(detail=error_msg)
+    return username, crypted
+
+
+def parse_token(token):
+    """Parse the token portion of the Authentication header value
+
+    :param: token: Token value from basic authorization header
+    :returns: tuple of username, password
+    :raises: BadRequest, if username and password could not be parsed for any
+        reason
+    """
+
+    try:
+        if isinstance(token, str):
+            token = token.encode('utf-8')
+        auth_pair = base64.b64decode(token, validate=True)
+        (username, password) = auth_pair.split(b':', maxsplit=1)
+        return (username.decode('utf-8'), password)
+    except (TypeError, binascii.Error, ValueError) as exc:
+        LOG.info('Could not decode authorization token: %s', exc)
+        raise webob.exc.HTTPBadRequest(detail=(
+            'Could not decode authorization token'))
+
+
+def parse_header(env):
+    """Parse WSGI environment for Authorization header of type Basic
+
+    :param: env: WSGI environment to get header from
+    :returns: Token portion of the header value
+    :raises: HTTPUnauthorized, if header is missing or if the type is not Basic
+    """
+
+    try:
+        auth_header = env.pop('HTTP_AUTHORIZATION')
+    except KeyError:
+        LOG.info('No authorization token received')
+        raise webob.exc.HTTPUnauthorized()
+    try:
+        auth_type, token = auth_header.strip().split(maxsplit=1)
+    except (ValueError, AttributeError) as exc:
+        LOG.info('Could not parse Authorization header: %s', exc)
+        raise webob.exc.HTTPBadRequest(detail=(
+            'Could not parse Authorization header'))
+    if auth_type.lower() != 'basic':
+        error_msg = ('Unsupported authorization type "%s"') % auth_type
+        LOG.info(error_msg)
+        raise webob.exc.HTTPBadRequest(detail=error_msg)
+    return token
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo_middleware/healthcheck/__init__.py 
new/oslo.middleware-4.4.0/oslo_middleware/healthcheck/__init__.py
--- old/oslo.middleware-4.2.0/oslo_middleware/healthcheck/__init__.py   
2021-03-11 21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo_middleware/healthcheck/__init__.py   
2021-08-12 10:36:30.000000000 +0200
@@ -65,6 +65,12 @@
       the activity of the server.
     * *(and more)*
 
+    .. note::
+
+        This middleware indicates that the API is accessible but it does
+        indicate that it is necessarily functional or that any other API
+        request will actually work.
+
     Example requests/responses (**not** detailed mode)::
 
       $ curl -i -X HEAD "http://0.0.0.0:8775/healthcheck";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo_middleware/tests/test_auth_basic.py 
new/oslo.middleware-4.4.0/oslo_middleware/tests/test_auth_basic.py
--- old/oslo.middleware-4.2.0/oslo_middleware/tests/test_auth_basic.py  
1970-01-01 01:00:00.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo_middleware/tests/test_auth_basic.py  
2021-08-12 10:36:30.000000000 +0200
@@ -0,0 +1,174 @@
+# Copyright 2012 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.
+
+import base64
+import os
+import tempfile
+
+from oslo_config import cfg
+import webob
+
+from oslo_middleware import basic_auth as auth
+from oslotest import base as test_base
+
+
+class TestAuthBasic(test_base.BaseTestCase):
+    def setUp(self):
+        super().setUp()
+
+        @webob.dec.wsgify
+        def fake_app(req):
+            return webob.Response()
+        self.fake_app = fake_app
+        self.request = webob.Request.blank('/')
+
+    def write_auth_file(self, data=None):
+        if not data:
+            data = '\n'
+        with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
+            f.write(data)
+            self.addCleanup(os.remove, f.name)
+            return f.name
+
+    def test_middleware_authenticate(self):
+        auth_file = self.write_auth_file(
+            'myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+            'JETVCWBkc32C63UP2aYrGoYOEpbJm\n\n\n')
+        cfg.CONF.set_override('http_basic_auth_user_file',
+                              auth_file, group='oslo_middleware')
+        self.middleware = auth.BasicAuthMiddleware(self.fake_app)
+        self.request.environ[
+            'HTTP_AUTHORIZATION'] = 'Basic bXlOYW1lOm15UGFzc3dvcmQ='
+        response = self.request.get_response(self.middleware)
+        self.assertEqual('200 OK', response.status)
+
+    def test_middleware_unauthenticated(self):
+        auth_file = self.write_auth_file(
+            'myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+            'JETVCWBkc32C63UP2aYrGoYOEpbJm\n\n\n')
+        cfg.CONF.set_override('http_basic_auth_user_file',
+                              auth_file, group='oslo_middleware')
+
+        self.middleware = auth.BasicAuthMiddleware(self.fake_app)
+        response = self.request.get_response(self.middleware)
+        self.assertEqual('401 Unauthorized', response.status)
+
+    def test_authenticate(self):
+        auth_file = self.write_auth_file(
+            'foo:bar\nmyName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+            'JETVCWBkc32C63UP2aYrGoYOEpbJm\n\n\n')
+        # test basic auth
+        self.assertEqual(
+            {'HTTP_X_USER': 'myName', 'HTTP_X_USER_NAME': 'myName'},
+            auth.authenticate(
+                auth_file, 'myName', b'myPassword')
+        )
+        # test failed auth
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.authenticate,
+                              auth_file, 'foo', b'bar')
+        self.assertEqual('Only bcrypt digested '
+                         'passwords are supported for foo', str(e))
+        # test problem reading user data file
+        auth_file = auth_file + '.missing'
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.authenticate,
+                              auth_file, 'myName',
+                              b'myPassword')
+        self.assertEqual(
+            'Problem reading auth file', str(e))
+
+    def test_auth_entry(self):
+        entry_pass = ('myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+                      'JETVCWBkc32C63UP2aYrGoYOEpbJm')
+        entry_fail = 'foo:bar'
+        # success
+        self.assertEqual(
+            {'HTTP_X_USER': 'myName', 'HTTP_X_USER_NAME': 'myName'},
+            auth.auth_entry(entry_pass, b'myPassword')
+        )
+        # failed, unknown digest format
+        ex = self.assertRaises(webob.exc.HTTPBadRequest,
+                               auth.auth_entry, entry_fail, b'bar')
+        self.assertEqual('Only bcrypt digested '
+                         'passwords are supported for foo', str(ex))
+        # failed, incorrect password
+        self.assertRaises(webob.exc.HTTPUnauthorized,
+                          auth.auth_entry, entry_pass, b'bar')
+
+    def test_validate_auth_file(self):
+        auth_file = self.write_auth_file(
+            'myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+            'JETVCWBkc32C63UP2aYrGoYOEpbJm\n\n\n')
+        # success, valid config
+        auth.validate_auth_file(auth_file)
+        # failed, missing auth file
+        auth_file = auth_file + '.missing'
+        self.assertRaises(auth.ConfigInvalid,
+                          auth.validate_auth_file, auth_file)
+        # failed, invalid entry
+        auth_file = self.write_auth_file(
+            'foo:bar\nmyName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.'
+            'JETVCWBkc32C63UP2aYrGoYOEpbJm\n\n\n')
+        self.assertRaises(webob.exc.HTTPBadRequest,
+                          auth.validate_auth_file, auth_file)
+
+    def test_parse_token(self):
+        # success with bytes
+        token = base64.b64encode(b'myName:myPassword')
+        self.assertEqual(
+            ('myName', b'myPassword'),
+            auth.parse_token(token)
+        )
+        # success with string
+        token = str(token, encoding='utf-8')
+        self.assertEqual(
+            ('myName', b'myPassword'),
+            auth.parse_token(token)
+        )
+        # failed, invalid base64
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.parse_token, token[:-1])
+        self.assertEqual('Could not decode authorization token', str(e))
+        # failed, no colon in token
+        token = str(base64.b64encode(b'myNamemyPassword'), encoding='utf-8')
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.parse_token, token[:-1])
+        self.assertEqual('Could not decode authorization token', str(e))
+
+    def test_parse_header(self):
+        auth_value = 'Basic bXlOYW1lOm15UGFzc3dvcmQ='
+        # success
+        self.assertEqual(
+            'bXlOYW1lOm15UGFzc3dvcmQ=',
+            auth.parse_header({
+                'HTTP_AUTHORIZATION': auth_value
+            })
+        )
+        # failed, missing Authorization header
+        e = self.assertRaises(webob.exc.HTTPUnauthorized,
+                              auth.parse_header,
+                              {})
+        # failed missing token
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.parse_header,
+                              {'HTTP_AUTHORIZATION': 'Basic'})
+        self.assertEqual('Could not parse Authorization header', str(e))
+        # failed, type other than Basic
+        digest_value = 'Digest username="myName" nonce="foobar"'
+        e = self.assertRaises(webob.exc.HTTPBadRequest,
+                              auth.parse_header,
+                              {'HTTP_AUTHORIZATION': digest_value})
+        self.assertEqual('Unsupported authorization type "Digest"', str(e))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/oslo_middleware/tests/test_catch_errors.py 
new/oslo.middleware-4.4.0/oslo_middleware/tests/test_catch_errors.py
--- old/oslo.middleware-4.2.0/oslo_middleware/tests/test_catch_errors.py        
2021-03-11 21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/oslo_middleware/tests/test_catch_errors.py        
2021-08-12 10:36:30.000000000 +0200
@@ -60,7 +60,7 @@
 
         app = catch_errors.CatchErrors(application)
         req = webob.Request.blank('/test',
-                                  text=u'test data',
+                                  text='test data',
                                   method='POST',
                                   headers={'X-Auth-Token': 'secret1',
                                            'X-Service-Token': 'secret2',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/releasenotes/notes/basic-auth-middleware-5f812399e325425f.yaml
 
new/oslo.middleware-4.4.0/releasenotes/notes/basic-auth-middleware-5f812399e325425f.yaml
--- 
old/oslo.middleware-4.2.0/releasenotes/notes/basic-auth-middleware-5f812399e325425f.yaml
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/oslo.middleware-4.4.0/releasenotes/notes/basic-auth-middleware-5f812399e325425f.yaml
    2021-08-12 10:36:30.000000000 +0200
@@ -0,0 +1,12 @@
+---
+features:
+  - |
+    Adds a basic http auth middleware as an alternative to noauth in
+    standalone environments. This middleware uses a password file which
+    supports the Apache `htpasswd`_ syntax. This file is read for every
+    request, so no service restart is required when changes are made.
+    The only password digest supported is bcrypt, and the ``bcrypt``
+    python library is used for password checks since it supports ``$2y$``
+    prefixed bcrypt passwords as generated by the Apache htpasswd utility.
+
+    .. _htpasswd: 
https://httpd.apache.org/docs/current/misc/password_encryptions.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/releasenotes/source/conf.py 
new/oslo.middleware-4.4.0/releasenotes/source/conf.py
--- old/oslo.middleware-4.2.0/releasenotes/source/conf.py       2021-03-11 
21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/releasenotes/source/conf.py       2021-08-12 
10:36:30.000000000 +0200
@@ -56,7 +56,7 @@
 master_doc = 'index'
 
 # General information about the project.
-copyright = u'2016, oslo.middleware Developers'
+copyright = '2016, oslo.middleware Developers'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -181,8 +181,8 @@
 # (source start file, name, description, authors, manual section).
 man_pages = [
     ('index', 'oslo.middlewareReleaseNotes',
-     u'oslo.middleware Release Notes Documentation',
-     [u'oslo.middleware Developers'], 1)
+     'oslo.middleware Release Notes Documentation',
+     ['oslo.middleware Developers'], 1)
 ]
 
 # If true, show URL addresses after external links.
@@ -196,8 +196,8 @@
 #  dir menu entry, description, category)
 texinfo_documents = [
     ('index', 'oslo.middlewareReleaseNotes',
-     u'oslo.middleware Release Notes Documentation',
-     u'oslo.middleware Developers', 'oslo.middlewareReleaseNotes',
+     'oslo.middleware Release Notes Documentation',
+     'oslo.middleware Developers', 'oslo.middlewareReleaseNotes',
      'The library includes components that can be injected into wsgi pipelines'
      ' to intercept request/response flows.',
      'Miscellaneous'),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/releasenotes/source/index.rst 
new/oslo.middleware-4.4.0/releasenotes/source/index.rst
--- old/oslo.middleware-4.2.0/releasenotes/source/index.rst     2021-03-11 
21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/releasenotes/source/index.rst     2021-08-12 
10:36:30.000000000 +0200
@@ -6,6 +6,7 @@
     :maxdepth: 1
 
     unreleased
+    wallaby
     victoria
     ussuri
     train
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.middleware-4.2.0/releasenotes/source/wallaby.rst 
new/oslo.middleware-4.4.0/releasenotes/source/wallaby.rst
--- old/oslo.middleware-4.2.0/releasenotes/source/wallaby.rst   1970-01-01 
01:00:00.000000000 +0100
+++ new/oslo.middleware-4.4.0/releasenotes/source/wallaby.rst   2021-08-12 
10:36:30.000000000 +0200
@@ -0,0 +1,6 @@
+============================
+Wallaby Series Release Notes
+============================
+
+.. release-notes::
+   :branch: stable/wallaby
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/requirements.txt 
new/oslo.middleware-4.4.0/requirements.txt
--- old/oslo.middleware-4.2.0/requirements.txt  2021-03-11 21:41:04.000000000 
+0100
+++ new/oslo.middleware-4.4.0/requirements.txt  2021-08-12 10:36:30.000000000 
+0200
@@ -12,3 +12,4 @@
 WebOb>=1.8.0 # MIT
 debtcollector>=1.2.0 # Apache-2.0
 statsd>=3.2.1 # MIT
+bcrypt>=3.1.3 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/setup.cfg 
new/oslo.middleware-4.4.0/setup.cfg
--- old/oslo.middleware-4.2.0/setup.cfg 2021-03-11 21:41:52.863160100 +0100
+++ new/oslo.middleware-4.4.0/setup.cfg 2021-08-12 10:37:04.363057400 +0200
@@ -1,12 +1,12 @@
 [metadata]
 name = oslo.middleware
 summary = Oslo Middleware library
-description-file = 
+description_file = 
        README.rst
 author = OpenStack
-author-email = [email protected]
-home-page = https://docs.openstack.org/oslo.middleware/latest/
-python-requires = >=3.6
+author_email = [email protected]
+home_page = https://docs.openstack.org/oslo.middleware/latest/
+python_requires = >=3.6
 classifier = 
        Environment :: OpenStack
        Intended Audience :: Information Technology
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.middleware-4.2.0/tox.ini 
new/oslo.middleware-4.4.0/tox.ini
--- old/oslo.middleware-4.2.0/tox.ini   2021-03-11 21:41:04.000000000 +0100
+++ new/oslo.middleware-4.4.0/tox.ini   2021-08-12 10:36:30.000000000 +0200
@@ -1,6 +1,6 @@
 [tox]
 minversion = 3.1
-envlist = py38,pep8
+envlist = py3,pep8
 ignore_basepython_conflict = true
 
 [testenv]
@@ -49,9 +49,3 @@
 commands =
   rm -rf releasenotes/build
   sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html 
releasenotes/source releasenotes/build/html
-
-[testenv:lower-constraints]
-deps =
-  -c{toxinidir}/lower-constraints.txt
-  -r{toxinidir}/test-requirements.txt
-  -r{toxinidir}/requirements.txt

Reply via email to