Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting login pages with filter "source eq 'global'" results in error #753

Closed
noethig opened this issue Jun 11, 2024 · 1 comment
Closed
Labels
status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience

Comments

@noethig
Copy link

noethig commented Jun 11, 2024

Describe the bug

I took the following code from the API documentation:

query_params = LoginPagesRequestBuilder.LoginPagesRequestBuilderGetQueryParameters(
    filter="source eq 'global'")

request_configuration = LoginPagesRequestBuilder.LoginPagesRequestBuilderGetRequestConfiguration(
    query_parameters=query_params)

login_pages = await graph_client.security.attack_simulation.login_pages.get(
    request_configuration=request_configuration)

Expected behavior

The function await graph_client.security.attack_simulation.login_pages.get(...) should return all login pages.

How to reproduce

Minimal working example:

import asyncio

from azure.identity.aio import ClientSecretCredential
from msgraph import GraphServiceClient
from msgraph.generated.security.attack_simulation.login_pages.login_pages_request_builder import \
    LoginPagesRequestBuilder

TENANT_ID = 'todo'
CLIENT_ID = 'todo'
CLIENT_SECRET = 'todo'


async def get_global_login_pages():

    credentials = ClientSecretCredential(TENANT_ID, CLIENT_ID, CLIENT_SECRET)
    graph_client = GraphServiceClient(credentials=credentials, scopes=['https://graph.microsoft.com/.default'])

    query_params = LoginPagesRequestBuilder.LoginPagesRequestBuilderGetQueryParameters(
            filter="source eq 'global'")

    request_configuration = LoginPagesRequestBuilder.LoginPagesRequestBuilderGetRequestConfiguration(
        query_parameters=query_params)

    result = await graph_client.security.attack_simulation.login_pages.get(
        request_configuration=request_configuration)
    return result


if __name__ == '__main__':
    response = asyncio.run(get_global_login_pages())
    print(response)

SDK Version

1.4.0

Latest version known to work for scenario above?

No response

Known Workarounds

A workaround is to just write a get request with another library. But that should be done by this SDK, if it would work...

Debug output

Click to expand log

/opt/miniconda3/envs/project-name/bin/python /Users/xxxx/Library/Application Support/JetBrains/PyCharm2024.1/scratches/scratch.py
Traceback (most recent call last):
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 199, in get_enum_value
    return enum_class[camel_case_key]  # type: ignore
  File "/opt/miniconda3/envs/project-name/lib/python3.10/enum.py", line 440, in __getitem__
    return cls._member_map_[name]
KeyError: 'Global'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/xxxx/Library/Application Support/JetBrains/PyCharm2024.1/scratches/scratch.py", line 79, in <module>
    response = asyncio.run(get_global_login_pages())
  File "/opt/miniconda3/envs/project-name/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/Users/xxxx/Library/Application Support/JetBrains/PyCharm2024.1/scratches/scratch.py", line 74, in get_global_login_pages
    result = await graph_client.security.attack_simulation.login_pages.get(request_configuration = request_configuration)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/msgraph/generated/security/attack_simulation/login_pages/login_pages_request_builder.py", line 68, in get
    return await self.request_adapter.send_async(request_info, LoginPageCollectionResponse, error_mapping)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_http/httpx_request_adapter.py", line 192, in send_async
    value = root_node.get_object_value(parsable_factory)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 212, in get_object_value
    self._assign_field_values(result)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 281, in _assign_field_values
    field_deserializer(JsonParseNode(field_value))
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/msgraph/generated/models/login_page_collection_response.py", line 40, in <lambda>
    "value": lambda n : setattr(self, 'value', n.get_collection_of_object_values(LoginPage)),
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 163, in get_collection_of_object_values
    return list(
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 165, in <lambda>
    lambda x: self._create_new_node(x).get_object_value(factory),  # type: ignore
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 212, in get_object_value
    self._assign_field_values(result)
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 281, in _assign_field_values
    field_deserializer(JsonParseNode(field_value))
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/msgraph/generated/models/login_page.py", line 75, in <lambda>
    "source": lambda n : setattr(self, 'source', n.get_enum_value(SimulationContentSource)),
  File "/opt/miniconda3/envs/project-name/lib/python3.10/site-packages/kiota_serialization_json/json_parse_node.py", line 201, in get_enum_value
    raise Exception(f'Invalid key: {camel_case_key} for enum {enum_class}.')
Exception: Invalid key: Global for enum <enum 'SimulationContentSource'>.

Process finished with exit code 1

Configuration

  • OS: MacOS Sonoma 14.5 (23F79)
  • architecture: Apple M1 Pro

I think that problem is not specific to this configuration.

Other information

Taking the same code (minimal working example) and only changing the filter from filter="source eq 'global'" to filter="source eq 'tenant'", the SDK call works as expected.

The error cause seems to be here:

msgraph/generated/models/simulation_content_source.py

Copied source code:

from enum import Enum

class SimulationContentSource(str, Enum):
    Unknown = "unknown",
    Global_ = "global",
    Tenant = "tenant",
    UnknownFutureValue = "unknownFutureValue",

The member Global_ seems to cause the problem because of the trailing _. I don't quite understand, why this members needs the trailing _ and would be happy to learn more about that.

@noethig noethig added status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience labels Jun 11, 2024
@noethig
Copy link
Author

noethig commented Jun 12, 2024

I just created a workaround that handles the serialization. Although it might not yet be optimal, it should be a great place to get started. In general it's just a replacement for the method in login_pages_request_builder.py LoginPagesRequestBuilder.get(...)

from kiota_abstractions.serialization import ParsableFactory
from kiota_abstractions.request_information import RequestInformation

from msgraph.generated.models.o_data_errors.o_data_error import ODataError
from msgraph.generated.models.login_page_collection_response import LoginPageCollectionResponse


async def __login_pages_get_all_global(self) -> Optional[LoginPageCollectionResponse]:
    url_template = '{+baseurl}/security/attackSimulation/loginPages{?%24count,%24expand,%24filter,%24orderby,%24search,%24select,%24skip,%24top}'
    path_parameters = {'base_url': 'https://graph.microsoft.com/v1.0'}
    request_info = RequestInformation(Method.GET, url_template, path_parameters)

    request_info.query_parameters = {'%24filter': "source eq 'global'", '%24select': ['id', 'displayName', 'language', 'source']}
    request_info.url = '/security/attackSimulation/loginPages?%24filter=source%20eq%20%27tenant%27&%24select=id,displayName,language,source'

    auth_token = await self.get_access_token()
    request_info.headers.try_add("Accept", "application/json")
    request_info.headers.try_add("Authorization", f"Bearer {auth_token}")

    error_mapping: Dict[str, ParsableFactory] = {
        "XXX": ODataError,
    }

    return await self.graph_client.request_adapter.send_async(request_info, LoginPageCollectionResponse, error_mapping)

The only thing to do is to get the auth_token which depends on your specific implementation.

@microsoftgraph microsoftgraph locked and limited conversation to collaborators Jun 18, 2024
@shemogumbe shemogumbe converted this issue into discussion #763 Jun 18, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience
Projects
None yet
Development

No branches or pull requests

1 participant