feat(linode): add provider with administration compute and networking services#11633
feat(linode): add provider with administration compute and networking services#11633varunmamillapalli wants to merge 30 commits into
Conversation
…tion check description
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Linode as a new Prowler cloud provider with PAT-based authentication, three service modules (account, firewall, instance), eight security checks across two services, mutelist support, integrated CLI/output/HTML reporting, Pydantic models, custom exception hierarchy, comprehensive unit tests, user-facing documentation, and CI integration. ChangesLinode Provider Integration
Sequence Diagram(s)sequenceDiagram
participant CLI as prowler CLI
participant Init as Provider.init_global_provider
participant LinodeProvider
participant LinodeAPI as Linode API
participant Service as Account/Firewall/InstanceService
participant Check as Check.execute()
participant Report as Finding/HTML/Report
CLI->>Init: arguments.provider == "linode"
Init->>LinodeProvider: __init__(token, config, mutelist)
LinodeProvider->>LinodeProvider: setup_session(LINODE_TOKEN)
LinodeProvider->>LinodeAPI: validate token
LinodeProvider->>LinodeProvider: setup_identity()
LinodeProvider->>LinodeAPI: profile() / account()
LinodeAPI-->>LinodeProvider: username/email/account_id
Init-->>CLI: LinodeProvider registered globally
CLI->>Service: Service(get_global_provider())
Service->>LinodeAPI: users() / firewalls() / instances()
LinodeAPI-->>Service: raw resource data
Service-->>CLI: populated User/Firewall/Instance models
CLI->>Check: execute()
Check->>Service: iterate service.users/firewalls/instances
Check-->>CLI: list[CheckReportLinode]
CLI->>Report: Finding.generate_output(check_output, identity)
Report-->>CLI: rendered output with account_uid/credentials/region
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
✅ Conflict Markers Resolved All conflict markers have been successfully resolved in this pull request. |
There was a problem hiding this comment.
Actionable comments posted: 38
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json (1)
18-37:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFill Required Metadata Contract Fields
Remediation.Code.CLIis empty and compliance version metadata is missing. This breaks the required check metadata contract and can degrade downstream compliance/report consumption.As per coding guidelines, in
prowler/**metadata, “Remediation.Code.CLI ... required and non-empty” and “Compliance Version must be non-empty.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json` around lines 18 - 37, In the account_user_2fa_enabled.metadata.json file, fill the empty Remediation.Code.CLI field with appropriate CLI command instructions for enabling two-factor authentication in Linode, similar to how the Other field is populated with step-by-step guidance. Additionally, add the required Compliance Version metadata field (which is currently missing from the metadata contract) with an appropriate version value to ensure the check metadata contract is fully satisfied and downstream compliance reporting functions correctly.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/user-guide/providers/linode/authentication.mdx`:
- Around line 1-6: The Linode authentication documentation is missing the
Version Badge component that indicates when Linode provider support was
introduced. Add a VersionBadge component with the appropriate version number
immediately after the YAML frontmatter closing (--) and before the main content
that begins with "Prowler for Linode uses a Personal Access Token". Place the
VersionBadge on its own line to maintain consistency with documentation
standards.
In `@docs/user-guide/providers/linode/getting-started-linode.mdx`:
- Around line 1-6: The document is missing the Version Badge component that
indicates when Linode provider support was introduced in Prowler. Add the
VersionBadge component immediately after the frontmatter closing (---) and
before the description paragraph that begins with "Prowler for Linode scans...".
The VersionBadge should be placed on its own line and include the appropriate
version attribute indicating when Linode support was introduced.
- Line 18: In the getting-started-linode.mdx file, minimize second-person
pronouns in the sentence that begins with "Once you have your Personal Access
Token, you can run Prowler for Linode...". Restructure this sentence to reduce
explicit use of "you" and "your" by rephrasing it in a more passive or
imperative form, such as changing it to use "Once authenticated with a Personal
Access Token, run Prowler for Linode using either an environment variable or CLI
argument:" to maintain clarity while following documentation style guidelines.
- Line 57: The table entry describing the firewall resource uses inconsistent
capitalization for Linode's official product name. In the table row for the
firewall resource (marked with backtick firewall), change "Cloud firewall" to
"Cloud Firewall" to match Linode's official branding and maintain consistent
capitalization of proper product names throughout the documentation.
In `@prowler/config/linode_mutelist_example.yaml`:
- Line 2: In the comment "### Account == <Linode Account EUUID>", replace the
typo "EUUID" with "UUID" to match standard Linode terminology and ensure the
example configuration file uses correct terminology.
In `@prowler/providers/linode/exceptions/exceptions.py`:
- Around line 27-80: Add type hints and Google-style docstrings to all public
exception constructors in the file. For the LinodeBaseException.__init__ method,
add type hints for parameters code (int), file (optional), original_exception
(optional), and message (optional), plus a return type of None. For each
subclass constructor (LinodeCredentialsError.__init__,
LinodeAuthenticationError.__init__, LinodeSessionError.__init__, and
LinodeIdentityError.__init__), add the same type hints for their parameters and
return type. Additionally, add a method docstring to each __init__ method that
briefly describes what the constructor does, following Google docstring style
format with an Args section if applicable.
In `@prowler/providers/linode/lib/arguments/arguments.py`:
- Line 4: The public method init_parser in the arguments parser class is missing
type hints. Add type annotations to the method signature by specifying the
return type. Since this is a public function (no leading underscore), it
requires type hints per the Python coding guidelines. Add the appropriate return
type annotation after the method parameters, such as -> None if the method
doesn't return a value, or the specific type if it returns an argument parser
instance or other object.
In `@prowler/providers/linode/lib/mutelist/mutelist.py`:
- Around line 9-20: The is_finding_muted method is missing a docstring that
explains its purpose and parameters. Add a docstring to the is_finding_muted
method that describes what it does (determines whether a finding is muted),
documents all parameters (self, finding as CheckReportLinode, and account_id as
str), and explains the return type (bool). The docstring should follow the
project's documentation standards and provide sufficient context for developers
using this method.
In `@prowler/providers/linode/lib/service/service.py`:
- Around line 12-20: The __init__ method in the LinodeProvider service class is
missing a return type hint and a docstring. Add `-> None` as the return type
hint after the method signature closing parenthesis, and add a docstring
immediately after the method definition that describes the initialization of the
service with the provider, client, and other configuration attributes. This
aligns with the coding guidelines requiring type hints for all public functions
and docstrings for all methods.
- Line 19: The ThreadPoolExecutor instance created as self.thread_pool in the
__init__ method needs explicit cleanup to ensure threads are properly shut down.
Add a __del__ method to the service class that calls
self.thread_pool.shutdown(wait=True) to gracefully terminate all worker threads
when the service instance is garbage collected, or alternatively implement
context manager support by adding __enter__ and __exit__ methods that handle the
ThreadPoolExecutor lifecycle properly. This ensures threads are cleaned up
promptly rather than relying on garbage collection.
- Around line 21-41: Add type hints to the __threading_call__ method to comply
with coding guidelines. The call parameter should be typed as a Callable that
accepts an item and returns an optional result, the iterator parameter should be
typed to accept either a list or an iterable of items, and the method's return
type should be specified as returning a list. Ensure the type hints accurately
reflect how the parameters are used within the method (call is invoked with each
item, iterator can be a list or converted to one, and the method returns a list
of results).
In `@prowler/providers/linode/linode_provider.py`:
- Around line 40-48: Add complete type hints and Google-style docstrings to all
public methods in the LinodeProvider class. Specifically, ensure the __init__
method and all other public methods (referenced at lines 76-95 and 187-187) have
return type hints in their signatures and comprehensive docstrings that describe
the purpose, parameters, return values, and any exceptions. Follow Google
documentation style format with proper sections for Args, Returns, and Raises
where applicable.
- Around line 44-45: The LinodeProvider class initialization uses a mutable
default argument `fixer_config: dict = {}` which causes state to be shared
across instances. Change the default value from `{}` to `None` in the parameter
definition at line 44. Then in the method body, add a check to initialize
fixer_config to an empty dictionary if it is None (similar pattern: `if
fixer_config is None: fixer_config = {}`). Apply the same fix to the other
mutable default argument mentioned at line 65.
In `@prowler/providers/linode/models.py`:
- Around line 27-38: The LinodeOutputOptions.__init__ method is missing type
hints for the public parameters arguments and bulk_checks_metadata, and it lacks
a method docstring. Add type annotations to these parameters (you may need to
determine the appropriate types based on the parent class and usage context),
and add a comprehensive Google-style docstring to the __init__ method that
describes the purpose of the method, documents each parameter with its type and
description, and explains any relevant behavior.
In `@prowler/providers/linode/services/account/account_service.py`:
- Around line 23-28: Add type annotations and a Google-style docstring to the
__init__ method in the account service class. The __init__ method should have
the provider parameter properly annotated and a return type annotation of None,
along with a docstring explaining the initialization of the account service.
Additionally, add a return type annotation of None to the _describe_users method
to complete the type hints for both methods.
- Around line 21-25: The `users` list is defined as a class-level attribute in
AccountService, causing all instances to share the same list object which leads
to state accumulation and duplicate findings. Move the `users` list
initialization from the class level to the instance level by setting `self.users
= []` inside the `__init__` method before calling `self._describe_users()`, so
each AccountService instance has its own independent users list that gets
properly reset on re-instantiation.
In
`@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.py`:
- Line 8: The execute() method is missing a Google-style docstring as required
by prowler documentation standards. Add a docstring immediately after the
execute() method definition that follows Google style documentation format,
including a description of what the method does and documentation of the return
type (list[CheckReportLinode]) to comply with the codebase documentation
requirements.
In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.json`:
- Line 20: In the firewall_assigned_to_devices metadata file, you need to
populate two required fields according to the metadata contract. First, replace
the empty string value for the Remediation.Code.CLI field with an appropriate
non-empty CLI command that describes how to remediate the firewall configuration
issue. Second, ensure there is a non-empty Compliance Version field in the
metadata (add it if missing) with an appropriate version value. Both fields must
contain non-empty values to satisfy the check metadata requirements.
In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
properly formatted Google-style docstring to the execute() method that documents
its purpose, return type, and any relevant details about what the method does.
The docstring should follow the Google documentation format and be placed
immediately after the method signature.
- Around line 11-23: The firewall check relies solely on
fw.attached_devices_count which can report a count even when the upstream
fw.devices list is empty due to rule parsing failures. Modify the condition that
checks fw.attached_devices_count to also verify that fw.devices is not empty and
contains actual device data, ensuring the firewall's device assignment status is
based on successfully populated device information rather than just a count that
might be stale from partial data retrieval.
In
`@prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.json`:
- Line 20: The metadata file has two required fields that are missing or empty:
the Remediation.Code.CLI field on line 20 is set to an empty string and the
Compliance Version field is either missing or empty. To fix this, populate the
Remediation.Code.CLI field with actual CLI remediation steps that describe how
to fix the firewall default inbound policy drop issue, and add or update the
Compliance Version field to include a non-empty value. Both fields are required
by the check metadata contract and must contain meaningful content to comply
with coding guidelines.
In
`@prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
docstring immediately after the method signature that describes what the method
does, its return type, and any relevant details about the check it performs.
Follow Google style documentation format with a summary line, detailed
description if needed, and a Returns section documenting the
list[CheckReportLinode] return type.
In
`@prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.json`:
- Line 20: The metadata file contains empty required fields that violate the
check metadata contract. Locate the empty "CLI" field under Remediation.Code and
populate it with an actual remediation command appropriate for the Linode
Firewall default outbound policy drop check. Additionally, identify the
Compliance Version field in the metadata and ensure it contains a non-empty
value. Both fields must be populated according to the coding guidelines for
metadata validation.
In
`@prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.py`:
- Line 8: The execute() method is missing a Google-style docstring which is
required per coding guidelines. Add a Google-style docstring to the execute()
method that documents its purpose, parameters (if any), return type
(list[CheckReportLinode]), and any relevant details about what the method does.
The docstring should be placed immediately after the method signature and follow
the standard Google docstring format with sections for Summary, Returns, and any
other relevant sections.
In
`@prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.json`:
- Line 20: The firewall_inbound_rules_configured.metadata.json file has two
required metadata fields that are missing or empty: the `Remediation.Code.CLI`
field (at line 20) is set to an empty string and must be populated with an
actual CLI remediation command, and a Compliance Version field must be added and
set to a non-empty value. Update both of these fields in the metadata.json file
to satisfy the check metadata contract requirements.
In
`@prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
docstring immediately after the method signature that includes a brief summary
of what the method does, followed by a Returns section that documents the return
type list[CheckReportLinode] and describes what the list contains. Follow
Google's Python style guide format with proper indentation and formatting.
In
`@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json`:
- Line 20: The CLI field in the Remediation.Code section of the
firewall_outbound_rules_configured metadata file is empty, which violates the
coding guideline requiring this field to be non-empty. Fill in the CLI field
with an appropriate CLI command for configuring Linode firewall outbound rules,
or if no such command exists, use the placeholder text "Not available via CLI"
to indicate that remediation cannot be performed through the command line
interface.
In `@prowler/providers/linode/services/firewall/firewall_service.py`:
- Around line 39-44: The __init__ and _describe_firewalls methods in the
firewall_service.py file are missing proper type hints and Google-style
documentation. Add return type hint (-> None) to both the __init__ constructor
and the _describe_firewalls method, and provide a complete Google-style
docstring for __init__ that documents the provider parameter and its purpose.
Enhance the existing _describe_firewalls docstring to follow Google style format
with proper sections for Args, Returns, and any Raises if applicable, ensuring
it clearly describes what the method does and any parameters it accepts.
- Around line 37-41: The `firewalls` attribute is currently defined at class
scope, causing all instances of `FirewallService` to share the same list, which
leads to state leakage and stale/duplicate findings when the service is
recreated. Move the `firewalls: List[Firewall] = []` initialization from the
class level into the `__init__` method so that each instance has its own
independent list, ensuring no state is shared between service instances.
In
`@prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.json`:
- Around line 18-38: The metadata file has two empty required fields that need
to be populated. First, fill in the Remediation.Code.CLI field with the
appropriate CLI commands for enabling a Linode Cloud Firewall (remove the empty
string value and provide actual CLI instructions). Second, add the missing
Compliance Version metadata to the root level of the JSON object with the
appropriate version information according to Prowler's compliance metadata
guidelines. Ensure both fields are non-empty strings that clearly document the
remediation steps and compliance tracking information.
In
`@prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.py`:
- Line 8: The execute() method in the firewall_status_enabled.py file is missing
a Google-style docstring, which is required by the repository's coding
guidelines. Add a Google-style docstring to the execute() method that describes
its purpose, parameters (if any), and return type. The docstring should follow
Google's documentation format with sections like Args, Returns, and Raises as
appropriate for this method.
In
`@prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.json`:
- Line 21: The CLI remediation field under Remediation.Code in the
instance_disk_encryption_enabled.metadata.json file is empty, which violates the
coding guideline requiring non-empty remediation fields. Populate the empty
"CLI" field with either a concrete linode-cli command demonstrating how to
enable disk encryption on a Linode instance (for example, a command with the
--disk_encryption enabled flag), or if disk encryption cannot be enabled on
existing instances post-creation, use a descriptive placeholder string such as
"Not available for existing instances" to clearly communicate this limitation.
In
`@prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.py`:
- Line 8: The execute() method is missing a docstring which violates the coding
guidelines requiring Google-style documentation for all methods. Add a docstring
to the execute() method that describes what the method does, its return type,
and any relevant details about the check being performed. The docstring should
follow Google style format and be placed immediately after the method signature
before the method body.
In
`@tests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.py`:
- Around line 11-12: The code assigns `account_client` to the `mock.MagicMock`
class itself instead of creating an instance of it, which causes the subsequent
assignment to the `users` attribute to mutate the global mock class and pollute
test state. Replace `mock.MagicMock` with `mock.MagicMock()` (add parentheses to
instantiate) on all three occurrences: line 11, line 34, and line 67 so that
each test gets its own isolated mock instance rather than mutating the shared
class.
In
`@tests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.py`:
- Around line 9-10: The firewall_client variable is being assigned the MagicMock
class itself instead of an instance of it (missing parentheses). This causes
subsequent assignments to firewall_client.firewalls to mutate a shared class
attribute across all tests. Fix this by changing mock.MagicMock to
mock.MagicMock() (with parentheses) to create independent instances. Apply this
fix at all three locations where firewall_client is instantiated (lines 9, 32,
and 70).
In `@tests/providers/linode/services/firewall/linode_firewall_service_test.py`:
- Around line 103-110: The test modifies the MagicMock class at the global level
using type(fw).rules = property(...), which causes the property modification to
leak into other tests and affect any subsequent mocks that access the rules
attribute. Instead of modifying the class-level property on the fw instance,
configure the instance-level behavior directly using PropertyMock or side_effect
to make the fw.rules attribute raise the exception only for this specific mock
instance without affecting the MagicMock class globally.
In
`@tests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.py`:
- Line 11: In the test file, locate all three instances where instance_client is
assigned to mock.MagicMock without parentheses. Fix each assignment by changing
instance_client = mock.MagicMock to instance_client = mock.MagicMock() to
properly instantiate the MagicMock object instead of referencing the class
itself. This applies to the assignments on lines 11, 34, and 70, ensuring each
test method creates its own isolated mock instance rather than sharing a
class-level attribute.
In `@tests/providers/linode/services/instance/linode_instance_service_test.py`:
- Around line 8-31: Add type hints to the helper functions `_mock_instance` and
`_build_service` to improve code clarity and maintainability. For
`_mock_instance`, add type hints to each parameter (id as int, label as str,
region as str, status as str, backups_enabled as bool, disk_encryption as str,
watchdog_enabled as bool, tags as list or None) and specify the return type as
MagicMock. For `_build_service`, add type hints to the parameters
(linode_instances_return as list or None, linode_instances_side_effect as
Exception or None) and specify the return type as InstanceService.
---
Outside diff comments:
In
`@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json`:
- Around line 18-37: In the account_user_2fa_enabled.metadata.json file, fill
the empty Remediation.Code.CLI field with appropriate CLI command instructions
for enabling two-factor authentication in Linode, similar to how the Other field
is populated with step-by-step guidance. Additionally, add the required
Compliance Version metadata field (which is currently missing from the metadata
contract) with an appropriate version value to ensure the check metadata
contract is fully satisfied and downstream compliance reporting functions
correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4fb43188-4752-4bdb-a087-621763d08d3b
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock,!**/uv.lock
📒 Files selected for processing (87)
README.mddocs/docs.jsondocs/user-guide/providers/linode/authentication.mdxdocs/user-guide/providers/linode/getting-started-linode.mdxprowler/__main__.pyprowler/compliance/linode/__init__.pyprowler/config/config.pyprowler/config/linode_mutelist_example.yamlprowler/lib/check/check.pyprowler/lib/check/models.pyprowler/lib/cli/parser.pyprowler/lib/outputs/finding.pyprowler/lib/outputs/html/html.pyprowler/lib/outputs/outputs.pyprowler/lib/outputs/summary_table.pyprowler/providers/common/provider.pyprowler/providers/linode/__init__.pyprowler/providers/linode/exceptions/__init__.pyprowler/providers/linode/exceptions/exceptions.pyprowler/providers/linode/lib/__init__.pyprowler/providers/linode/lib/arguments/__init__.pyprowler/providers/linode/lib/arguments/arguments.pyprowler/providers/linode/lib/mutelist/__init__.pyprowler/providers/linode/lib/mutelist/mutelist.pyprowler/providers/linode/lib/service/__init__.pyprowler/providers/linode/lib/service/service.pyprowler/providers/linode/linode_provider.pyprowler/providers/linode/models.pyprowler/providers/linode/services/__init__.pyprowler/providers/linode/services/account/__init__.pyprowler/providers/linode/services/account/account_client.pyprowler/providers/linode/services/account/account_service.pyprowler/providers/linode/services/account/account_user_2fa_enabled/__init__.pyprowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.jsonprowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.pyprowler/providers/linode/services/firewall/__init__.pyprowler/providers/linode/services/firewall/firewall_assigned_to_devices/__init__.pyprowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.jsonprowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.pyprowler/providers/linode/services/firewall/firewall_client.pyprowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/__init__.pyprowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.jsonprowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.pyprowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/__init__.pyprowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.jsonprowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.pyprowler/providers/linode/services/firewall/firewall_inbound_rules_configured/__init__.pyprowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.jsonprowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.pyprowler/providers/linode/services/firewall/firewall_outbound_rules_configured/__init__.pyprowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.jsonprowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.pyprowler/providers/linode/services/firewall/firewall_service.pyprowler/providers/linode/services/firewall/firewall_status_enabled/__init__.pyprowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.jsonprowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.pyprowler/providers/linode/services/instance/__init__.pyprowler/providers/linode/services/instance/instance_backups_enabled/__init__.pyprowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.pyprowler/providers/linode/services/instance/instance_client.pyprowler/providers/linode/services/instance/instance_disk_encryption_enabled/__init__.pyprowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.pyprowler/providers/linode/services/instance/instance_service.pyprowler/providers/linode/services/instance/instance_watchdog_enabled/__init__.pyprowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.pypyproject.tomltests/lib/cli/parser_test.pytests/providers/linode/lib/mutelist/fixtures/linode_mutelist.yamltests/providers/linode/lib/mutelist/linode_mutelist_test.pytests/providers/linode/linode_fixtures.pytests/providers/linode/linode_provider_test.pytests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.pytests/providers/linode/services/account/linode_account_service_test.pytests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.pytests/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop_test.pytests/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop_test.pytests/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured_test.pytests/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured_test.pytests/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled_test.pytests/providers/linode/services/firewall/linode_firewall_service_test.pytests/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled_test.pytests/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled_test.pytests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.pytests/providers/linode/services/instance/linode_instance_service_test.py
|
Hello @varunmamillapalli! Thanks for this! We'll try to review this as soon as possible, in the meantime could you share some screenshots of the provider working? |
Hi @danibarranqueroo, I have added screenshots to the PR description. Please take a look! |
…ion in tests, avoiding shared mutable services
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
prowler/providers/linode/lib/service/service.py (2)
12-12:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd return type hint to
__init__method.As per coding guidelines, type hints are required for all public functions. The
__init__method is missing the-> Nonereturn type hint.📝 Proposed fix
- def __init__(self, service: str, provider: LinodeProvider): + def __init__(self, service: str, provider: LinodeProvider) -> None:🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/lib/service/service.py` at line 12, The `__init__` method in the service class is missing the required return type hint for public functions. Add the `-> None` return type hint to the `__init__` method signature after the closing parenthesis of the parameters and before the colon to indicate that this method returns None, making it compliant with the coding guidelines that require type hints for all public functions.Source: Coding guidelines
28-48:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd type hints and expand docstring for
__threading_call__method.As per coding guidelines, type hints are required for all public functions and docstrings are required for all methods. The
__threading_call__method is missing:
- Type hints for
callanditeratorparameters- Return type hint
- Args and Returns sections in the docstring
📝 Proposed fix
+from typing import Any, Callable, Iterable, List + - def __threading_call__(self, call, iterator): - """Execute a function across multiple items using threading.""" + def __threading_call__( + self, call: Callable[[Any], Any], iterator: Iterable[Any] + ) -> List[Any]: + """Execute a function across multiple items using threading. + + Args: + call: Callable function to execute on each item. + iterator: Iterable of items to process. + + Returns: + List of non-None results from the callable. + """🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/lib/service/service.py` around lines 28 - 48, The __threading_call__ method is missing type hints and complete documentation. Add type hints to the call parameter (which should be a Callable that accepts an item and returns an optional result), the iterator parameter (which should accept an Iterable or List), and the return type (which should be List). Then expand the existing docstring to include an Args section documenting both parameters (call should describe it as a callable function to execute on each item, and iterator should describe it as an iterable or list of items to process) and a Returns section describing that the method returns a list of non-None results from the executed function calls.Source: Coding guidelines
prowler/providers/linode/services/firewall/firewall_service.py (1)
37-42: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winAdd required type hints and Google-style docstring to service methods.
The
__init__method is missing parameter type hints, a return annotation, and a docstring. The_describe_firewallsmethod is missing its return type annotation.As per coding guidelines,
prowler/**/*.pyrequires type hints for all public functions and docstrings for all classes and methods following Google style documentation.♻️ Proposed fix
- def __init__(self, provider): + def __init__(self, provider) -> None: + """Initialize the FirewallService. + + Args: + provider: The Linode provider instance. + """ super().__init__("firewall", provider) self.firewalls: List[Firewall] = [] self._describe_firewalls() - def _describe_firewalls(self): + def _describe_firewalls(self) -> None: """Fetch all Linode Cloud Firewalls with their rules."""🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/services/firewall/firewall_service.py` around lines 37 - 42, The `__init__` method and `_describe_firewalls` method in the Firewall service class are missing type hints and docstrings required by the coding guidelines. Add a type hint for the `provider` parameter in the `__init__` method, add a return annotation of `-> None` to both the `__init__` and `_describe_firewalls` methods, and add Google-style docstrings to both methods describing their purpose and parameters. Ensure the docstrings follow the Google style format with sections for description, args, and returns as appropriate.Source: Coding guidelines
prowler/providers/linode/services/account/account_service.py (1)
21-26: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winAdd required type hints and Google-style docstring to service methods.
The
__init__method is missing parameter type hints, a return annotation, and a docstring. The_describe_usersmethod is missing its return type annotation.As per coding guidelines,
prowler/**/*.pyrequires type hints for all public functions and docstrings for all classes and methods following Google style documentation.♻️ Proposed fix
- def __init__(self, provider): + def __init__(self, provider) -> None: + """Initialize the AccountService. + + Args: + provider: The Linode provider instance. + """ super().__init__("account", provider) self.users: List[User] = [] self._describe_users() - def _describe_users(self): + def _describe_users(self) -> None: """Fetch all Linode account users."""🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/services/account/account_service.py` around lines 21 - 26, The `__init__` method in the account service class is missing parameter type hints, a return type annotation, and a docstring. Add a type hint for the `provider` parameter, add a return type annotation of `-> None` to the method signature, and include a Google-style docstring that describes the initialization of the account service and what the method does. Additionally, add the missing return type annotation `-> None` to the `_describe_users` method to ensure all methods have complete type hints as required by the coding guidelines.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@prowler/CHANGELOG.md`:
- Line 21: The changelog entry for Linode has two issues: first, the verb "Add"
is redundant since the entry is already under the "### 🚀 Added" section header
which indicates the action; second, "Provider" should be lowercase "provider" to
match changelog conventions. Change the entry from "Add support for Linode cloud
Provider" to "Support for Linode cloud provider" to be consistent with other
entries like "Support for Python 3.13" on line 9 and the lowercase "provider"
pattern used in entries like "AWS provider" on line 10.
In `@prowler/providers/linode/linode_provider.py`:
- Around line 65-66: The __init__ method in the LinodeProvider class has an
incorrect "Returns" section in its docstring that claims it returns a
LinodeProvider instance. Remove the entire "Returns" section (including the
"Returns:" label and the "LinodeProvider: The LinodeProvider instance." line)
from the __init__ docstring, as __init__ methods implicitly return None and
should not have a Returns section according to Python conventions.
In `@prowler/providers/linode/services/instance/instance_service.py`:
- Around line 25-30: Add type hints and Google-style docstrings to the
`__init__` and `_describe_instances` methods in the Instance service class. For
the `__init__` method, add a type hint for the `provider` parameter, add a
return annotation of `-> None`, and add a Google-style docstring that describes
the initialization of the service and its parameters. For the
`_describe_instances` method, add a return annotation of `-> None` to indicate
it does not return a value.
---
Duplicate comments:
In `@prowler/providers/linode/lib/service/service.py`:
- Line 12: The `__init__` method in the service class is missing the required
return type hint for public functions. Add the `-> None` return type hint to the
`__init__` method signature after the closing parenthesis of the parameters and
before the colon to indicate that this method returns None, making it compliant
with the coding guidelines that require type hints for all public functions.
- Around line 28-48: The __threading_call__ method is missing type hints and
complete documentation. Add type hints to the call parameter (which should be a
Callable that accepts an item and returns an optional result), the iterator
parameter (which should accept an Iterable or List), and the return type (which
should be List). Then expand the existing docstring to include an Args section
documenting both parameters (call should describe it as a callable function to
execute on each item, and iterator should describe it as an iterable or list of
items to process) and a Returns section describing that the method returns a
list of non-None results from the executed function calls.
In `@prowler/providers/linode/services/account/account_service.py`:
- Around line 21-26: The `__init__` method in the account service class is
missing parameter type hints, a return type annotation, and a docstring. Add a
type hint for the `provider` parameter, add a return type annotation of `->
None` to the method signature, and include a Google-style docstring that
describes the initialization of the account service and what the method does.
Additionally, add the missing return type annotation `-> None` to the
`_describe_users` method to ensure all methods have complete type hints as
required by the coding guidelines.
In `@prowler/providers/linode/services/firewall/firewall_service.py`:
- Around line 37-42: The `__init__` method and `_describe_firewalls` method in
the Firewall service class are missing type hints and docstrings required by the
coding guidelines. Add a type hint for the `provider` parameter in the
`__init__` method, add a return annotation of `-> None` to both the `__init__`
and `_describe_firewalls` methods, and add Google-style docstrings to both
methods describing their purpose and parameters. Ensure the docstrings follow
the Google style format with sections for description, args, and returns as
appropriate.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7b8cf6fc-e435-41e2-b7d9-3507c3a67a76
📒 Files selected for processing (32)
README.mddocs/user-guide/providers/linode/authentication.mdxdocs/user-guide/providers/linode/getting-started-linode.mdxprowler/CHANGELOG.mdprowler/config/linode_mutelist_example.yamlprowler/providers/linode/lib/mutelist/mutelist.pyprowler/providers/linode/lib/service/service.pyprowler/providers/linode/linode_provider.pyprowler/providers/linode/services/account/account_service.pyprowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.pyprowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.pyprowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.pyprowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.pyprowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.pyprowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.pyprowler/providers/linode/services/firewall/firewall_service.pyprowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.pyprowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.pyprowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.pyprowler/providers/linode/services/instance/instance_service.pyprowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.pytests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.pytests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.pytests/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop_test.pytests/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop_test.pytests/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured_test.pytests/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured_test.pytests/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled_test.pytests/providers/linode/services/firewall/linode_firewall_service_test.pytests/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled_test.pytests/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled_test.pytests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.py
…move unnecessary docstring comment
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json (1)
10-10:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPopulate the outbound-rules CLI remediation.
Linode's docs already expose
linode-cli firewalls rules-update, so leavingRemediation.Code.CLIblank here removes a supported remediation path. (techdocs.akamai.com)Also applies to: 20-28
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json` at line 10, The Remediation.Code.CLI field in the firewall_outbound_rules_configured metadata is empty, which prevents users from having a documented CLI remediation path. Populate the Remediation.Code.CLI field with the appropriate linode-cli command for updating firewall outbound rules using the linode-cli firewalls rules-update command that is already documented in Linode's API reference. Ensure this is consistent across all locations mentioned (lines 10-28) where similar remediation fields need to be filled in for this check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/user-guide/providers/linode/authentication.mdx`:
- Line 9: The documentation at the beginning of the authentication section makes
an overly absolute security claim by stating the token is "never exposed in
shell history or process listings." Reword this sentence to make a narrower
guarantee that using an environment variable keeps the token off the command
line itself, without claiming it prevents exposure through other means. Keep the
accurate parts about Prowler reading exclusively from the LINODE_TOKEN
environment variable and having no credential CLI flags, but remove the absolute
language about preventing all exposure methods.
In `@docs/user-guide/providers/linode/getting-started-linode.mdx`:
- Line 26: The documentation in the Linode getting-started guide overstates the
security benefit of using the LINODE_TOKEN environment variable. Revise the
sentence starting at line 26 to accurately reflect that setting the token as an
environment variable prevents it from being exposed in shell history and command
line process listings (since it's not passed as a CLI argument), rather than
claiming it is never exposed in any context. The statement should be more
precise about the actual security protection provided by the environment
variable approach, acknowledging that this method avoids command line exposure
specifically.
In `@tests/providers/linode/linode_metadata_test.py`:
- Around line 8-11: The parametrize decorator uses a glob pattern that could
return an empty list, causing the test to pass vacuously without validating
anything. Extract the glob result from
Path("prowler/providers/linode").glob("services/**/*.metadata.json") into a
shared variable before the parametrize decorator, then add an assert statement
to verify the list is not empty before using it in the parametrize call. This
ensures the test will fail in CI if the metadata file discovery breaks.
---
Duplicate comments:
In
`@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json`:
- Line 10: The Remediation.Code.CLI field in the
firewall_outbound_rules_configured metadata is empty, which prevents users from
having a documented CLI remediation path. Populate the Remediation.Code.CLI
field with the appropriate linode-cli command for updating firewall outbound
rules using the linode-cli firewalls rules-update command that is already
documented in Linode's API reference. Ensure this is consistent across all
locations mentioned (lines 10-28) where similar remediation fields need to be
filled in for this check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1f0558ac-bb57-4656-9ab7-9fd24373d358
📒 Files selected for processing (26)
.github/labeler.yml.github/workflows/sdk-tests.ymlREADME.mddocs/docs.jsondocs/user-guide/providers/linode/authentication.mdxdocs/user-guide/providers/linode/getting-started-linode.mdxprowler/CHANGELOG.mdprowler/lib/outputs/finding.pyprowler/providers/common/provider.pyprowler/providers/linode/exceptions/exceptions.pyprowler/providers/linode/lib/arguments/arguments.pyprowler/providers/linode/lib/mutelist/mutelist.pyprowler/providers/linode/linode_provider.pyprowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.jsonprowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.jsonprowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.jsonprowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.jsonprowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.jsonprowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.jsonprowler/providers/linode/services/firewall/firewall_service.pyprowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.jsonprowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.metadata.jsontests/lib/outputs/finding_test.pytests/providers/linode/linode_metadata_test.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py`:
- Around line 21-29: The issue is that when fw.attached_devices_count is None,
the code uses continue to skip the firewall entirely, which means no finding is
returned for that resource. This violates the requirement that execute() must
return one PASS/FAIL finding per iterated resource. Instead of skipping with
continue, create a FAIL finding for this firewall with a clear status_extended
message that explains the device assignment could not be determined. Use
fw.label and fw.id to identify the resource in the status message, and ensure
the finding is added to the results list so one finding is emitted per firewall
resource.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6b4ae5d5-c3d1-43ff-81df-64860509a13b
📒 Files selected for processing (6)
prowler/providers/linode/services/account/account_service.pyprowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.pyprowler/providers/linode/services/firewall/firewall_service.pytests/providers/linode/services/account/linode_account_service_test.pytests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.pytests/providers/linode/services/firewall/linode_firewall_service_test.py
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11633 +/- ##
==========================================
- Coverage 94.10% 86.81% -7.30%
==========================================
Files 247 1930 +1683
Lines 36421 65165 +28744
==========================================
+ Hits 34274 56572 +22298
- Misses 2147 8593 +6446 Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Context
This PR introduces the Linode provider to Prowler, enabling security assessments for Linode-managed infrastructure as described in #11504.
Description
Adds Linode provider infrastructure with CLI integration (no API/UI) using Linode's official Python SDK. Support is added for 3 Linode product-area services —
administration,compute, andnetworking— with 10 checks across 4 security categories.Authentication is handled exclusively through the
LINODE_TOKENenvironment variable. The token currently needs read-only access to account, firewalls, and Linodes.LINODE_TOKEN.Services
administrationcomputenetworkingList of checks
administration_user_2fa_enabledcompute_instance_backups_enabledcompute_instance_disk_encryption_enabledcompute_instance_watchdog_enablednetworking_firewall_assigned_to_devicesnetworking_firewall_default_inbound_policy_dropDROPnetworking_firewall_default_outbound_policy_dropDROPnetworking_firewall_inbound_rules_configurednetworking_firewall_outbound_rules_configurednetworking_firewall_status_enabledScreenshots of running various scans
All these runs have
LINODE_TOKENset in the environment:prowler linode --verbose📸 View Full Scan Screenshots (4)
prowler linode --services networking --verbose📸 View Networking Service Scan Screenshots (3)
prowler linode --checks compute_instance_watchdog_enabled --verbose📸 View Watchdog Compute Check Scan Screenshot (1)
📸 View Output Folder Screenshot (1)
Steps to review
prowler/providers/linode/prowler/providers/linode/services/administration/,compute/, andnetworking/docs/user-guide/providers/linode/Checklist
Community Checklist
SDK/CLI
License
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.