Uploaded image for project: 'Project Quay'
  1. Project Quay
  2. PROJQUAY-1576

Mirror configurations cannot be decoded after QuayRegistry reconciliation

XMLWordPrintable

    • 0

      Passwords saved in the repomirror configuration cannot be decoded after complete Quay restart (for example, after MCO updates worker nodes). The following stack trace appers in the logs:

      gunicorn-web stdout | 2021-02-10 13:51:57,967 [300] [ERROR] [data.encryption] Got exception when trying to decrypt value `iK1I2kkOEesFY/m32sWLS8wVDT0jhVRBYiGhNI0Zr2cCTWLh69w=`
      gunicorn-web stdout | Traceback (most recent call last):
      gunicorn-web stdout |   File "/quay-registry/data/encryption.py", line 44, in _decrypt_ccm
      gunicorn-web stdout |     decrypted = aesccm.decrypt(nonce, ct, None)
      gunicorn-web stdout |   File "/usr/local/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/aead.py", line 120, in decrypt
      gunicorn-web stdout |     return aead._decrypt(
      gunicorn-web stdout |   File "/usr/local/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/aead.py", line 151, in _decrypt
      gunicorn-web stdout |     raise InvalidTag
      gunicorn-web stdout | cryptography.exceptions.InvalidTag
      gunicorn-web stdout | 2021-02-10 13:51:57,969 [300] [ERROR] [gunicorn.error] Error handling request /api/v1/repository/ibazulic/mirror/mirror
      gunicorn-web stdout | Traceback (most recent call last):
      gunicorn-web stdout |   File "/quay-registry/data/encryption.py", line 44, in _decrypt_ccm
      gunicorn-web stdout |     decrypted = aesccm.decrypt(nonce, ct, None)
      gunicorn-web stdout |   File "/usr/local/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/aead.py", line 120, in decrypt
      gunicorn-web stdout |     return aead._decrypt(
      gunicorn-web stdout |   File "/usr/local/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/aead.py", line 151, in _decrypt
      gunicorn-web stdout |     raise InvalidTag
      gunicorn-web stdout | cryptography.exceptions.InvalidTag
      gunicorn-web stdout | During handling of the above exception, another exception occurred:
      gunicorn-web stdout | Traceback (most recent call last):
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/mirror.py", line 235, in get
      gunicorn-web stdout |     username = self._decrypt_username(mirror.external_registry_username)
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/mirror.py", line 566, in _decrypt_username
      gunicorn-web stdout |     return username.decrypt()
      gunicorn-web stdout |   File "/quay-registry/data/fields.py", line 119, in decrypt
      gunicorn-web stdout |     return encrypter.decrypt_value(self.encrypted_value)
      gunicorn-web stdout |   File "/quay-registry/data/encryption.py", line 97, in decrypt_value
      gunicorn-web stdout |     return _VERSIONS[version_prefix].decrypt(self._secret_key, data)
      gunicorn-web stdout |   File "/quay-registry/data/encryption.py", line 48, in _decrypt_ccm
      gunicorn-web stdout |     raise DecryptionFailureException()
      gunicorn-web stdout | data.encryption.DecryptionFailureException
      gunicorn-web stdout | During handling of the above exception, another exception occurred:
      gunicorn-web stdout | Traceback (most recent call last):
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 55, in handle
      gunicorn-web stdout |     self.handle_request(listener_name, req, client, addr)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/ggevent.py", line 143, in handle_request
      gunicorn-web stdout |     super().handle_request(listener_name, req, sock, addr)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 106, in handle_request
      gunicorn-web stdout |     respiter = self.wsgi(environ, resp.start_response)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2463, in __call__
      gunicorn-web stdout |     return self.wsgi_app(environ, start_response)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 232, in __call__
      gunicorn-web stdout |     return self.app(environ, start_response)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2449, in wsgi_app
      gunicorn-web stdout |     response = self.handle_exception(e)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 269, in error_router
      gunicorn-web stdout |     return original_handler(e)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1866, in handle_exception
      gunicorn-web stdout |     reraise(exc_type, exc_value, tb)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 38, in reraise
      gunicorn-web stdout |     raise value.with_traceback(tb)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2446, in wsgi_app
      gunicorn-web stdout |     response = self.full_dispatch_request()
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1951, in full_dispatch_request
      gunicorn-web stdout |     rv = self.handle_user_exception(e)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 269, in error_router
      gunicorn-web stdout |     return original_handler(e)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1820, in handle_user_exception
      gunicorn-web stdout |     reraise(exc_type, exc_value, tb)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 38, in reraise
      gunicorn-web stdout |     raise value.with_traceback(tb)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1949, in full_dispatch_request
      gunicorn-web stdout |     rv = self.dispatch_request()
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1935, in dispatch_request
      gunicorn-web stdout |     return self.view_functions[rule.endpoint](**req.view_args)
      gunicorn-web stdout |   File "/quay-registry/endpoints/decorators.py", line 197, in wrapper
      gunicorn-web stdout |     return func(*args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/auth/decorators.py", line 65, in wrapper
      gunicorn-web stdout |     return func(*args, **kwargs)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask_restful/utils/cors.py", line 35, in wrapped_function
      gunicorn-web stdout |     resp = make_response(f(*args, **kwargs))
      gunicorn-web stdout |   File "/quay-registry/endpoints/csrf.py", line 73, in wrapper
      gunicorn-web stdout |     resp = func(*args, **kwargs)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 458, in wrapper
      gunicorn-web stdout |     resp = resource(*args, **kwargs)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask/views.py", line 89, in view
      gunicorn-web stdout |     return self.dispatch_request(*args, **kwargs)
      gunicorn-web stdout |   File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
      gunicorn-web stdout |     resp = meth(*args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/decorators.py", line 141, in wrapper
      gunicorn-web stdout |     return func(*args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/__init__.py", line 241, in wrapper
      gunicorn-web stdout |     return func(namespace, repository, *args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/decorators.py", line 120, in wrapper
      gunicorn-web stdout |     return func(*args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/__init__.py", line 295, in wrapped
      gunicorn-web stdout |     return func(self, namespace, repository, *args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/__init__.py", line 466, in wrapped
      gunicorn-web stdout |     resp = func(self, *args, **kwargs)
      gunicorn-web stdout |   File "/quay-registry/endpoints/api/mirror.py", line 237, in get
      gunicorn-web stdout |     logger.warning(
      gunicorn-web stdout | NameError: name 'logger' is not defined
      gunicorn-web stdout | 2021-02-10 13:51:57,971 [300] [INFO] [gunicorn.access]  - - [10/Feb/2021:13:51:57 +0000] "GET /api/v1/repository/ibazulic/mirror/mirror HTTP/1.0" 500 0 "-" "-"
      

      The workaround is to disable mirror configuration and to delete the config from the db directly. Then access to these repos is once again established:

      quay-quay-database=#select * from repository;
       id | namespace_user_id |  name  | visibility_id | description |             badge_token              | kind_id | trust_enabled | state 
      ----+-------------------+--------+---------------+-------------+--------------------------------------+---------+---------------+-------
        1 |                 1 | mirror |             2 |             | e7c5d7ed-7686-4459-a90d-5d30fa40c655 |       1 | f             |     2
        2 |                 1 | test-2 |             2 |             | fd0bdf59-80ae-4d67-b96f-cc83bcd0a5e8 |       1 | f             |     0
        3 |                 1 | test-3 |             2 |             | 7a212a44-1a2b-420b-aedd-39833f43ce1f |       1 | f             |     0
        4 |                 1 | test-4 |             2 |             | 2496399b-bc42-441b-abbf-02d86aed650a |       1 | f             |     0
        5 |                 3 | test-1 |             2 |             | a9de9269-0873-46d1-8e44-beae0aa7be6a |       1 | f             |     0
        6 |                 3 | test-2 |             2 |             | b24299b8-da9f-48d2-9eb5-6bd2e4a5cac2 |       1 | f             |     0
        7 |                 3 | test-3 |             2 |             | a5b1c292-d3b8-47d1-95a0-0e8b873fddda |       1 | f             |     0
        8 |                 3 | test-4 |             2 |             | 3b216021-c89b-487c-b1e5-7561ad1d901e |       1 | f             |     0
      (8 rows)
      
      quay-quay-database=# update repository set state = 0 where id=1;
      UPDATE 1
      quay-quay-database=# delete from repomirrorconfig where repository_id = 1;
      DELETE 1
      quay-quay-database=# delete from repomirrorrule where repository_id = 1;
      DELETE 1
      

      However, this is not feasible when one has a lot of mirror repositories defined.

            rhn-coreos-amerdler Alec Merdler (Inactive)
            rhn-support-ibazulic Ivan Bazulic
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: