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:
query_params = []
headers = {'Accept': 'application/vnd.api+json', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiaT...hGpcYCOCsmDUo4MOEkbbMLVkjRMWlU', 'Content-Type': 'application/json', 'Origin': 'https:, ...}
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:
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