mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
feat(app): split SDK App service calls (#7778)
This commit is contained in:
committed by
GitHub
parent
66acfd8691
commit
f254a4bc0d
@@ -81,6 +81,9 @@ Prowler for Azure needs two types of permission scopes to be set:
|
||||
|
||||
To assign the permissions, follow the instructions in the [Microsoft Entra ID permissions](../tutorials/azure/create-prowler-service-principal.md#assigning-the-proper-permissions) section and the [Azure subscriptions permissions](../tutorials/azure/subscriptions.md#assign-the-appropriate-permissions-to-the-identity-that-is-going-to-be-assumed-by-prowler) section, respectively.
|
||||
|
||||
???+ warning
|
||||
Some permissions in `ProwlerRole` are considered **write** permissions, so if you have a `ReadOnly` lock attached to some resources you may get an error and will not get a finding for that check.
|
||||
|
||||
#### Checks that require ProwlerRole
|
||||
|
||||
The following checks require the `ProwlerRole` permissions to be executed, if you want to run them, make sure you have assigned the role to the identity that is going to be assumed by Prowler:
|
||||
|
||||
@@ -11,19 +11,20 @@ class app_function_access_keys_configured(Check):
|
||||
functions,
|
||||
) in app_client.functions.items():
|
||||
for function in functions.values():
|
||||
report = Check_Report_Azure(metadata=self.metadata(), resource=function)
|
||||
report.subscription = subscription_name
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} does not have function keys configured."
|
||||
)
|
||||
|
||||
if len(function.function_keys) > 0:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} has function keys configured."
|
||||
if function.function_keys is not None:
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=function
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Function {function.name} does not have function keys configured."
|
||||
|
||||
findings.append(report)
|
||||
if len(function.function_keys) > 0:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} has function keys configured."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -14,26 +14,29 @@ class app_function_application_insights_enabled(Check):
|
||||
functions,
|
||||
) in app_client.functions.items():
|
||||
for function in functions.values():
|
||||
report = Check_Report_Azure(metadata=self.metadata(), resource=function)
|
||||
report.subscription = subscription_name
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} is not using Application Insights."
|
||||
)
|
||||
|
||||
if function.enviroment_variables.get(
|
||||
"APPINSIGHTS_INSTRUMENTATIONKEY", ""
|
||||
) in [
|
||||
component.instrumentation_key
|
||||
for component in appinsights_client.components[
|
||||
subscription_name
|
||||
].values()
|
||||
]:
|
||||
report.status = "PASS"
|
||||
if function.enviroment_variables is not None:
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=function
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} is using Application Insights."
|
||||
f"Function {function.name} is not using Application Insights."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
if function.enviroment_variables.get(
|
||||
"APPINSIGHTS_INSTRUMENTATIONKEY", ""
|
||||
) in [
|
||||
component.instrumentation_key
|
||||
for component in appinsights_client.components[
|
||||
subscription_name
|
||||
].values()
|
||||
]:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} is using Application Insights."
|
||||
)
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -11,20 +11,25 @@ class app_function_latest_runtime_version(Check):
|
||||
functions,
|
||||
) in app_client.functions.items():
|
||||
for function in functions.values():
|
||||
report = Check_Report_Azure(metadata=self.metadata(), resource=function)
|
||||
report.subscription = subscription_name
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} is using the latest runtime."
|
||||
)
|
||||
if function.enviroment_variables is not None:
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=function
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Function {function.name} is using the latest runtime."
|
||||
)
|
||||
|
||||
if (
|
||||
function.enviroment_variables.get("FUNCTIONS_EXTENSION_VERSION", "")
|
||||
!= "~4"
|
||||
):
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Function {function.name} is not using the latest runtime. The current runtime is '{function.enviroment_variables.get('FUNCTIONS_EXTENSION_VERSION', '')}' and should be '~4'."
|
||||
if (
|
||||
function.enviroment_variables.get(
|
||||
"FUNCTIONS_EXTENSION_VERSION", ""
|
||||
)
|
||||
!= "~4"
|
||||
):
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Function {function.name} is not using the latest runtime. The current runtime is '{function.enviroment_variables.get('FUNCTIONS_EXTENSION_VERSION', '')}' and should be '~4'."
|
||||
|
||||
findings.append(report)
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from azure.mgmt.web import WebSiteManagementClient
|
||||
|
||||
@@ -124,14 +124,16 @@ class App(AzureService):
|
||||
# Filter function apps
|
||||
if getattr(function, "kind", "").startswith("functionapp"):
|
||||
# List host keys
|
||||
host_keys = client.web_apps.list_host_keys(
|
||||
resource_group_name=function.resource_group,
|
||||
name=function.name,
|
||||
) # Need to add role 'Logic App Contributor' to the service principal to get the host keys or add to the reader role the permission 'Microsoft.Web/sites/host/listkeys'
|
||||
host_keys = self._get_function_host_keys(
|
||||
subscription_name, function.resource_group, function.name
|
||||
)
|
||||
if host_keys is not None:
|
||||
function_keys = getattr(host_keys, "function_keys", {})
|
||||
else:
|
||||
function_keys = None
|
||||
|
||||
function_config = client.web_apps.get_configuration(
|
||||
resource_group_name=function.resource_group,
|
||||
name=function.name,
|
||||
function_config = self._get_function_config(
|
||||
subscription_name, function.resource_group, function.name
|
||||
)
|
||||
|
||||
functions[subscription_name].update(
|
||||
@@ -141,16 +143,9 @@ class App(AzureService):
|
||||
name=function.name,
|
||||
location=function.location,
|
||||
kind=function.kind,
|
||||
function_keys=getattr(
|
||||
host_keys, "function_keys", {}
|
||||
),
|
||||
function_keys=function_keys,
|
||||
enviroment_variables=getattr(
|
||||
client.web_apps.list_application_settings(
|
||||
resource_group_name=function.resource_group,
|
||||
name=function.name,
|
||||
),
|
||||
"properties",
|
||||
{},
|
||||
function_config, "properties", None
|
||||
),
|
||||
identity=getattr(function, "identity", None),
|
||||
public_access=(
|
||||
@@ -167,7 +162,7 @@ class App(AzureService):
|
||||
"",
|
||||
),
|
||||
ftps_state=getattr(
|
||||
function_config, "ftps_state", ""
|
||||
function_config, "ftps_state", None
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -209,6 +204,30 @@ class App(AzureService):
|
||||
)
|
||||
return monitor_diagnostics_settings
|
||||
|
||||
def _get_function_host_keys(self, subscription, resource_group, name):
|
||||
try:
|
||||
return self.clients[subscription].web_apps.list_host_keys(
|
||||
resource_group_name=resource_group,
|
||||
name=name,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Error getting host keys for {name} in {resource_group}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return None
|
||||
|
||||
def _get_function_config(self, subscription, resource_group, name):
|
||||
try:
|
||||
return self.clients[subscription].web_apps.list_application_settings(
|
||||
resource_group_name=resource_group,
|
||||
name=name,
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Error getting configuration for {name} in {resource_group}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ManagedServiceIdentity:
|
||||
@@ -250,9 +269,9 @@ class FunctionApp:
|
||||
name: str
|
||||
location: str
|
||||
kind: str
|
||||
function_keys: Dict[str, str]
|
||||
enviroment_variables: Dict[str, str]
|
||||
function_keys: Optional[Dict[str, str]]
|
||||
enviroment_variables: Optional[Dict[str, str]]
|
||||
identity: ManagedServiceIdentity
|
||||
public_access: bool
|
||||
vnet_subnet_id: str
|
||||
ftps_state: str
|
||||
ftps_state: Optional[str]
|
||||
|
||||
Reference in New Issue
Block a user