mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
feat(sagemaker): add sagemaker_domain_sso_configured check (#11094)
Co-authored-by: Daniel Barranquero <danielbo2001@gmail.com>
This commit is contained in:
@@ -10,6 +10,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- `iam_user_access_not_stale_to_sagemaker` check for AWS provider with configurable `max_unused_sagemaker_access_days` (default 90) [(#11000)](https://github.com/prowler-cloud/prowler/pull/11000)
|
||||
- `cloudtrail_bedrock_logging_enabled` check for AWS provider [(#10858)](https://github.com/prowler-cloud/prowler/pull/10858)
|
||||
- Okta provider with OAuth 2.0 authentication and `signon_global_session_idle_timeout_15min` check [(#11079)](https://github.com/prowler-cloud/prowler/pull/11079)
|
||||
- `sagemaker_domain_sso_configured` check for AWS provider [(#11094)](https://github.com/prowler-cloud/prowler/pull/11094)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "sagemaker_domain_sso_configured",
|
||||
"CheckTitle": "SageMaker domains use SSO authentication instead of IAM mode",
|
||||
"CheckType": [
|
||||
"Software and Configuration Checks/AWS Security Best Practices"
|
||||
],
|
||||
"ServiceName": "sagemaker",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Other",
|
||||
"ResourceGroup": "ai_ml",
|
||||
"Description": "**SageMaker Domain** configured with **IAM Identity Center (SSO) authentication**. The check validates that each SageMaker Domain uses SSO mode (`AuthMode: SSO`) and is associated with an IAM Identity Center instance (`SingleSignOnManagedApplicationInstanceId` or `SingleSignOnApplicationArn` present), ensuring user access is centrally managed through AWS IAM Identity Center.",
|
||||
"Risk": "IAM-mode domains create per-user IAM users or roles managed locally to SageMaker, drifting from the organization's identity provider and weakening lifecycle controls such as offboarding, MFA enforcement, and session policies. SSO-mode domains without an IAM Identity Center association leave authentication in an inconsistent state and bypass centralized access governance.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://docs.aws.amazon.com/sagemaker/latest/dg/onboard-sso-users.html"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws sagemaker describe-domain --domain-id <domain_id> --query '{AuthMode:AuthMode,SingleSignOnManagedApplicationInstanceId:SingleSignOnManagedApplicationInstanceId,SingleSignOnApplicationArn:SingleSignOnApplicationArn}'",
|
||||
"NativeIaC": "```yaml\n# CloudFormation: Create a SageMaker Domain with SSO authentication\nResources:\n SageMakerDomain:\n Type: AWS::SageMaker::Domain\n Properties:\n DomainName: <example_domain_name>\n AuthMode: SSO # Critical: enables IAM Identity Center authentication\n DefaultUserSettings:\n ExecutionRole: <example_role_arn>\n VpcId: <example_vpc_id>\n SubnetIds:\n - <example_subnet_id>\n```",
|
||||
"Other": "SageMaker Domains cannot be switched from IAM to SSO mode after creation. To remediate, create a new Domain with AuthMode set to SSO and migrate user profiles.",
|
||||
"Terraform": "```hcl\n# Terraform: Create a SageMaker Domain with SSO authentication\nresource \"aws_sagemaker_domain\" \"example\" {\n domain_name = \"<example_domain_name>\"\n auth_mode = \"SSO\" # Critical: enables IAM Identity Center authentication\n vpc_id = \"<example_vpc_id>\"\n subnet_ids = [\"<example_subnet_id>\"]\n\n default_user_settings {\n execution_role = \"<example_role_arn>\"\n }\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Configure SageMaker Domains with SSO authentication mode to anchor user access to AWS IAM Identity Center. This enforces centralized identity lifecycle management, MFA policies, and session controls. Domains created with IAM mode must be recreated with SSO mode since the auth mode cannot be changed after creation.",
|
||||
"Url": "https://hub.prowler.com/check/sagemaker_domain_sso_configured"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"identity-access",
|
||||
"gen-ai"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
|
||||
|
||||
|
||||
class sagemaker_domain_sso_configured(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for domain in sagemaker_client.sagemaker_domains:
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=domain)
|
||||
if domain.auth_mode == "SSO":
|
||||
if (
|
||||
domain.single_sign_on_managed_application_instance_id
|
||||
or domain.single_sign_on_application_arn
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"SageMaker domain {domain.name} is configured with SSO authentication and is associated with an IAM Identity Center instance."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"SageMaker domain {domain.name} is configured with SSO authentication but is not associated with an IAM Identity Center instance."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
current_mode = domain.auth_mode if domain.auth_mode else "unknown"
|
||||
report.status_extended = f"SageMaker domain {domain.name} is not configured with SSO authentication, current mode is {current_mode}."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -15,6 +15,7 @@ class SageMaker(AWSService):
|
||||
self.sagemaker_notebook_instances = []
|
||||
self.sagemaker_models = []
|
||||
self.sagemaker_training_jobs = []
|
||||
self.sagemaker_domains = []
|
||||
self.endpoint_configs = {}
|
||||
|
||||
# Retrieve resources concurrently
|
||||
@@ -22,6 +23,7 @@ class SageMaker(AWSService):
|
||||
self.__threading_call__(self._list_models)
|
||||
self.__threading_call__(self._list_training_jobs)
|
||||
self.__threading_call__(self._list_endpoint_configs)
|
||||
self.__threading_call__(self._list_domains)
|
||||
|
||||
# Describe resources concurrently
|
||||
self.__threading_call__(self._describe_model, self.sagemaker_models)
|
||||
@@ -34,6 +36,7 @@ class SageMaker(AWSService):
|
||||
self.__threading_call__(
|
||||
self._describe_endpoint_config, list(self.endpoint_configs.values())
|
||||
)
|
||||
self.__threading_call__(self._describe_domain, self.sagemaker_domains)
|
||||
|
||||
# List tags concurrently for each resource collection
|
||||
# This replaces the previous sequential sequential execution to improve performance
|
||||
@@ -47,6 +50,7 @@ class SageMaker(AWSService):
|
||||
self.__threading_call__(
|
||||
self._list_tags_for_resource, list(self.endpoint_configs.values())
|
||||
)
|
||||
self.__threading_call__(self._list_tags_for_resource, self.sagemaker_domains)
|
||||
|
||||
def _list_notebook_instances(self, regional_client):
|
||||
logger.info("SageMaker - listing notebook instances...")
|
||||
@@ -218,6 +222,46 @@ class SageMaker(AWSService):
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def _list_domains(self, regional_client):
|
||||
logger.info("SageMaker - listing domains...")
|
||||
try:
|
||||
list_domains_paginator = regional_client.get_paginator("list_domains")
|
||||
for page in list_domains_paginator.paginate():
|
||||
for domain in page["Domains"]:
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(domain["DomainArn"], self.audit_resources)
|
||||
):
|
||||
self.sagemaker_domains.append(
|
||||
Domain(
|
||||
domain_id=domain["DomainId"],
|
||||
name=domain["DomainName"],
|
||||
region=regional_client.region,
|
||||
arn=domain["DomainArn"],
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def _describe_domain(self, domain):
|
||||
logger.info("SageMaker - describing domain...")
|
||||
try:
|
||||
regional_client = self.regional_clients[domain.region]
|
||||
describe_domain = regional_client.describe_domain(DomainId=domain.domain_id)
|
||||
if "AuthMode" in describe_domain:
|
||||
domain.auth_mode = describe_domain["AuthMode"]
|
||||
domain.single_sign_on_managed_application_instance_id = describe_domain.get(
|
||||
"SingleSignOnManagedApplicationInstanceId"
|
||||
)
|
||||
domain.single_sign_on_application_arn = describe_domain.get(
|
||||
"SingleSignOnApplicationArn"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{domain.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def _list_endpoint_configs(self, regional_client):
|
||||
logger.info("SageMaker - listing endpoint configs...")
|
||||
try:
|
||||
@@ -303,6 +347,17 @@ class ProductionVariant(BaseModel):
|
||||
initial_instance_count: int
|
||||
|
||||
|
||||
class Domain(BaseModel):
|
||||
domain_id: str
|
||||
name: str
|
||||
region: str
|
||||
arn: str
|
||||
auth_mode: Optional[str] = None
|
||||
single_sign_on_managed_application_instance_id: Optional[str] = None
|
||||
single_sign_on_application_arn: Optional[str] = None
|
||||
tags: Optional[list] = []
|
||||
|
||||
|
||||
class EndpointConfig(BaseModel):
|
||||
name: str
|
||||
region: str
|
||||
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_service import Domain
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_EU_WEST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
test_domain_name = "test-domain"
|
||||
test_domain_id = "d-testdomain123"
|
||||
domain_arn = f"arn:aws:sagemaker:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:domain/{test_domain_id}"
|
||||
test_sso_instance_id = "app-test-instance-id"
|
||||
test_sso_application_arn = (
|
||||
f"arn:aws:sso::{AWS_ACCOUNT_NUMBER}:application/sagemaker/apl-test"
|
||||
)
|
||||
|
||||
|
||||
class Test_sagemaker_domain_sso_configured:
|
||||
def test_no_domains(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = []
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_domain_sso_configured_with_instance_id(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = [
|
||||
Domain(
|
||||
domain_id=test_domain_id,
|
||||
name=test_domain_name,
|
||||
arn=domain_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
auth_mode="SSO",
|
||||
single_sign_on_managed_application_instance_id=test_sso_instance_id,
|
||||
)
|
||||
]
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SageMaker domain {test_domain_name} is configured with SSO authentication and is associated with an IAM Identity Center instance."
|
||||
)
|
||||
assert result[0].resource_id == test_domain_name
|
||||
assert result[0].resource_arn == domain_arn
|
||||
|
||||
def test_domain_sso_configured_with_application_arn(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = [
|
||||
Domain(
|
||||
domain_id=test_domain_id,
|
||||
name=test_domain_name,
|
||||
arn=domain_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
auth_mode="SSO",
|
||||
single_sign_on_application_arn=test_sso_application_arn,
|
||||
)
|
||||
]
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SageMaker domain {test_domain_name} is configured with SSO authentication and is associated with an IAM Identity Center instance."
|
||||
)
|
||||
|
||||
def test_domain_sso_without_identity_center(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = [
|
||||
Domain(
|
||||
domain_id=test_domain_id,
|
||||
name=test_domain_name,
|
||||
arn=domain_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
auth_mode="SSO",
|
||||
)
|
||||
]
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SageMaker domain {test_domain_name} is configured with SSO authentication but is not associated with an IAM Identity Center instance."
|
||||
)
|
||||
assert result[0].resource_id == test_domain_name
|
||||
assert result[0].resource_arn == domain_arn
|
||||
|
||||
def test_domain_iam_mode(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = [
|
||||
Domain(
|
||||
domain_id=test_domain_id,
|
||||
name=test_domain_name,
|
||||
arn=domain_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
auth_mode="IAM",
|
||||
)
|
||||
]
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SageMaker domain {test_domain_name} is not configured with SSO authentication, current mode is IAM."
|
||||
)
|
||||
assert result[0].resource_id == test_domain_name
|
||||
assert result[0].resource_arn == domain_arn
|
||||
|
||||
def test_domain_auth_mode_unknown(self):
|
||||
sagemaker_client = mock.MagicMock
|
||||
sagemaker_client.sagemaker_domains = [
|
||||
Domain(
|
||||
domain_id=test_domain_id,
|
||||
name=test_domain_name,
|
||||
arn=domain_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
)
|
||||
]
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured.sagemaker_client",
|
||||
sagemaker_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.sagemaker.sagemaker_domain_sso_configured.sagemaker_domain_sso_configured import (
|
||||
sagemaker_domain_sso_configured,
|
||||
)
|
||||
|
||||
check = sagemaker_domain_sso_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SageMaker domain {test_domain_name} is not configured with SSO authentication, current mode is unknown."
|
||||
)
|
||||
@@ -26,6 +26,13 @@ kms_key_id = str(uuid4())
|
||||
endpoint_config_name = "endpoint-config-test"
|
||||
endpoint_config_arn = f"arn:aws:sagemaker:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:endpoint-config/{endpoint_config_name}"
|
||||
prod_variant_name = "Variant1"
|
||||
test_domain_name = "test-domain"
|
||||
test_domain_id = "d-testdomain123"
|
||||
test_domain_arn = f"arn:aws:sagemaker:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:domain/{test_domain_id}"
|
||||
test_sso_instance_id = "app-test-instance-id"
|
||||
test_sso_application_arn = (
|
||||
f"arn:aws:sso::{AWS_ACCOUNT_NUMBER}:application/sagemaker/apl-test"
|
||||
)
|
||||
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
@@ -115,6 +122,25 @@ def mock_make_api_call(self, operation_name, kwarg):
|
||||
},
|
||||
]
|
||||
}
|
||||
if operation_name == "ListDomains":
|
||||
return {
|
||||
"Domains": [
|
||||
{
|
||||
"DomainId": test_domain_id,
|
||||
"DomainName": test_domain_name,
|
||||
"DomainArn": test_domain_arn,
|
||||
},
|
||||
],
|
||||
}
|
||||
if operation_name == "DescribeDomain":
|
||||
return {
|
||||
"DomainId": test_domain_id,
|
||||
"DomainName": test_domain_name,
|
||||
"DomainArn": test_domain_arn,
|
||||
"AuthMode": "SSO",
|
||||
"SingleSignOnManagedApplicationInstanceId": test_sso_instance_id,
|
||||
"SingleSignOnApplicationArn": test_sso_application_arn,
|
||||
}
|
||||
|
||||
return make_api_call(self, operation_name, kwarg)
|
||||
|
||||
@@ -249,6 +275,33 @@ class Test_SageMaker_Service:
|
||||
else:
|
||||
assert prod_variant.initial_instance_count == 2
|
||||
|
||||
# Test SageMaker list domains
|
||||
def test_list_domains(self):
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
sagemaker = SageMaker(aws_provider)
|
||||
assert len(sagemaker.sagemaker_domains) == 1
|
||||
assert sagemaker.sagemaker_domains[0].domain_id == test_domain_id
|
||||
assert sagemaker.sagemaker_domains[0].name == test_domain_name
|
||||
assert sagemaker.sagemaker_domains[0].arn == test_domain_arn
|
||||
assert sagemaker.sagemaker_domains[0].region == AWS_REGION_EU_WEST_1
|
||||
|
||||
# Test SageMaker describe domain
|
||||
def test_describe_domain(self):
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
sagemaker = SageMaker(aws_provider)
|
||||
assert len(sagemaker.sagemaker_domains) == 1
|
||||
assert sagemaker.sagemaker_domains[0].auth_mode == "SSO"
|
||||
assert (
|
||||
sagemaker.sagemaker_domains[
|
||||
0
|
||||
].single_sign_on_managed_application_instance_id
|
||||
== test_sso_instance_id
|
||||
)
|
||||
assert (
|
||||
sagemaker.sagemaker_domains[0].single_sign_on_application_arn
|
||||
== test_sso_application_arn
|
||||
)
|
||||
|
||||
# Test SageMaker _list_tags_for_resource
|
||||
def test_list_tags_for_resource_calls_client(self):
|
||||
"""Test that _list_tags_for_resource calls the correct AWS client and updates the resource."""
|
||||
@@ -312,14 +365,17 @@ class Test_SageMaker_Service:
|
||||
patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_service.SageMaker._list_endpoint_configs"
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.aws.services.sagemaker.sagemaker_service.SageMaker._list_domains"
|
||||
),
|
||||
):
|
||||
sagemaker_service = SageMaker(audit_info)
|
||||
|
||||
# Check that __threading_call__ was called for _list_tags_for_resource
|
||||
# (at least 4 calls expected, one for each resource type)
|
||||
# (one for each resource type: models, notebooks, training jobs, endpoint configs, domains)
|
||||
tag_calls = [
|
||||
c
|
||||
for c in mock_threading_call.call_args_list
|
||||
if c[0][0] == sagemaker_service._list_tags_for_resource
|
||||
]
|
||||
assert len(tag_calls) == 4
|
||||
assert len(tag_calls) == 5
|
||||
|
||||
Reference in New Issue
Block a user