mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(azure): Azure new checks related with App Service (#3432)
Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
055a90df30
commit
ab14efa329
@@ -37,6 +37,14 @@ The following list includes all the AWS checks with configurable variables that
|
||||
## Azure
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the Azure checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `app_ensure_php_version_is_latest` | `php_latest_version` | String |
|
||||
| `app_ensure_python_version_is_latest` | `python_latest_version` | String |
|
||||
| `app_ensure_java_version_is_latest` | `java_latest_version` | String |
|
||||
|
||||
|
||||
## GCP
|
||||
|
||||
@@ -129,6 +137,14 @@ aws:
|
||||
# Azure Configuration
|
||||
azure:
|
||||
|
||||
# Azure App Configuration
|
||||
# azure.app_ensure_php_version_is_latest
|
||||
php_latest_version: "8.2"
|
||||
# azure.app_ensure_python_version_is_latest
|
||||
python_latest_version: "3.12"
|
||||
# azure.app_ensure_java_version_is_latest
|
||||
java_latest_version: "17"
|
||||
|
||||
# GCP Configuration
|
||||
gcp:
|
||||
|
||||
|
||||
18
poetry.lock
generated
18
poetry.lock
generated
@@ -549,6 +549,22 @@ azure-common = ">=1.1,<2.0"
|
||||
azure-mgmt-core = ">=1.3.2,<2.0.0"
|
||||
msrest = ">=0.7.1"
|
||||
|
||||
[[package]]
|
||||
name = "azure-mgmt-web"
|
||||
version = "7.2.0"
|
||||
description = "Microsoft Azure Web Apps Management Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "azure-mgmt-web-7.2.0.tar.gz", hash = "sha256:efcfe6f7f520ed0abcfe86517e1c8cf02a712f737a3db0db7cb46c6d647981ed"},
|
||||
{file = "azure_mgmt_web-7.2.0-py3-none-any.whl", hash = "sha256:28e88602ad9d6d03ed3ba89f966f478b6148e28d292d165e5f371c92c59621df"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
azure-common = ">=1.1,<2.0"
|
||||
azure-mgmt-core = ">=1.3.2,<2.0.0"
|
||||
isodate = ">=0.6.1,<1.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "azure-storage-blob"
|
||||
version = "12.19.0"
|
||||
@@ -4377,4 +4393,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9,<3.13"
|
||||
content-hash = "e25fa1004f59cdb59302a8ce727499fd432c24bb1462dbc7a10ab62035f9445f"
|
||||
content-hash = "ab8c8f47bee7e9efdfcb3c736ccd97ea74cd8c601168541e64e3c2c486b9ae58"
|
||||
|
||||
@@ -90,5 +90,13 @@ aws:
|
||||
# Azure Configuration
|
||||
azure:
|
||||
|
||||
# Azure App Service
|
||||
# azure.app_ensure_php_version_is_latest
|
||||
php_latest_version: "8.2"
|
||||
# azure.app_ensure_python_version_is_latest
|
||||
python_latest_version: "3.12"
|
||||
# azure.app_ensure_java_version_is_latest
|
||||
java_latest_version: "17"
|
||||
|
||||
# GCP Configuration
|
||||
gcp:
|
||||
|
||||
@@ -18,6 +18,8 @@ class AzureService:
|
||||
self.subscriptions = audit_info.identity.subscriptions
|
||||
self.locations = audit_info.locations
|
||||
|
||||
self.audit_config = audit_info.audit_config
|
||||
|
||||
def __set_clients__(self, subscriptions, credentials, service, region_config):
|
||||
clients = {}
|
||||
try:
|
||||
|
||||
0
prowler/providers/azure/services/app/__init__.py
Normal file
0
prowler/providers/azure/services/app/__init__.py
Normal file
4
prowler/providers/azure/services/app/app_client.py
Normal file
4
prowler/providers/azure/services/app/app_client.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from prowler.providers.azure.lib.audit_info.audit_info import azure_audit_info
|
||||
from prowler.providers.azure.services.app.app_service import App
|
||||
|
||||
app_client = App(azure_audit_info)
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_client_certificates_on",
|
||||
"CheckTitle": "Ensure the web app has 'Client Certificates (Incoming client certificates)' set to 'On'",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Microsoft.Web/sites/config",
|
||||
"Description": "Client certificates allow for the app to request a certificate for incoming requests. Only clients that have a valid certificate will be able to reach the app.",
|
||||
"Risk": "The TLS mutual authentication technique in enterprise environments ensures the authenticity of clients to the server. If incoming client certificates are enabled, then only an authenticated client who has valid certificates can access the app.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth?tabs=azurecli",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp update --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> --set clientCertEnabled=true",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_azr_networking_7#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under the Settings section, Click on Configuration, then General settings 5. Set the option Client certificate mode located under Incoming client certificates to Require",
|
||||
"Url": "https://learn.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-identity-management#im-4-authenticate-server-and-services"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Utilizing and maintaining client certificates will require additional work to obtain and manage replacement and key rotation."
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_client_certificates_on(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "PASS"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"Clients are required to present a certificate for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if app.client_cert_mode != "Required":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Clients are not required to present a certificate for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_auth_is_set_up",
|
||||
"CheckTitle": "Ensure App Service Authentication is set up for apps in Azure App Service",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Azure App Service Authentication is a feature that can prevent anonymous HTTP requests from reaching a Web Application or authenticate those with tokens before they reach the app. If an anonymous request is received from a browser, App Service will redirect to a logon page. To handle the logon process, a choice from a set of identity providers can be made, or a custom authentication mechanism can be implemented.",
|
||||
"Risk": "By Enabling App Service Authentication, every incoming HTTP request passes through it before being handled by the application code. It also handles authentication of users with the specified provider (Azure Active Directory, Facebook, Google, Microsoft Account, and Twitter), validation, storing and refreshing of tokens, managing the authenticated sessions and injecting identity information into request headers.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp auth update --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> --enabled true",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/enable-app-service-authentication.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_azr_general_2#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Setting section, click on Authentication 5. If no identity providers are set up, then click Add identity provider 6. Choose other parameters as per your requirements and click on Add",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#website-contributor"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "This is only required for App Services which require authentication. Enabling on site like a marketing or support website will prevent unauthenticated access which would be undesirable. Adding Authentication requirement will increase cost of App Service and require additional security components to facilitate the authentication"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_auth_is_set_up(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "PASS"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"Authentication is set up for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if not app.auth_enabled:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Authentication is not set up for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_http_is_redirected_to_https",
|
||||
"CheckTitle": "Ensure Web App Redirects All HTTP traffic to HTTPS in Azure App Service",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Microsoft.Web/sites/config",
|
||||
"Description": "Azure Web Apps allows sites to run under both HTTP and HTTPS by default. Web apps can be accessed by anyone using non-secure HTTP links by default. Non-secure HTTP requests can be restricted and all HTTP requests redirected to the secure HTTPS port. It is recommended to enforce HTTPS-only traffic.",
|
||||
"Risk": "Enabling HTTPS-only traffic will redirect all non-secure HTTP requests to HTTPS ports. HTTPS uses the TLS/SSL protocol to provide a secure connection which is both encrypted and authenticated. It is therefore important to support HTTPS for the security benefits.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-bindings#enforce-https",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp update --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> --set httpsOnly=true",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/enable-https-only-traffic.html#",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_azr_networking_5#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Setting section, Click on Configuration 5. In the General Settings section, set the HTTPS Only to On 6. Click Save",
|
||||
"Url": "https://learn.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-data-protection#dp-3-encrypt-sensitive-data-in-transit"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "When it is enabled, every incoming HTTP request is redirected to the HTTPS port. This means an extra level of security will be added to the HTTP requests made to the app."
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_http_is_redirected_to_https(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "PASS"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"HTTP is redirected to HTTPS for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if not app.https_only:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"HTTP is not redirected to HTTPS for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_java_version_is_latest",
|
||||
"CheckTitle": "Ensure that 'Java version' is the latest, if used to run the Web App",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Periodically, newer versions are released for Java software either due to security flaws or to include additional functionality. Using the latest Java version for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the newer version.",
|
||||
"Risk": "Newer versions may contain security enhancements and additional functionality. Using the latest software version is recommended in order to take advantage of enhancements and new capabilities. With each software installation, organizations need to determine if a given update meets their requirements. They must also verify the compatibility and support provided for any additional software against the update revision that is selected.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal#general-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/latest-version-of-java.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/ensure-that-java-version-is-the-latest-if-used-to-run-the-web-app#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Settings section, click on Configuration 5. Click on the General settings pane and ensure that for a Stack of Java the Major Version and Minor Version reflect the latest stable and supported release, and that the Java web server version is set to the auto-update option. NOTE: No action is required if Java version is set to Off, as Java is not used by your web app.",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/app-service/configure-language-java?pivots=platform-linux#choosing-a-java-runtime-version"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "If your app is written using version-dependent features or libraries, they may not be available on the latest version. If you wish to upgrade, research the impact thoroughly. Upgrading may have unforeseen consequences that could result in downtime."
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_java_version_is_latest(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
linux_framework = getattr(app.configurations, "linux_fx_version", "")
|
||||
windows_framework_version = getattr(
|
||||
app.configurations, "java_version", None
|
||||
)
|
||||
|
||||
if "java" in linux_framework.lower() or windows_framework_version:
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
java_latest_version = app_client.audit_config.get(
|
||||
"java_latest_version", "17"
|
||||
)
|
||||
report.status_extended = f"Java version is set to '{f'java{windows_framework_version}' if windows_framework_version else linux_framework}', but should be set to 'java {java_latest_version}' for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if (
|
||||
f"java{java_latest_version}" in linux_framework
|
||||
or java_latest_version == windows_framework_version
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Java version is set to 'java {java_latest_version}' for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_php_version_is_latest",
|
||||
"CheckTitle": "Ensure That 'PHP version' is the Latest, If Used to Run the Web App",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Periodically newer versions are released for PHP software either due to security flaws or to include additional functionality. Using the latest PHP version for web apps is recommended in order to take advantage of security fixes, if any, and/or additional functionalities of the newer version.",
|
||||
"Risk": "Newer versions may contain security enhancements and additional functionality. Using the latest software version is recommended in order to take advantage of enhancements and new capabilities. With each software installation, organizations need to determine if a given update meets their requirements. They must also verify the compatibility and support provided for any additional software against the update revision that is selected.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal#general-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp config set --resource-group <resource group name> --name <app name> [--linux-fx-version <php runtime version>][--php-version <php version>]",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/latest-version-of-php.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/ensure-that-php-version-is-the-latest-if-used-to-run-the-web-app#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. From Azure Home open the Portal Menu in the top left 2. Go to App Services 3. Click on each App 4. Under Settings section, click on Configuration 5. Click on the General settings pane, ensure that for a Stack of PHP the Major Version and Minor Version reflect the latest stable and supported release. NOTE: No action is required If PHP version is set to Off or is set with an empty value as PHP is not used by your web app",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/app-service/configure-language-php?pivots=platform-linux#set-php-version"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "If your app is written using version-dependent features or libraries, they may not be available on the latest version. If you wish to upgrade, research the impact thoroughly. Upgrading may have unforeseen consequences that could result in downtime"
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_php_version_is_latest(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
framework = getattr(app.configurations, "linux_fx_version", "")
|
||||
|
||||
if "php" in framework.lower() or getattr(
|
||||
app.configurations, "php_version", ""
|
||||
):
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
|
||||
php_latest_version = app_client.audit_config.get(
|
||||
"php_latest_version", "8.2"
|
||||
)
|
||||
|
||||
report.status_extended = f"PHP version is set to '{framework}', the latest version that you could use is the '{php_latest_version}' version, for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if (
|
||||
php_latest_version in framework
|
||||
or getattr(app.configurations, "php_version", None)
|
||||
== php_latest_version
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"PHP version is set to '{php_latest_version}' for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_python_version_is_latest",
|
||||
"CheckTitle": "Ensure that 'Python version' is the Latest Stable Version, if Used to Run the Web App",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Periodically, newer versions are released for Python software either due to security flaws or to include additional functionality. Using the latest full Python version for web apps is recommended in order to take advantage of security fixes, if any, and/or additional functionalities of the newer version.",
|
||||
"Risk": "Newer versions may contain security enhancements and additional functionality. Using the latest software version is recommended in order to take advantage of enhancements and new capabilities. With each software installation, organizations need to determine if a given update meets their requirements. They must also verify the compatibility and support provided for any additional software against the update revision that is selected. Using the latest full version will keep your stack secure to vulnerabilities and exploits.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal#general-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp config set --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> [--linux-fx-version 'PYTHON|3.12']",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/latest-version-of-python.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/ensure-that-python-version-is-the-latest-if-used-to-run-the-web-app"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "From Azure Portal 1. From Azure Home open the Portal Menu in the top left 2. Go to App Services 3. Click on each App 4. Under Settings section, click on Configuration 5. Click on the General settings pane and ensure that the Major Version and the Minor Version is set to the latest stable version available (Python 3.11, at the time of writing) NOTE: No action is required if Python version is set to Off, as Python is not used by your web app.",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/app-service/configure-language-python#configure-python-version"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "If your app is written using version-dependent features or libraries, they may not be available on the latest version. If you wish to upgrade, research the impact thoroughly. Upgrading may have unforeseen consequences that could result in downtime."
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_python_version_is_latest(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
framework = getattr(app.configurations, "linux_fx_version", "")
|
||||
|
||||
if "python" in framework.lower() or getattr(
|
||||
app.configurations, "python_version", ""
|
||||
):
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
python_latest_version = app_client.audit_config.get(
|
||||
"python_latest_version", "3.12"
|
||||
)
|
||||
report.status_extended = f"Python version is '{framework}', the latest version that you could use is the '{python_latest_version}' version, for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if (
|
||||
python_latest_version in framework
|
||||
or getattr(app.configurations, "python_version", None)
|
||||
== python_latest_version
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Python version is set to '{python_latest_version}' for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ensure_using_http20",
|
||||
"CheckTitle": "Ensure that 'HTTP Version' is the Latest, if Used to Run the Web App",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Periodically, newer versions are released for HTTP either due to security flaws or to include additional functionality. Using the latest HTTP version for web apps to take advantage of security fixes, if any, and/or new functionalities of the newer version.",
|
||||
"Risk": "Newer versions may contain security enhancements and additional functionality. Using the latest version is recommended in order to take advantage of enhancements and new capabilities. With each software installation, organizations need to determine if a given update meets their requirements. They must also verify the compatibility and support provided for any additional software against the update revision that is selected. HTTP 2.0 has additional performance improvements on the head-of-line blocking problem of old HTTP version, header compression, and prioritization of requests. HTTP 2.0 no longer supports HTTP 1.1's chunked transfer encoding mechanism, as it provides its own, more efficient, mechanisms for data streaming.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal#general-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp config set --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> --http20-enabled true",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/enable-http-2-for-app-service-web-applications.html",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Setting section, Click on Configuration 5. Set HTTP version to 2.0 under General settings",
|
||||
"Url": "https://azure.microsoft.com/en-us/blog/announcing-http-2-support-in-azure-app-service/"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "https://learn.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-posture-vulnerability-management#pv-7-rapidly-and-automatically-remediate-software-vulnerabilities"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ensure_using_http20(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"HTTP/2.0 is not enabled for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if app.configurations and getattr(
|
||||
app.configurations, "http20_enabled", False
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"HTTP/2.0 is enabled for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_ftp_deployment_disabled",
|
||||
"CheckTitle": "Ensure FTP deployments are Disabled",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Microsoft.Web/sites/config",
|
||||
"Description": "By default, Azure Functions, Web, and API Services can be deployed over FTP. If FTP is required for an essential deployment workflow, FTPS should be required for FTP login for all App Service Apps and Functions.",
|
||||
"Risk": "Azure FTP deployment endpoints are public. An attacker listening to traffic on a wifi network used by a remote employee or a corporate network could see login traffic in clear-text which would then grant them full control of the code base of the app or service. This finding is more severe if User Credentials for deployment are set at the subscription level rather than using the default Application Credentials which are unique per App.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/deploy-ftp?tabs=portal",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp config set --resource-group <resource group name> --name <app name> --ftps-state [disabled|FtpsOnly]",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/ftp-access-disabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/ensure-ftp-deployments-are-disabled#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Go to the Azure Portal 2. Select App Services 3. Click on an app 4. Select Settings and then Configuration 5. Under General Settings, for the Platform Settings, the FTP state should be set to Disabled or FTPS Only",
|
||||
"Url": ""
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Any deployment workflows that rely on FTP or FTPs rather than the WebDeploy or HTTPs endpoints may be affected."
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_ftp_deployment_disabled(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"FTP is enabled for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if (
|
||||
app.configurations
|
||||
and getattr(app.configurations, "ftps_state", "AllAllowed")
|
||||
!= "AllAllowed"
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"FTP is disabled for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_minimum_tls_version_12",
|
||||
"CheckTitle": "Ensure Web App is using the latest version of TLS encryption",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Microsoft.Web/sites/config",
|
||||
"Description": "The TLS (Transport Layer Security) protocol secures transmission of data over the internet using standard encryption technology. Encryption should be set with the latest version of TLS. App service allows TLS 1.2 by default, which is the recommended TLS level by industry standards such as PCI DSS.",
|
||||
"Risk": "App service currently allows the web app to set TLS versions 1.0, 1.1 and 1.2. It is highly recommended to use the latest TLS 1.2 version for web app secure connections.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-bindings#enforce-tls-versions",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp config set --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME> --min-tls-version 1.2",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/latest-version-of-tls-encryption-in-use.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_azr_networking_6#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Setting section, Click on TLS/SSL settings 5. Under the Bindings pane, ensure that Minimum TLS Version set to 1.2 under Protocol Settings",
|
||||
"Url": "https://docs.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-data-protection#dp-3-encrypt-sensitive-data-in-transit"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "By default, TLS Version feature will be set to 1.2 when a new app is created using the command-line tool or Azure Portal console."
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_minimum_tls_version_12(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"Minimum TLS version is not set to 1.2 for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
if (
|
||||
app.configurations
|
||||
and getattr(app.configurations, "min_tls_version", "") == "1.2"
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Minimum TLS version is set to 1.2 for app '{app_name}' in subscription '{subscription_name}'."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "app_register_with_identity",
|
||||
"CheckTitle": "Ensure that Register with Azure Active Directory is enabled on App Service",
|
||||
"CheckType": [],
|
||||
"ServiceName": "app",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Microsoft.Web/sites",
|
||||
"Description": "Managed service identity in App Service provides more security by eliminating secrets from the app, such as credentials in the connection strings. When registering with Azure Active Directory in App Service, the app will connect to other Azure services securely without the need for usernames and passwords.",
|
||||
"Risk": "App Service provides a highly scalable, self-patching web hosting service in Azure. It also provides a managed identity for apps, which is a turn-key solution for securing access to Azure SQL Database and other Azure services.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad?tabs=workforce-tenant",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az webapp identity assign --resource-group <RESOURCE_GROUP_NAME> --name <APP_NAME>",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/AppService/enable-registration-with-microsoft-entra-id.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_azr_iam_1#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Login to Azure Portal using https://portal.azure.com 2. Go to App Services 3. Click on each App 4. Under Setting section, Click on Identity 5. Under the System assigned pane, set Status to On",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/app-service/scenario-secure-app-authentication-app-service"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "By default, Managed service identity via Azure AD is disabled."
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.app.app_client import app_client
|
||||
|
||||
|
||||
class app_register_with_identity(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
apps,
|
||||
) in app_client.apps.items():
|
||||
for app_name, app in apps.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "PASS"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = app_name
|
||||
report.resource_id = app.resource_id
|
||||
report.status_extended = f"App '{app_name}' in subscription '{subscription_name}' has an identity configured."
|
||||
|
||||
if not app.identity:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"App '{app_name}' in subscription '{subscription_name}' does not have an identity configured."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
89
prowler/providers/azure/services/app/app_service.py
Normal file
89
prowler/providers/azure/services/app/app_service.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from azure.mgmt.web import WebSiteManagementClient
|
||||
from azure.mgmt.web.models import ManagedServiceIdentity, SiteConfigResource
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.azure.lib.audit_info.models import Azure_Audit_Info
|
||||
from prowler.providers.azure.lib.service.service import AzureService
|
||||
|
||||
|
||||
########################## App
|
||||
class App(AzureService):
|
||||
def __init__(self, audit_info: Azure_Audit_Info):
|
||||
super().__init__(WebSiteManagementClient, audit_info)
|
||||
self.apps = self.__get_apps__()
|
||||
|
||||
def __get_apps__(self):
|
||||
logger.info("App - Getting apps...")
|
||||
apps = {}
|
||||
|
||||
for subscription_name, client in self.clients.items():
|
||||
try:
|
||||
apps_list = client.web_apps.list()
|
||||
apps.update({subscription_name: {}})
|
||||
|
||||
for app in apps_list:
|
||||
platform_auth = getattr(
|
||||
client.web_apps.get_auth_settings_v2(
|
||||
resource_group_name=app.resource_group, name=app.name
|
||||
),
|
||||
"platform",
|
||||
None,
|
||||
)
|
||||
|
||||
apps[subscription_name].update(
|
||||
{
|
||||
app.name: WebApp(
|
||||
resource_id=app.id,
|
||||
auth_enabled=(
|
||||
getattr(platform_auth, "enabled", False)
|
||||
if platform_auth
|
||||
else False
|
||||
),
|
||||
configurations=client.web_apps.get_configuration(
|
||||
resource_group_name=app.resource_group,
|
||||
name=app.name,
|
||||
),
|
||||
client_cert_mode=self.__get_client_cert_mode__(
|
||||
getattr(app, "client_cert_enabled", False),
|
||||
getattr(app, "client_cert_mode", "Ignore"),
|
||||
),
|
||||
https_only=getattr(app, "https_only", False),
|
||||
identity=getattr(app, "identity", None),
|
||||
)
|
||||
}
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
return apps
|
||||
|
||||
def __get_client_cert_mode__(
|
||||
self, client_cert_enabled: bool, client_cert_mode: str
|
||||
):
|
||||
cert_mode = "Ignore"
|
||||
if not client_cert_enabled and client_cert_mode == "OptionalInteractiveUser":
|
||||
cert_mode = "Ignore"
|
||||
elif client_cert_enabled and client_cert_mode == "OptionalInteractiveUser":
|
||||
cert_mode = "Optional"
|
||||
elif client_cert_enabled and client_cert_mode == "Optional":
|
||||
cert_mode = "Allow"
|
||||
elif client_cert_enabled and client_cert_mode == "Required":
|
||||
cert_mode = "Required"
|
||||
else:
|
||||
cert_mode = "Ignore"
|
||||
|
||||
return cert_mode
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebApp:
|
||||
resource_id: str
|
||||
configurations: SiteConfigResource
|
||||
identity: ManagedServiceIdentity
|
||||
client_cert_mode: str = "Ignore"
|
||||
auth_enabled: bool = False
|
||||
https_only: bool = False
|
||||
@@ -41,6 +41,7 @@ azure-mgmt-security = "6.0.0"
|
||||
azure-mgmt-sql = "3.0.1"
|
||||
azure-mgmt-storage = "21.1.0"
|
||||
azure-mgmt-subscription = "3.1.1"
|
||||
azure-mgmt-web = "7.2.0"
|
||||
azure-storage-blob = "12.19.0"
|
||||
boto3 = "1.26.165"
|
||||
botocore = "1.29.165"
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_client_certificates_on:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on import (
|
||||
app_client_certificates_on,
|
||||
)
|
||||
|
||||
check = app_client_certificates_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscription_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on import (
|
||||
app_client_certificates_on,
|
||||
)
|
||||
|
||||
check = app_client_certificates_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_client_certificates_on(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Required",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on import (
|
||||
app_client_certificates_on,
|
||||
)
|
||||
|
||||
check = app_client_certificates_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Clients are required to present a certificate for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_client_certificates_off(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_client_certificates_on.app_client_certificates_on import (
|
||||
app_client_certificates_on,
|
||||
)
|
||||
|
||||
check = app_client_certificates_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Clients are not required to present a certificate for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,111 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_auth_is_set_up:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up import (
|
||||
app_ensure_auth_is_set_up,
|
||||
)
|
||||
|
||||
check = app_ensure_auth_is_set_up()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscription_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up import (
|
||||
app_ensure_auth_is_set_up,
|
||||
)
|
||||
|
||||
check = app_ensure_auth_is_set_up()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_auth_enabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up import (
|
||||
app_ensure_auth_is_set_up,
|
||||
)
|
||||
|
||||
check = app_ensure_auth_is_set_up()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Authentication is set up for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_auth_disabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=False,
|
||||
configurations=mock.MagicMock(),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_auth_is_set_up.app_ensure_auth_is_set_up import (
|
||||
app_ensure_auth_is_set_up,
|
||||
)
|
||||
|
||||
check = app_ensure_auth_is_set_up()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Authentication is not set up for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,111 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_http_is_redirected_to_https:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https import (
|
||||
app_ensure_http_is_redirected_to_https,
|
||||
)
|
||||
|
||||
check = app_ensure_http_is_redirected_to_https()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https import (
|
||||
app_ensure_http_is_redirected_to_https,
|
||||
)
|
||||
|
||||
check = app_ensure_http_is_redirected_to_https()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_http_to_https(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https import (
|
||||
app_ensure_http_is_redirected_to_https,
|
||||
)
|
||||
|
||||
check = app_ensure_http_is_redirected_to_https()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"HTTP is not redirected to HTTPS for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_http_to_https_enabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=True,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_http_is_redirected_to_https.app_ensure_http_is_redirected_to_https import (
|
||||
app_ensure_http_is_redirected_to_https,
|
||||
)
|
||||
|
||||
check = app_ensure_http_is_redirected_to_https()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"HTTP is redirected to HTTPS for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,259 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_java_version_is_latest:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_configurations_none(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_linux_java_version_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(
|
||||
linux_fx_version="Tomcat|9.0-java17", java_version=None
|
||||
),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"java_latest_version": "17"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Java version is set to 'java 17' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_linux_java_version_not_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(
|
||||
linux_fx_version="Tomcat|9.0-java11", java_version=None
|
||||
),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"java_latest_version": "17"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Java version is set to 'Tomcat|9.0-java11', but should be set to 'java 17' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_windows_java_version_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(
|
||||
linux_fx_version="", java_version="17"
|
||||
),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"java_latest_version": "17"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Java version is set to 'java 17' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_windows_java_version_not_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(
|
||||
linux_fx_version="", java_version="11"
|
||||
),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"java_latest_version": "17"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Java version is set to 'java11', but should be set to 'java 17' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_linux_php_version_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(
|
||||
linux_fx_version="php|8.0", java_version=None
|
||||
),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"java_latest_version": "17"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_java_version_is_latest.app_ensure_java_version_is_latest import (
|
||||
app_ensure_java_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_java_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
@@ -0,0 +1,143 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_php_version_is_latest:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest import (
|
||||
app_ensure_php_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_php_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscription_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest import (
|
||||
app_ensure_php_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_php_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_configurations_none(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest import (
|
||||
app_ensure_php_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_php_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_php_version_not_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(linux_fx_version="php|8.0"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"php_latest_version": "8.2"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest import (
|
||||
app_ensure_php_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_php_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"PHP version is set to 'php|8.0', the latest version that you could use is the '8.2' version, for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_php_version_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(linux_fx_version="php|8.2"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"php_latest_version": "8.2"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_php_version_is_latest.app_ensure_php_version_is_latest import (
|
||||
app_ensure_php_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_php_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"PHP version is set to '8.2' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,143 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_python_version_is_latest:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest import (
|
||||
app_ensure_python_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_python_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest import (
|
||||
app_ensure_python_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_python_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_configurations_none(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest import (
|
||||
app_ensure_python_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_python_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_python_version_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(linux_fx_version="python|3.12"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"python_latest_version": "3.12"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest import (
|
||||
app_ensure_python_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_python_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Python version is set to '3.12' for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_python_version_not_latest(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(linux_fx_version="python|3.10"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
app_client.audit_config = {"python_latest_version": "3.12"}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_python_version_is_latest.app_ensure_python_version_is_latest import (
|
||||
app_ensure_python_version_is_latest,
|
||||
)
|
||||
|
||||
check = app_ensure_python_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Python version is 'python|3.10', the latest version that you could use is the '3.12' version, for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,147 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ensure_using_http20:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20 import (
|
||||
app_ensure_using_http20,
|
||||
)
|
||||
|
||||
check = app_ensure_using_http20()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscription_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20 import (
|
||||
app_ensure_using_http20,
|
||||
)
|
||||
|
||||
check = app_ensure_using_http20()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_configurations_none(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20 import (
|
||||
app_ensure_using_http20,
|
||||
)
|
||||
|
||||
check = app_ensure_using_http20()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"HTTP/2.0 is not enabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_http20_enabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(http20_enabled=True),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20 import (
|
||||
app_ensure_using_http20,
|
||||
)
|
||||
|
||||
check = app_ensure_using_http20()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"HTTP/2.0 is enabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_http20_not_enabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(http20_enabled=False),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ensure_using_http20.app_ensure_using_http20 import (
|
||||
app_ensure_using_http20,
|
||||
)
|
||||
|
||||
check = app_ensure_using_http20()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"HTTP/2.0 is not enabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,147 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_ftp_deployment_disabled:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled import (
|
||||
app_ftp_deployment_disabled,
|
||||
)
|
||||
|
||||
check = app_ftp_deployment_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled import (
|
||||
app_ftp_deployment_disabled,
|
||||
)
|
||||
|
||||
check = app_ftp_deployment_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_configurations_none(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled import (
|
||||
app_ftp_deployment_disabled,
|
||||
)
|
||||
|
||||
check = app_ftp_deployment_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"FTP is enabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_ftp_deployment_disabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(ftps_state="AllAllowed"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled import (
|
||||
app_ftp_deployment_disabled,
|
||||
)
|
||||
|
||||
check = app_ftp_deployment_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"FTP is enabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_ftp_deploy_enabled(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(ftps_state="Disabled"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_ftp_deployment_disabled.app_ftp_deployment_disabled import (
|
||||
app_ftp_deployment_disabled,
|
||||
)
|
||||
|
||||
check = app_ftp_deployment_disabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"FTP is disabled for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,147 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_minimum_tls_version_12:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12 import (
|
||||
app_minimum_tls_version_12,
|
||||
)
|
||||
|
||||
check = app_minimum_tls_version_12()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12 import (
|
||||
app_minimum_tls_version_12,
|
||||
)
|
||||
|
||||
check = app_minimum_tls_version_12()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_none_configurations(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12 import (
|
||||
app_minimum_tls_version_12,
|
||||
)
|
||||
|
||||
check = app_minimum_tls_version_12()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Minimum TLS version is not set to 1.2 for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_min_tls_version_12(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=mock.MagicMock(min_tls_version="1.2"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12 import (
|
||||
app_minimum_tls_version_12,
|
||||
)
|
||||
|
||||
check = app_minimum_tls_version_12()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Minimum TLS version is set to 1.2 for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_min_tls_version_10(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=False,
|
||||
configurations=mock.MagicMock(min_tls_version="1.0"),
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_minimum_tls_version_12.app_minimum_tls_version_12 import (
|
||||
app_minimum_tls_version_12,
|
||||
)
|
||||
|
||||
check = app_minimum_tls_version_12()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Minimum TLS version is not set to 1.2 for app 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}'."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -0,0 +1,111 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import WebApp
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_app_register_with_identity:
|
||||
def test_app_no_subscriptions(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity import (
|
||||
app_register_with_identity,
|
||||
)
|
||||
|
||||
check = app_register_with_identity()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_subscriptions_empty(self):
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity import (
|
||||
app_register_with_identity,
|
||||
)
|
||||
|
||||
check = app_register_with_identity()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_app_none_configurations(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity import (
|
||||
app_register_with_identity,
|
||||
)
|
||||
|
||||
check = app_register_with_identity()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"App 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}' does not have an identity configured."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_app_identity(self):
|
||||
resource_id = f"/subscriptions/{uuid4()}"
|
||||
app_client = mock.MagicMock
|
||||
app_client.apps = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id=resource_id,
|
||||
auth_enabled=True,
|
||||
configurations=None,
|
||||
client_cert_mode="Ignore",
|
||||
https_only=False,
|
||||
identity=mock.MagicMock,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity.app_client",
|
||||
new=app_client,
|
||||
):
|
||||
from prowler.providers.azure.services.app.app_register_with_identity.app_register_with_identity import (
|
||||
app_register_with_identity,
|
||||
)
|
||||
|
||||
check = app_register_with_identity()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"App 'app_id-1' in subscription '{AZURE_SUBSCRIPTION}' has an identity configured."
|
||||
)
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].resource_name == "app_id-1"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
79
tests/providers/azure/services/app/app_service_test.py
Normal file
79
tests/providers/azure/services/app/app_service_test.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from azure.mgmt.web.models import ManagedServiceIdentity, SiteConfigResource
|
||||
|
||||
from prowler.providers.azure.services.app.app_service import App, WebApp
|
||||
from tests.providers.azure.azure_fixtures import (
|
||||
AZURE_SUBSCRIPTION,
|
||||
set_mocked_azure_audit_info,
|
||||
)
|
||||
|
||||
|
||||
def mock_app_get_apps(self):
|
||||
return {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"app_id-1": WebApp(
|
||||
resource_id="/subscriptions/resource_id",
|
||||
configurations=SiteConfigResource(),
|
||||
identity=ManagedServiceIdentity(type="SystemAssigned"),
|
||||
auth_enabled=True,
|
||||
client_cert_mode="Required",
|
||||
https_only=True,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@patch(
|
||||
"prowler.providers.azure.services.app.app_service.App.__get_apps__",
|
||||
new=mock_app_get_apps,
|
||||
)
|
||||
class Test_App_Service:
|
||||
def test__get_client__(self):
|
||||
app_service = App(set_mocked_azure_audit_info())
|
||||
assert (
|
||||
app_service.clients[AZURE_SUBSCRIPTION].__class__.__name__
|
||||
== "WebSiteManagementClient"
|
||||
)
|
||||
|
||||
def test__get_subscriptions__(self):
|
||||
app_service = App(set_mocked_azure_audit_info())
|
||||
assert app_service.subscriptions.__class__.__name__ == "dict"
|
||||
|
||||
def test__get_apps__(self):
|
||||
app_service = App(set_mocked_azure_audit_info())
|
||||
assert len(app_service.apps) == 1
|
||||
assert (
|
||||
app_service.apps[AZURE_SUBSCRIPTION]["app_id-1"].resource_id
|
||||
== "/subscriptions/resource_id"
|
||||
)
|
||||
assert app_service.apps[AZURE_SUBSCRIPTION]["app_id-1"].auth_enabled
|
||||
assert (
|
||||
app_service.apps[AZURE_SUBSCRIPTION]["app_id-1"].client_cert_mode
|
||||
== "Required"
|
||||
)
|
||||
assert app_service.apps[AZURE_SUBSCRIPTION]["app_id-1"].https_only
|
||||
assert (
|
||||
app_service.apps[AZURE_SUBSCRIPTION]["app_id-1"].identity.type
|
||||
== "SystemAssigned"
|
||||
)
|
||||
assert (
|
||||
app_service.apps[AZURE_SUBSCRIPTION][
|
||||
"app_id-1"
|
||||
].configurations.__class__.__name__
|
||||
== "SiteConfigResource"
|
||||
)
|
||||
|
||||
def test__get_client_cert_mode__(self):
|
||||
app_service = App(set_mocked_azure_audit_info())
|
||||
assert (
|
||||
app_service.__get_client_cert_mode__(False, "OptionalInteractiveUser")
|
||||
== "Ignore"
|
||||
)
|
||||
assert (
|
||||
app_service.__get_client_cert_mode__(True, "OptionalInteractiveUser")
|
||||
== "Optional"
|
||||
)
|
||||
assert app_service.__get_client_cert_mode__(True, "Optional") == "Allow"
|
||||
assert app_service.__get_client_cert_mode__(True, "Required") == "Required"
|
||||
assert app_service.__get_client_cert_mode__(True, "Foo") == "Ignore"
|
||||
Reference in New Issue
Block a user