Skip to content

Conversation

achantavy
Copy link
Contributor

Summary

Describe your changes.

short_1

Screenshot 2025-08-06 at 3 47 12 PM

Related issues or links

Include links to relevant issues or other pages.

Checklist

Provide proof that this works (this makes reviews move faster). Please perform one or more of the following:

  • Update/add unit or integration tests.
  • Include a screenshot showing what the graph looked like before and after your changes.
  • Include console log trace showing what happened before and after your changes.
image

If you are changing a node or relationship:

If you are implementing a new intel module:

@achantavy achantavy linked an issue Aug 6, 2025 that may be closed by this pull request
@@ -45,119 +32,3 @@ def test_transform_app_role_assignments():
assert assignment3["principal_display_name"] == "Finance Team"
assert assignment3["resource_display_name"] == "Finance Tracker"
assert assignment3["principal_type"] == "Group"


@patch("cartography.intel.entra.applications.load")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing these brittle and not very useful unit tests

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cubic analysis

2 issues found across 9 files • Review in cubic

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

"display_name": "Finance Tracker Service Principal",
"reply_urls": [
"https://finance.example.com/callback",
"https://d-90663f7df1.awsapps.com/start",
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWS Identity Center instance id in this reply_urls entry is inconsistent with the corresponding login_url and aws_identity_center_instance_id values, which can cause equality assertions in tests to fail (Based on your team's feedback about ensuring mock data is internally consistent).

Prompt for AI agents
Address the following comment on tests/data/entra/applications.py at line 191:

<comment>AWS Identity Center instance id in this reply_urls entry is inconsistent with the corresponding login_url and aws_identity_center_instance_id values, which can cause equality assertions in tests to fail (Based on your team&#39;s feedback about ensuring mock data is internally consistent).</comment>

<file context>
@@ -153,3 +154,57 @@
         &quot;application_app_id&quot;: &quot;ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb&quot;,
     },
 ]
+
+MOCK_SERVICE_PRINCIPALS = [
+    ServicePrincipal(
+        id=&quot;sp-11111111-1111-1111-1111-111111111111&quot;,
+        app_id=&quot;aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee&quot;,
+        display_name=&quot;Finance Tracker Service Principal&quot;,
</file context>
Suggested change
"https://d-90663f7df1.awsapps.com/start",
"https://d-1234567890.awsapps.com/start",

✅ Addressed in 4c856f9

target_node_label: str = "AWSSSOUser"
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
{
"user_name": PropertyRef("aws_user_name"),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Target node matcher relies solely on user_name, which is not guaranteed to be unique across Identity Stores; include identity_store_id in the matcher to avoid incorrect links (Based on your team's feedback about ensuring relationship matchers use stable, unique keys).

Prompt for AI agents
Address the following comment on cartography/models/entra/entra_user_to_aws_sso.py at line 27:

<comment>Target node matcher relies solely on user_name, which is not guaranteed to be unique across Identity Stores; include identity_store_id in the matcher to avoid incorrect links (Based on your team&#39;s feedback about ensuring relationship matchers use stable, unique keys).</comment>

<file context>
@@ -0,0 +1,40 @@
+from dataclasses import dataclass
+
+from cartography.models.core.common import PropertyRef
+from cartography.models.core.relationships import CartographyRelProperties
+from cartography.models.core.relationships import CartographyRelSchema
+from cartography.models.core.relationships import LinkDirection
+from cartography.models.core.relationships import make_source_node_matcher
+from cartography.models.core.relationships import make_target_node_matcher
+from cartography.models.core.relationships import SourceNodeMatcher
</file context>

✅ Addressed in 4c856f9

@@ -235,10 +245,48 @@ def transform_app_role_assignments(
return result


def transform_service_principals(
service_principals: list[ServicePrincipal],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shyammukund this is what I was talking about at lunch: use list[SpecificType] wherever possible (like here with the Entra SDK because it's available to us. This way we can do things like spn.login_url instead of getattr(spn, 'login_url', None)

@achantavy achantavy changed the title feat: EntraUser sign on to AWS Identity Center (closes #1779) feat: EntraUser sign on to AWS Identity Center (#1779) Aug 7, 2025
Copy link
Collaborator

@jychp jychp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but:

I’m a bit uncomfortable having AWS-specific logic inside an Entra module.

It blurs the module boundaries and could become hard to maintain over time due to cross-dependencies. Especially since we don’t enforce any module execution order.

For example: if Entra runs before AWS, the behavior won’t be what users expect. This could be interpreted as a bug unless the user has deep knowledge of the implementation (i.e., actually read the code to understand the dependency).

I like the idea of:

  1. standalone modules
  2. cross-cutting modules (like analysis or ontology)

IMHO, we should eventually move this logic into a dedicated module (e.g., sso-federation, or another name I’m terrible at naming).

Note: since this is the only case for now, I’m fine merging it but we should open an issue right away to track this and clean it up later.

from typing import Any
from typing import Dict
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<3

@@ -313,14 +377,100 @@ def cleanup_app_role_assignments(
).run(neo4j_session)


@timeit
def cleanup_service_principals(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking: I think all the cleanup logic can be in a single function as they have the same purpose and same parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

neo4j_session, transformed_assignments, update_tag, tenant_id
)
# Attach sign-on relationships
sync_entra_to_aws_identity_center(neo4j_session, update_tag, tenant_id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like that multiple sync_* functions have different behaviors:

  • sync_entra_applications: performs cleanup and orchestrates other syncs
  • sync_entra_apps_roles_spns and sync_entra_to_aws_identity_center: don't perform cleanup

For consistency, we should either:

  • move the cleanup logic into each sub-function
  • or (my preferred option) make the sub-functions private (_sync_*) to highlight the difference in responsibility

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did the first option

Signed-off-by: Alex Chantavy <[email protected]>
Signed-off-by: Alex Chantavy <[email protected]>
Signed-off-by: Alex Chantavy <[email protected]>
Signed-off-by: Alex Chantavy <[email protected]>
@achantavy
Copy link
Contributor Author

I've got this working on my local setup, going to test it e2e soon and then merge when that works

Signed-off-by: Alex Chantavy <[email protected]>
@achantavy
Copy link
Contributor Author

Looks good, going to merge this in.

It's also possible to link to additional federated apps via the entra service principal's login url. The code can be extended there through the federation folder

@achantavy
Copy link
Contributor Author

I’m a bit uncomfortable having AWS-specific logic inside an Entra module.

Created a federation/ folder to help keep these cross-cuts more organized

Signed-off-by: Alex Chantavy <[email protected]>
@achantavy achantavy enabled auto-merge (squash) September 14, 2025 21:50
@achantavy achantavy merged commit dd7fef9 into master Sep 14, 2025
5 of 8 checks passed
@achantavy achantavy deleted the signintoazuretoaws branch September 14, 2025 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sign in with Entra ID to AWS
2 participants