mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(Azure): Include multiple authentication (#1528)
This commit is contained in:
38
Pipfile.lock
generated
38
Pipfile.lock
generated
@@ -112,19 +112,19 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:bb40a9788dd2234851cdd1110eec0e3f6b3af6b98280924fa44c25199ced5737",
|
||||
"sha256:c39b7e87b27b00dcf452b2fc80252d311e275036f3d48464af34d0123077f985"
|
||||
"sha256:4b4edf893b01c651007d61534c1d248cd2350d311a4e295039bd23fd60bf899a",
|
||||
"sha256:59aa6c7810a815fb52671f834d10ac4cd80b9c7c01a3cbde670cb41330059464"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.17"
|
||||
"version": "==1.26.19"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:4be7ca8c581dbc6e8584876c4347dcc4f4bc6aa6e6e8131901fc11816fc8151b",
|
||||
"sha256:d4bab7d42acdb18effa33fee53d137b8b1bdedc2da196428a2d1e04a123778bc"
|
||||
"sha256:917807ee4ccca34a2f2848eb4fcf878d9e97a44a911a6965ff556d0830c471fd",
|
||||
"sha256:a54561e591f5d8e653657ce04dcad09c10ebca9dbefba73471976e522abf038a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.29.17"
|
||||
"version": "==1.29.19"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
@@ -589,19 +589,19 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:bb40a9788dd2234851cdd1110eec0e3f6b3af6b98280924fa44c25199ced5737",
|
||||
"sha256:c39b7e87b27b00dcf452b2fc80252d311e275036f3d48464af34d0123077f985"
|
||||
"sha256:4b4edf893b01c651007d61534c1d248cd2350d311a4e295039bd23fd60bf899a",
|
||||
"sha256:59aa6c7810a815fb52671f834d10ac4cd80b9c7c01a3cbde670cb41330059464"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.17"
|
||||
"version": "==1.26.19"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:4be7ca8c581dbc6e8584876c4347dcc4f4bc6aa6e6e8131901fc11816fc8151b",
|
||||
"sha256:d4bab7d42acdb18effa33fee53d137b8b1bdedc2da196428a2d1e04a123778bc"
|
||||
"sha256:917807ee4ccca34a2f2848eb4fcf878d9e97a44a911a6965ff556d0830c471fd",
|
||||
"sha256:a54561e591f5d8e653657ce04dcad09c10ebca9dbefba73471976e522abf038a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.29.17"
|
||||
"version": "==1.29.19"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
@@ -905,11 +905,11 @@
|
||||
},
|
||||
"jsonschema": {
|
||||
"hashes": [
|
||||
"sha256:05b2d22c83640cde0b7e0aa329ca7754fbd98ea66ad8ae24aa61328dfe057fa3",
|
||||
"sha256:410ef23dcdbca4eaedc08b850079179883c2ed09378bd1f760d4af4aacfa28d7"
|
||||
"sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d",
|
||||
"sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.17.1"
|
||||
"version": "==4.17.3"
|
||||
},
|
||||
"jsonschema-spec": {
|
||||
"hashes": [
|
||||
@@ -1110,11 +1110,11 @@
|
||||
},
|
||||
"pylint": {
|
||||
"hashes": [
|
||||
"sha256:15060cc22ed6830a4049cf40bc24977744df2e554d38da1b2657591de5bcd052",
|
||||
"sha256:25b13ddcf5af7d112cf96935e21806c1da60e676f952efb650130f2a4483421c"
|
||||
"sha256:1d561d1d3e8be9dd880edc685162fbdaa0409c88b9b7400873c0cf345602e326",
|
||||
"sha256:91e4776dbcb4b4d921a3e4b6fec669551107ba11f29d9199154a01622e460a57"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.15.6"
|
||||
"version": "==2.15.7"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
|
||||
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
|
||||
],
|
||||
"markers": "python_version < '3.11'",
|
||||
"markers": "python_full_version < '3.11.0a7'",
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"tomlkit": {
|
||||
|
||||
@@ -49,13 +49,14 @@ def report(check_findings, output_options, audit_info):
|
||||
# csv_fields = []
|
||||
file_descriptors = {}
|
||||
if output_options.output_modes:
|
||||
# We have to create the required output files
|
||||
file_descriptors = fill_file_descriptors(
|
||||
output_options.output_modes,
|
||||
output_options.output_directory,
|
||||
output_options.output_filename,
|
||||
audit_info,
|
||||
)
|
||||
if isinstance(audit_info, AWS_Audit_Info):
|
||||
# We have to create the required output files
|
||||
file_descriptors = fill_file_descriptors(
|
||||
output_options.output_modes,
|
||||
output_options.output_directory,
|
||||
output_options.output_filename,
|
||||
audit_info,
|
||||
)
|
||||
|
||||
if check_findings:
|
||||
for finding in check_findings:
|
||||
@@ -325,6 +326,7 @@ def generate_csv_fields(format: Any) -> list[str]:
|
||||
|
||||
|
||||
def fill_json(finding_output, audit_info, finding):
|
||||
|
||||
finding_output.AssessmentStartTime = timestamp_iso
|
||||
finding_output.FindingUniqueId = ""
|
||||
finding_output.Profile = audit_info.profile
|
||||
@@ -457,7 +459,7 @@ def send_to_s3_bucket(
|
||||
|
||||
def display_summary_table(
|
||||
findings: list,
|
||||
audit_info: AWS_Audit_Info,
|
||||
audit_info,
|
||||
output_options: Output_From_Options,
|
||||
provider: str,
|
||||
):
|
||||
@@ -466,8 +468,14 @@ def display_summary_table(
|
||||
try:
|
||||
if provider == "aws":
|
||||
entity_type = "Account"
|
||||
audited_entities = audit_info.audited_account
|
||||
elif provider == "azure":
|
||||
entity_type = "Tenant Domain"
|
||||
if audit_info.identity.domain:
|
||||
entity_type = "Tenant Domain"
|
||||
audited_entities = audit_info.identity.domain
|
||||
else:
|
||||
entity_type = "Tenant ID/s"
|
||||
audited_entities = " ".join(audit_info.identity.tenant_ids)
|
||||
|
||||
if findings:
|
||||
current = {
|
||||
@@ -531,12 +539,13 @@ def display_summary_table(
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
print(
|
||||
f"\n{entity_type} {Fore.YELLOW}{audit_info.audited_account}{Style.RESET_ALL} Scan Results (severity columns are for fails only):"
|
||||
f"\n{entity_type} {Fore.YELLOW}{audited_entities}{Style.RESET_ALL} Scan Results (severity columns are for fails only):"
|
||||
)
|
||||
if provider == "azure":
|
||||
print(
|
||||
f"\nSubscriptions scanned: {Fore.YELLOW}{' '.join(audit_info.subscriptions.keys())}{Style.RESET_ALL}"
|
||||
f"\nSubscriptions scanned: {Fore.YELLOW}{' '.join(audit_info.identity.subscriptions.keys())}{Style.RESET_ALL}"
|
||||
)
|
||||
print(tabulate(findings_table, headers="keys", tablefmt="rounded_grid"))
|
||||
print(
|
||||
@@ -552,7 +561,7 @@ def display_summary_table(
|
||||
|
||||
else:
|
||||
print(
|
||||
f"\n {Style.BRIGHT}There are no findings in {entity_type} {Fore.YELLOW}{audit_info.audited_account}{Style.RESET_ALL}\n"
|
||||
f"\n {Style.BRIGHT}There are no findings in {entity_type} {Fore.YELLOW}{audited_entities}{Style.RESET_ALL}\n"
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import sys
|
||||
from os import getenv
|
||||
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
|
||||
from azure.mgmt.subscription import SubscriptionClient
|
||||
from msgraph.core import GraphClient
|
||||
|
||||
@@ -11,82 +11,190 @@ from providers.azure.lib.audit_info.models import Azure_Audit_Info, Azure_Identi
|
||||
|
||||
|
||||
class Azure_Provider:
|
||||
def __init__(self):
|
||||
def __init__(
|
||||
self,
|
||||
az_cli_auth: bool,
|
||||
sp_env_auth: bool,
|
||||
browser_auth: bool,
|
||||
managed_entity_auth: bool,
|
||||
subscription_ids: list,
|
||||
):
|
||||
logger.info("Instantiating Azure Provider ...")
|
||||
self.credentials = DefaultAzureCredential()
|
||||
self.credentials = self.__set_credentials__(
|
||||
az_cli_auth, sp_env_auth, browser_auth, managed_entity_auth
|
||||
)
|
||||
self.identity = self.__set_identity_info__(
|
||||
self.credentials,
|
||||
az_cli_auth,
|
||||
sp_env_auth,
|
||||
browser_auth,
|
||||
managed_entity_auth,
|
||||
subscription_ids,
|
||||
)
|
||||
|
||||
def __set_credentials__(
|
||||
self, az_cli_auth, sp_env_auth, browser_auth, managed_entity_auth
|
||||
):
|
||||
# Browser auth creds cannot be set with DefaultAzureCredentials()
|
||||
if not browser_auth:
|
||||
if sp_env_auth:
|
||||
self.__check_sp_creds_env_vars__()
|
||||
try:
|
||||
# Since the input vars come as True when it is wanted to be used, we need to inverse it since
|
||||
# DefaultAzureCredential sets the auth method excluding the others
|
||||
credentials = DefaultAzureCredential(
|
||||
exclude_environment_credential=not sp_env_auth,
|
||||
exclude_cli_credential=not az_cli_auth,
|
||||
exclude_managed_identity_credential=not managed_entity_auth,
|
||||
# Azure Auth using Visual Studio is not supported
|
||||
exclude_visual_studio_code_credential=True,
|
||||
# Azure Auth using Shared Token Cache is not supported
|
||||
exclude_shared_token_cache_credential=True,
|
||||
# Azure Auth using PowerShell is not supported
|
||||
exclude_powershell_credential=True,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.critical("Failed to retrieve azure credentials")
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
sys.exit()
|
||||
else:
|
||||
credentials = InteractiveBrowserCredential()
|
||||
|
||||
return credentials
|
||||
|
||||
def __check_sp_creds_env_vars__(self):
|
||||
logger.info(
|
||||
"Azure provider: checking service principal environment variables ..."
|
||||
)
|
||||
for env_var in ["AZURE_CLIENT_ID", "AZURE_TENANT_ID", "AZURE_CLIENT_SECRET"]:
|
||||
if not getenv(env_var):
|
||||
logger.critical(
|
||||
f"Azure provider: Missing environment variable {env_var} needed to autenticate against Azure"
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
def __set_identity_info__(
|
||||
self,
|
||||
credentials,
|
||||
az_cli_auth,
|
||||
sp_env_auth,
|
||||
browser_auth,
|
||||
managed_entity_auth,
|
||||
subscription_ids,
|
||||
):
|
||||
identity = Azure_Identity_Info()
|
||||
|
||||
# If credentials comes from service principal or browser, if the required permissions are assigned
|
||||
# the identity can access AAD and retrieve the tenant domain name.
|
||||
# With cli also should be possible but right now it does not work, azure python package issue is coming
|
||||
# At the time of writting this with az cli creds is not working, despite that is included
|
||||
if sp_env_auth or browser_auth or az_cli_auth:
|
||||
# Trying to recover tenant domain info
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to retrieve tenant domain from AAD to populate identity structure ..."
|
||||
)
|
||||
client = GraphClient(credential=credentials)
|
||||
domain_result = client.get("/domains").json()
|
||||
if "value" in domain_result:
|
||||
if "id" in domain_result["value"][0]:
|
||||
identity.domain = domain_result["value"][0]["id"]
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
"Provided identity does not have permissions to access AAD to retrieve tenant domain"
|
||||
)
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
# since that exception is not considered as critical, we keep filling another identity fields
|
||||
if sp_env_auth:
|
||||
# The id of the sp can be retrieved from environment variables
|
||||
identity.identity_id = getenv("AZURE_CLIENT_ID")
|
||||
identity.identity_type = "Service Principal"
|
||||
# Same here, if user can access AAD, some fields are retrieved if not, default value, for az cli
|
||||
# should work but it doesn't, pending issue
|
||||
else:
|
||||
identity.identity_id = "Unknown user id (NO AAD permissions)"
|
||||
identity.identity_type = "User"
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to retrieve user information from AAD to populate identity structure ..."
|
||||
)
|
||||
client = GraphClient(credential=credentials)
|
||||
user_name = client.get("/me").json()["userPrincipalName"]
|
||||
identity.identity_id = user_name
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
"Provided identity does not have permissions to access AAD to retrieve user's metadata"
|
||||
)
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
# Managed identities only can be assigned resource, resource group and subscription scope permissions
|
||||
elif managed_entity_auth:
|
||||
identity.identity_id = "Default Managed Identity ID"
|
||||
identity.identity_type = "Managed Identity"
|
||||
# Pending extracting info from managed identity
|
||||
|
||||
# once we have populated the id, type, and domain fields, time to retrieve the subscriptions and finally the tenants
|
||||
try:
|
||||
logger.info(
|
||||
"Trying to subscriptions and tenant ids to populate identity structure ..."
|
||||
)
|
||||
subscriptions_client = SubscriptionClient(credential=credentials)
|
||||
if not subscription_ids:
|
||||
logger.info("Scanning all the Azure subscriptions...")
|
||||
for subscription in subscriptions_client.subscriptions.list():
|
||||
|
||||
identity.subscriptions.update(
|
||||
{subscription.display_name: subscription.subscription_id}
|
||||
)
|
||||
else:
|
||||
logger.info("Scanning the subscriptions passed as argument ...")
|
||||
for id in subscription_ids:
|
||||
subscription = subscriptions_client.subscriptions.get(
|
||||
subscription_id=id
|
||||
)
|
||||
identity.subscriptions.update({subscription.display_name: id})
|
||||
|
||||
tenants = subscriptions_client.tenants.list()
|
||||
for tenant in tenants:
|
||||
identity.tenant_ids.append(tenant.tenant_id)
|
||||
# This error is critical, since it implies something is wrong with the credentials provided
|
||||
except Exception as error:
|
||||
logger.critical(
|
||||
"Error with credentials provided getting subscriptions and tenants to scan"
|
||||
)
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
return identity
|
||||
|
||||
def get_credentials(self):
|
||||
return self.credentials
|
||||
|
||||
|
||||
def check_credential_env_vars() -> Azure_Identity_Info:
|
||||
for env_var in ["AZURE_CLIENT_ID", "AZURE_TENANT_ID", "AZURE_CLIENT_SECRET"]:
|
||||
if not getenv(env_var):
|
||||
logger.critical(
|
||||
f"Azure provider: Missing environment variable {env_var} needed to autenticate against Azure"
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
azure_identity = Azure_Identity_Info(
|
||||
app_id=getenv("AZURE_CLIENT_ID"), tenant_id=getenv("AZURE_TENANT_ID")
|
||||
)
|
||||
|
||||
return azure_identity
|
||||
def get_identity(self):
|
||||
return self.identity
|
||||
|
||||
|
||||
def validate_credentials(
|
||||
azure_identity: Azure_Identity_Info, client: GraphClient
|
||||
) -> Azure_Identity_Info:
|
||||
|
||||
try:
|
||||
logger.info("Azure provider: validating service principal credentials ...")
|
||||
result = client.get("/servicePrincipals/").json()
|
||||
if "value" in result:
|
||||
for sp in result["value"]:
|
||||
if sp["appId"] == azure_identity.app_id:
|
||||
azure_identity.id = sp["id"]
|
||||
except Exception as error:
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
sys.exit()
|
||||
else:
|
||||
return azure_identity
|
||||
|
||||
|
||||
def azure_provider_set_session(subscription_ids: list) -> Azure_Audit_Info:
|
||||
def azure_provider_set_session(
|
||||
subscription_ids: list,
|
||||
az_cli_auth: bool,
|
||||
sp_env_auth: bool,
|
||||
browser_auth: bool,
|
||||
managed_entity_auth: bool,
|
||||
) -> Azure_Audit_Info:
|
||||
logger.info("Setting Azure session ...")
|
||||
azure_identity = check_credential_env_vars()
|
||||
azure_audit_info.credentials = Azure_Provider().get_credentials()
|
||||
client = GraphClient(credential=azure_audit_info.credentials)
|
||||
azure_audit_info.identity = validate_credentials(azure_identity, client)
|
||||
try:
|
||||
|
||||
domain_result = client.get("/domains").json()
|
||||
if "value" in domain_result:
|
||||
if "id" in domain_result["value"][0]:
|
||||
azure_audit_info.audited_account = domain_result["value"][0]["id"]
|
||||
subscriptions_client = SubscriptionClient(
|
||||
credential=azure_audit_info.credentials
|
||||
)
|
||||
if not subscription_ids:
|
||||
logger.info("Scanning all the Azure subscriptions...")
|
||||
for subscription in subscriptions_client.subscriptions.list():
|
||||
azure_provider = Azure_Provider(
|
||||
az_cli_auth, sp_env_auth, browser_auth, managed_entity_auth, subscription_ids
|
||||
)
|
||||
azure_audit_info.credentials = azure_provider.get_credentials()
|
||||
azure_audit_info.identity = azure_provider.get_identity()
|
||||
|
||||
azure_audit_info.subscriptions.update(
|
||||
{subscription.display_name: subscription.subscription_id}
|
||||
)
|
||||
else:
|
||||
logger.info("Scanning the subscriptions passed as argument ...")
|
||||
for id in subscription_ids:
|
||||
subscription = subscriptions_client.subscriptions.get(
|
||||
subscription_id=id
|
||||
)
|
||||
azure_audit_info.subscriptions.update({subscription.display_name: id})
|
||||
except Exception as error:
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
sys.exit()
|
||||
else:
|
||||
return azure_audit_info
|
||||
return azure_audit_info
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from providers.azure.lib.audit_info.models import Azure_Audit_Info, Azure_Identity_Info
|
||||
|
||||
azure_audit_info = Azure_Audit_Info(
|
||||
credentials=None, identity=Azure_Identity_Info(), subscriptions={}
|
||||
)
|
||||
azure_audit_info = Azure_Audit_Info(credentials=None, identity=Azure_Identity_Info())
|
||||
|
||||
@@ -5,20 +5,19 @@ from pydantic import BaseModel
|
||||
|
||||
|
||||
class Azure_Identity_Info(BaseModel):
|
||||
id: str = None
|
||||
app_id: str = None
|
||||
tenant_id: str = None
|
||||
identity_id: str = None
|
||||
identity_type: str = None
|
||||
tenant_ids: list[str] = []
|
||||
domain: str = None
|
||||
subscriptions: dict = {}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Azure_Audit_Info:
|
||||
credentials: DefaultAzureCredential
|
||||
identity: Azure_Identity_Info
|
||||
subscriptions: dict
|
||||
audited_account: str
|
||||
|
||||
def __init__(self, credentials, identity, subscriptions):
|
||||
def __init__(self, credentials, identity):
|
||||
self.credentials = credentials
|
||||
self.identity = identity
|
||||
self.subscriptions = subscriptions
|
||||
self.audited_account = None
|
||||
self.is_azure = True
|
||||
|
||||
@@ -11,9 +11,9 @@ class Defender:
|
||||
def __init__(self, audit_info):
|
||||
self.service = "defender"
|
||||
self.credentials = audit_info.credentials
|
||||
self.subscriptions = audit_info.subscriptions
|
||||
self.subscriptions = audit_info.identity.subscriptions
|
||||
self.clients = self.__set_clients__(
|
||||
audit_info.subscriptions, audit_info.credentials
|
||||
audit_info.identity.subscriptions, audit_info.credentials
|
||||
)
|
||||
self.pricings = self.__get_pricings__()
|
||||
self.region = "azure"
|
||||
|
||||
@@ -11,9 +11,9 @@ class IAM:
|
||||
def __init__(self, audit_info):
|
||||
self.service = "iam"
|
||||
self.credentials = audit_info.credentials
|
||||
self.subscriptions = audit_info.subscriptions
|
||||
self.subscriptions = audit_info.identity.subscriptions
|
||||
self.clients = self.__set_clients__(
|
||||
audit_info.subscriptions, audit_info.credentials
|
||||
audit_info.identity.subscriptions, audit_info.credentials
|
||||
)
|
||||
self.roles = self.__get_roles__()
|
||||
self.region = "azure"
|
||||
|
||||
@@ -11,9 +11,9 @@ class Storage:
|
||||
def __init__(self, audit_info):
|
||||
self.service = "storage"
|
||||
self.credentials = audit_info.credentials
|
||||
self.subscriptions = audit_info.subscriptions
|
||||
self.subscriptions = audit_info.identity.subscriptions
|
||||
self.clients = self.__set_clients__(
|
||||
audit_info.subscriptions, audit_info.credentials
|
||||
audit_info.identity.subscriptions, audit_info.credentials
|
||||
)
|
||||
self.storage_accounts = self.__get_storage_accounts__()
|
||||
self.region = "azure"
|
||||
|
||||
53
prowler
53
prowler
@@ -233,6 +233,28 @@ if __name__ == "__main__":
|
||||
default=[],
|
||||
help="Azure subscription ids to be scanned by prowler",
|
||||
)
|
||||
az_auth = parser.add_mutually_exclusive_group()
|
||||
az_auth.add_argument(
|
||||
"--az-cli-auth",
|
||||
action="store_true",
|
||||
help="Use Azure cli credentials to log in against azure",
|
||||
)
|
||||
az_auth.add_argument(
|
||||
"--sp-env-auth",
|
||||
action="store_true",
|
||||
help="Use service principal env variables authentication to log in against azure",
|
||||
)
|
||||
az_auth.add_argument(
|
||||
"--browser-auth",
|
||||
action="store_true",
|
||||
help="Use browser authentication to log in against azure ",
|
||||
)
|
||||
az_auth.add_argument(
|
||||
"--managed-identity-auth",
|
||||
action="store_true",
|
||||
help="Use managed identity authentication to log in against azure ",
|
||||
)
|
||||
|
||||
# Parse Arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -251,6 +273,21 @@ if __name__ == "__main__":
|
||||
|
||||
# Azure options
|
||||
subscriptions = args.subscription_ids
|
||||
az_cli_auth = args.az_cli_auth
|
||||
sp_env_auth = args.sp_env_auth
|
||||
browser_auth = args.browser_auth
|
||||
managed_entity_auth = args.managed_identity_auth
|
||||
if provider == "azure":
|
||||
if (
|
||||
not az_cli_auth
|
||||
and not sp_env_auth
|
||||
and not browser_auth
|
||||
and not managed_entity_auth
|
||||
):
|
||||
logger.critical(
|
||||
"If you are using Azure provider you need to set one of the following options: --az-cli-auth, --sp-env-auth, --browser-auth, --managed-identity-auth"
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
# We treat the compliance framework as another output format
|
||||
if compliance_framework:
|
||||
@@ -370,13 +407,21 @@ if __name__ == "__main__":
|
||||
args.organizations_role,
|
||||
)
|
||||
elif provider == "azure":
|
||||
audit_info = azure_provider_set_session(subscriptions)
|
||||
audit_info = azure_provider_set_session(
|
||||
subscriptions, az_cli_auth, sp_env_auth, browser_auth, managed_entity_auth
|
||||
)
|
||||
|
||||
# Check if custom output filename was input, if not, set the default
|
||||
if not output_filename:
|
||||
output_filename = (
|
||||
f"prowler-output-{audit_info.audited_account}-{output_file_timestamp}"
|
||||
)
|
||||
if provider == "aws":
|
||||
output_filename = (
|
||||
f"prowler-output-{audit_info.audited_account}-{output_file_timestamp}"
|
||||
)
|
||||
elif provider == "azure":
|
||||
if audit_info.identity.domain:
|
||||
output_filename = f"prowler-output-{audit_info.identity.domain}-{output_file_timestamp}"
|
||||
else:
|
||||
output_filename = f"prowler-output-{'-'.join(audit_info.identity.tenant_ids)}-{output_file_timestamp}"
|
||||
|
||||
# Parse content from Allowlist file and get it, if necessary, from S3
|
||||
if args.allowlist_file:
|
||||
|
||||
Reference in New Issue
Block a user