Uploaded image for project: 'Subscription Watch'
  1. Subscription Watch
  2. SWATCH-3974 Evaluate post-stage test failures to prepare for prod release
  3. SWATCH-4069

test_rbac.py::test_verify_rbac_not_opt_in_and_with_subscriptions_user_permission

XMLWordPrintable

    • Icon: Sub-task Sub-task
    • Resolution: Unresolved
    • Icon: Normal Normal
    • None
    • None
    • None
    • False
    • Hide

      None

      Show
      None
    • False
    • subs-swatch-thunder
    • Swatch Thunder Sprint 2

      https://reportportal-smqe.apps.dno.ocp-hub.prod.psi.redhat.com/ui/#subscription_watch/launches/all/347065/28748121/log?item0Params=filter.eq.hasStats%3Dtrue%26filter.eq.hasChildren%3Dfalse%26filter.in.type%3DSTEP%26filter.in.status%3DFAILED&logParams=history%3D28748121%26page.page%3D1

       

      application = <iqe.base.application.Application object at 0x7fed72b45b80>
      remove_all_groups = None
      add_non_admin_user_to_swatch_read_group = {'admin_default': False,
       'created': datetime.datetime(2025, 10, 7, 21, 12, 22, 23994, tzinfo=tzlocal()),
       'descriptio...: False,
       'principal_count': None,
       'role_count': 0,
       'system': False,
       'uuid': '4293e520-060b-4348-9b3e-90521ac6d161'}
      rhsm_non_admin_user = <Box: {'auth': {'username': 'rbacnoadmin25', 'password': 'redhatswatchqe', 'refresh_token': 'eyJhbGciOiJIUzUxMiIsInR5c...bGllbnRfdHlwZS5wcmVfa2MyNSJ9.4Clf_kqEzHBXfqJAtIrSqjfTG36sQGLgK6Q8ixzYw3wyd1WEJgKzkV9I92aNmZFxNvbVR9Tudqf756pO6KPd_A'}}>
      
          @pytest.mark.post_stage_deploy
          def test_verify_rbac_not_opt_in_and_with_subscriptions_user_permission(
              application,
              remove_all_groups,
              add_non_admin_user_to_swatch_read_group,
              rhsm_non_admin_user,
          ):
              """Verify user not able to access apis with role Subscription user role
              and without opt-in.
          
                 JIRA: ENT-3284
                 metadata:
                     assignee: aunayak
                     negative: true
                     importance: high
                     level: system
                     test_steps:
                         1. Create new group with subscriptions user role
                         2. Add user to group.
                         3. Delete opt-in config
                         4. See if user can not access different swatch apis .
                     expected_results:
                         1. User should not be able to access apis.
              """
              product_id = "RHEL for x86"
              metric_id = get_random_choice_or_first(
                  config_parser.get_swatch_metric_id_from_tag_metrics(product_id=product_id)
              )
              with application.copy_using(user=rhsm_non_admin_user) as app:
      >           app.rhsm_subscriptions.rest_client.opt_in_api.delete_opt_in_config()
      
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions/tests/integration/rbac/test_rbac.py:384: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:771: in __call__
          return self.callable(self, *args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api/opt_in_api.py:98: in __delete_opt_in_config
          return self.call_with_http_info(**kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:833: in call_with_http_info
          return self.api_client.call_api(
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:153: in call_api
          resp = super().call_api(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:408: in call_api
          return self.__call_api(resource_path, method,
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:202: in __call_api
          raise e
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:195: in __call_api
          response_data = self.request(
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:130: in request
          raise err
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:124: in request
          response = super().request(
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/api_client.py:478: in request
          return self.rest_client.DELETE(url,
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/rest.py:257: in DELETE
          return self.request("DELETE", url,
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = <iqe_rhsm_subscriptions_api.rest.RESTClientObject object at 0x7fed6ae4cec0>
      method = 'DELETE'
      url = 'https://console.stage.redhat.com/api/rhsm-subscriptions/v1/opt-in'
      query_params = []
      headers = {'Accept': 'application/vnd.api+json', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiaT...hGpcYCOCsmDUo4MOEkbbMLVkjRMWlU', 'Content-Type': 'application/json', 'Origin': 'https://console.stage.redhat.com', ...}
      body = None, post_params = {}, _preload_content = True, _request_timeout = None
      
          def request(self, method, url, query_params=None, headers=None,
                      body=None, post_params=None, _preload_content=True,
                      _request_timeout=None):
              """Perform requests.
          
              :param method: http request method
              :param url: http request url
              :param query_params: query parameters in the url
              :param headers: http request headers
              :param body: request json body, for `application/json`
              :param post_params: request post parameters,
                                  `application/x-www-form-urlencoded`
                                  and `multipart/form-data`
              :param _preload_content: if False, the urllib3.HTTPResponse object will
                                       be returned without reading/decoding response
                                       data. Default is True.
              :param _request_timeout: timeout setting for this request. If one
                                       number provided, it will be total request
                                       timeout. It can also be a pair (tuple) of
                                       (connection, read) timeouts.
              """
              method = method.upper()
              assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
                                'PATCH', 'OPTIONS']
          
              if post_params and body:
                  raise ApiValueError(
                      "body parameter cannot be used with post_params parameter."
                  )
          
              post_params = post_params or {}
              headers = headers or {}
          
              timeout = None
              if _request_timeout:
                  if isinstance(_request_timeout, (int, float)):  # noqa: E501,F821
                      timeout = urllib3.Timeout(total=_request_timeout)
                  elif (isinstance(_request_timeout, tuple) and
                        len(_request_timeout) == 2):
                      timeout = urllib3.Timeout(
                          connect=_request_timeout[0], read=_request_timeout[1])
          
              if 'Content-Type' not in headers:
                  headers['Content-Type'] = 'application/json'
          
              try:
                  # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
                  if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
                      if query_params:
                          url += '?' + urlencode(query_params)
                      if re.search('json', headers['Content-Type'], re.IGNORECASE):
                          request_body = None
                          if body is not None:
                              request_body = json.dumps(body)
                          r = self.pool_manager.request(
                              method, url,
                              body=request_body,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
                          r = self.pool_manager.request(
                              method, url,
                              fields=post_params,
                              encode_multipart=False,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      elif headers['Content-Type'] == 'multipart/form-data':
                          # must del headers['Content-Type'], or the correct
                          # Content-Type which generated by urllib3 will be
                          # overwritten.
                          del headers['Content-Type']
                          r = self.pool_manager.request(
                              method, url,
                              fields=post_params,
                              encode_multipart=True,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      # Pass a `string` parameter directly in the body to support
                      # other content types than Json when `body` argument is
                      # provided in serialized form
                      elif isinstance(body, str) or isinstance(body, bytes):
                          request_body = body
                          r = self.pool_manager.request(
                              method, url,
                              body=request_body,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      else:
                          # Cannot generate the request from given parameters
                          msg = """Cannot prepare a request message for provided
                                   arguments. Please check that your arguments match
                                   declared content type."""
                          raise ApiException(status=0, reason=msg)
                  # For `GET`, `HEAD`
                  else:
                      r = self.pool_manager.request(method, url,
                                                    fields=query_params,
                                                    preload_content=_preload_content,
                                                    timeout=timeout,
                                                    headers=headers)
              except urllib3.exceptions.SSLError as e:
                  msg = "{0}\n{1}".format(type(e).__name__, str(e))
                  raise ApiException(status=0, reason=msg)
          
              if _preload_content:
                  r = RESTResponse(r)
          
                  # log response body
                  logger.debug("response body: %s", r.data)
          
              if not 200 <= r.status <= 299:
                  if r.status == 401:
                      raise UnauthorizedException(http_resp=r)
          
                  if r.status == 403:
      >               raise ForbiddenException(http_resp=r)
      E               iqe_rhsm_subscriptions_api.exceptions.ForbiddenException: (403)
      E               Reason: Forbidden
      E               HTTP response headers: HTTPHeaderDict({'Server': 'openresty', 'Content-Type': 'application/vnd.api+json', 'Content-Length': '105', 'x-rh-insights-request-id': 'a607240c23964c33b93be67cb7d98f43', 'traceresponse': '00-79aab28bcdf771c261f2d3df0bddf3e9-bfd832bd306407fe-00', 'x-content-type-options': 'nosniff', 'x-xss-protection': '0', 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'strict-transport-security': 'max-age=31536000 ; includeSubDomains', 'x-frame-options': 'DENY', 'Date': 'Tue, 07 Oct 2025 21:12:25 GMT', 'Connection': 'keep-alive', 'Set-Cookie': 'JSESSIONID=D01592F684373F5482C182D2529400A0; Path=/; Secure; HttpOnly, e15dd7c1deaec3a6b67fca153d520b0b=eee5d1ce02ee767654441b8bfe3b6c56; path=/; HttpOnly; Secure; SameSite=None', 'x-rh-edge-request-id': '3ecb174b', 'x-rh-edge-reference-id': '0.9a6bdc17.1759871545.3ecb174b', 'x-rh-edge-cache-status': 'NotCacheable from child'})
      E               HTTP response body: {"errors":[{"status":"403","code":"SUBSCRIPTIONS1003","title":"Access Denied","detail":"Access Denied"}]}
      
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions_api/rest.py:217: ForbiddenException2025-10-07 17:12:25Jump Toapplication = <iqe.base.application.Application object at 0x7fed72b45b80>
      rhsm_admin_user = <Box: {'auth': {'username': 'rbac-admin25', 'password': 'redhatqa', 'refresh_token': 'eyJhbGciOiJIUzUxMiIsInR5cCIgOiAi...saWVudF90eXBlLnByZV9rYzI1In0.XhwEt3nAwii1BsRK8bGAm3qOFDJR5heVdg5ebKBhcUNj4bYJZty85gUKPkZ8KFXPoK7ZZ80GXt82U5cbm9nXgg'}}>
      rhsm_non_admin_user = <Box: {'auth': {'username': 'rbacnoadmin25', 'password': 'redhatswatchqe', 'refresh_token': 'eyJhbGciOiJIUzUxMiIsInR5c...bGllbnRfdHlwZS5wcmVfa2MyNSJ9.4Clf_kqEzHBXfqJAtIrSqjfTG36sQGLgK6Q8ixzYw3wyd1WEJgKzkV9I92aNmZFxNvbVR9Tudqf756pO6KPd_A'}}>
      
          @pytest.fixture(scope="function")
          def add_non_admin_user_to_swatch_read_group(application, rhsm_admin_user, rhsm_non_admin_user):
              """Non admin user should be in same account of admin user"""
              with application.copy_using(user=rhsm_admin_user) as app:
                  group = app.rbac.rest_client.group_api.create_group(
                      {"name": f"swatch-admin-{uuid.uuid4()}", "description": "test"}
                  )
                  role = app.rbac.rest_client.role_api.list_roles(name="Subscriptions user")
                  app.rbac.rest_client.group_api.add_role_to_group(group.uuid, {"roles": [role.data[0].uuid]})
                  app.rbac.rest_client.group_api.add_principal_to_group(
                      group.uuid, {"principals": [{"username": rhsm_non_admin_user.auth.username}]}
                  )
                  yield group
      >           app.rbac.rest_client.group_api.delete_group(group.uuid)
      
      /iqe_venv/lib/python3.12/site-packages/iqe_rhsm_subscriptions/fixtures/rbac.py:138: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api/group_api.py:427: in delete_group
          return self.delete_group_with_http_info(uuid, **kwargs)  # noqa: E501
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api/group_api.py:501: in delete_group_with_http_info
          return self.api_client.call_api(
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:153: in call_api
          resp = super().call_api(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api_client.py:364: in call_api
          return self.__call_api(resource_path, method,
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api_client.py:188: in __call_api
          raise e
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api_client.py:181: in __call_api
          response_data = self.request(
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:130: in request
          raise err
      /iqe_venv/lib/python3.12/site-packages/iqe/base/rest_client.py:124: in request
          response = super().request(
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/api_client.py:431: in request
          return self.rest_client.DELETE(url,
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/rest.py:256: in DELETE
          return self.request("DELETE", url,
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = <iqe_rbac_api.rest.RESTClientObject object at 0x7fed6a743e00>
      method = 'DELETE'
      url = 'https://console.stage.redhat.com/api/rbac/v1/groups/4293e520-060b-4348-9b3e-90521ac6d161/'
      query_params = []
      headers = {'Accept': 'application/json', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiaTZWTjlMQV...Y8HXdbzPQMrV371_rnWBRZCxMXQNpcwNU', 'Content-Type': 'application/json', 'User-Agent': 'OpenAPI-Generator/1.0.0/python'}
      body = None, post_params = {}, _preload_content = True, _request_timeout = None
      
          def request(self, method, url, query_params=None, headers=None,
                      body=None, post_params=None, _preload_content=True,
                      _request_timeout=None):
              """Perform requests.
          
              :param method: http request method
              :param url: http request url
              :param query_params: query parameters in the url
              :param headers: http request headers
              :param body: request json body, for `application/json`
              :param post_params: request post parameters,
                                  `application/x-www-form-urlencoded`
                                  and `multipart/form-data`
              :param _preload_content: if False, the urllib3.HTTPResponse object will
                                       be returned without reading/decoding response
                                       data. Default is True.
              :param _request_timeout: timeout setting for this request. If one
                                       number provided, it will be total request
                                       timeout. It can also be a pair (tuple) of
                                       (connection, read) timeouts.
              """
              method = method.upper()
              assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
                                'PATCH', 'OPTIONS']
          
              if post_params and body:
                  raise ApiValueError(
                      "body parameter cannot be used with post_params parameter."
                  )
          
              post_params = post_params or {}
              headers = headers or {}
          
              timeout = None
              if _request_timeout:
                  if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
                      timeout = urllib3.Timeout(total=_request_timeout)
                  elif (isinstance(_request_timeout, tuple) and
                        len(_request_timeout) == 2):
                      timeout = urllib3.Timeout(
                          connect=_request_timeout[0], read=_request_timeout[1])
          
              if 'Content-Type' not in headers:
                  headers['Content-Type'] = 'application/json'
          
              try:
                  # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
                  if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
                      if query_params:
                          url += '?' + urlencode(query_params)
                      if re.search('json', headers['Content-Type'], re.IGNORECASE):
                          request_body = None
                          if body is not None:
                              request_body = json.dumps(body)
                          r = self.pool_manager.request(
                              method, url,
                              body=request_body,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
                          r = self.pool_manager.request(
                              method, url,
                              fields=post_params,
                              encode_multipart=False,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      elif headers['Content-Type'] == 'multipart/form-data':
                          # must del headers['Content-Type'], or the correct
                          # Content-Type which generated by urllib3 will be
                          # overwritten.
                          del headers['Content-Type']
                          r = self.pool_manager.request(
                              method, url,
                              fields=post_params,
                              encode_multipart=True,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      # Pass a `string` parameter directly in the body to support
                      # other content types than Json when `body` argument is
                      # provided in serialized form
                      elif isinstance(body, str) or isinstance(body, bytes):
                          request_body = body
                          r = self.pool_manager.request(
                              method, url,
                              body=request_body,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)
                      else:
                          # Cannot generate the request from given parameters
                          msg = """Cannot prepare a request message for provided
                                   arguments. Please check that your arguments match
                                   declared content type."""
                          raise ApiException(status=0, reason=msg)
                  # For `GET`, `HEAD`
                  else:
                      r = self.pool_manager.request(method, url,
                                                    fields=query_params,
                                                    preload_content=_preload_content,
                                                    timeout=timeout,
                                                    headers=headers)
              except urllib3.exceptions.SSLError as e:
                  msg = "{0}\n{1}".format(type(e).__name__, str(e))
                  raise ApiException(status=0, reason=msg)
          
              if _preload_content:
                  r = RESTResponse(r)
          
                  # log response body
                  logger.debug("response body: %s", r.data)
          
              if not 200 <= r.status <= 299:
      >           raise ApiException(http_resp=r)
      E           iqe_rbac_api.exceptions.ApiException: (404)
      E           Reason: Not Found
      E           HTTP response headers: HTTPHeaderDict({'Server': 'openresty', 'Content-Type': 'application/json', 'Content-Length': '92', 'x-rh-insights-request-id': '1c57e6d8b28b43f9a0a8ae903ff09930', 'Allow': 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS', 'x-frame-options': 'DENY', 'x-content-type-options': 'nosniff', 'referrer-policy': 'same-origin', 'cross-origin-opener-policy': 'same-origin', 'Vary': 'origin', 'Date': 'Tue, 07 Oct 2025 21:12:26 GMT', 'Connection': 'keep-alive', 'Set-Cookie': 'e15dd7c1deaec3a6b67fca153d520b0b=edbbae54a8ac3c772b2ae6c1ba2edada; path=/; HttpOnly; Secure; SameSite=None', 'x-rh-edge-request-id': '3ecb0c23', 'x-rh-edge-reference-id': '0.9a6bdc17.1759871545.3ecb0c23', 'x-rh-edge-cache-status': 'NotCacheable from child', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'})
      E           HTTP response body: {"errors":[{"detail":"No Group matches the given query.","source":"detail","status":"404"}]}
      
      /iqe_venv/lib/python3.12/site-packages/iqe_rbac_api/rest.py:224: ApiException 

              Unassigned Unassigned
              lburnett0 Lindsey Burnett
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: