8000 feat: ROS2 tools allowlist by maciejmajek · Pull Request #486 · RobotecAI/rai · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: ROS2 tools allowlist #486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 27, 2025
Merged

feat: ROS2 tools allowlist #486

merged 4 commits into from
Mar 27, 2025

Conversation

maciejmajek
Copy link
Member
@maciejmajek maciejmajek commented Mar 27, 2025

Purpose

RAI 1.x had a allowlist feature in StateBasedAgent, allowing the LLM to interact with certain topics only. This PR reintroduces the feature with extension to readable, writable and forbidden names (topics/services/actions)

Proposed Changes

  • ROS2BaseTool with connector and configurable list of readable, writable and forbidden names
  • Extended tests

Issues

Closes #479

Testing

Tests

Summary by CodeRabbit

  • New Features

    • Introduced configurable access controls for ROS2 interactions, allowing for granular read, write, and forbidden permissions.
    • Enhanced error handling now prevents unauthorized operations and displays clear error feedback.
  • Refactor

    • Unified the underlying framework for ROS2 tools, streamlining behavior across actions, topics, and services.
    • Renamed messaging components for improved clarity and consistency.
  • Tests

    • Expanded test coverage to ensure proper handling of access permissions and robust operation under varied conditions.

refactor: rename MessageReceiver to MessageSubscriber
@maciejmajek
Copy link
Member Author

@coderabbitai full review

Copy link
Contributor
coderabbitai bot commented Mar 27, 2025

Walkthrough

The changes introduce a new base class, BaseROS2Tool, which embeds allowlist functionality by managing access control via the additional permission attributes: readable, writable, and forbidden. Multiple ROS2 tool classes (for actions, topics, and services) are refactored to inherit from this new base class and now include error handling that validates permission checks. Additionally, corresponding tests were updated to reflect these changes, including renaming MessageReceiver to MessageSubscriber and adding test cases for allowed versus forbidden actions, services, and topic operations.

Changes

File(s) Change Summary
src/rai_core/rai/tools/ros2/actions.py Enhanced ROS2ActionToolkit with new permission attributes; updated get_tools to pass these parameters; refactored StartROS2ActionTool, CancelROS2ActionTool, and GetROS2ActionFeedbackTool to inherit from BaseROS2Tool with improved error handling.
src/rai_core/rai/tools/ros2/base.py Introduced new file defining BaseROS2Tool that extends BaseTool; includes permission attributes (readable, writable, forbidden), a connector, and methods (is_readable, is_writable) for access control.
src/rai_core/rai/tools/ros2/services.py Modified CallROS2ServiceTool to inherit from BaseROS2Tool; removed connector attribute; added permission check in _run to raise ValueError for non-writable services.
src/rai_core/rai/tools/ros2/topics.py Updated ROS2TopicsToolkit with new permission attributes; refactored several tools (e.g., PublishROS2MessageTool, ReceiveROS2MessageTool, etc.) to inherit from BaseROS2Tool; added error handling and refined topic filtering logic.
tests/communication/ros2/* Renamed MessageReceiver to MessageSubscriber in the module’s import and __all__ declarations.
tests/communication/ros2/helpers.py Renamed class MessageReceiver to MessageSubscriber; updated constructor to receive a msg_type parameter with a default value; adjusted type annotations accordingly.
tests/communication/ros2/test_api.py Updated test cases to replace MessageReceiver with MessageSubscriber while keeping functionality intact.
tests/communication/ros2/test_connectors.py Updated instantiation and import to refer to MessageSubscriber instead of MessageReceiver.
tests/tools/ros2/test_action_tools.py Added tests to validate behavior of StartROS2ActionTool for forbidden and writable actions, ensuring proper error handling and successful initiation.
tests/tools/ros2/test_service_tools.py Added tests for CallROS2ServiceTool that verify error handling for forbidden services and a successful call for writable services.
tests/tools/ros2/test_topic_tools.py Added tests for publishing/receiving messages and for retrieving topic names/types with permission validations; also updated references to MessageSubscriber.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant StartROS2ActionTool
  participant BaseROS2Tool
  participant ActionServer

  User->>StartROS2ActionTool: Request action start with action_name
  StartROS2ActionTool->>BaseROS2Tool: is_writable(action_name)?
  alt Not Writable
    BaseROS2Tool-->>StartROS2ActionTool: False
    StartROS2ActionTool-->>User: Raise ValueError
  else Writable
    BaseROS2Tool-->>StartROS2ActionTool: True
    StartROS2ActionTool->>ActionServer: Start action
    ActionServer-->>StartROS2ActionTool: Action ID/Success Response
    StartROS2ActionTool-->>User: Return success message
  end
Loading
sequenceDiagram
  participant Client
  participant CallROS2ServiceTool
  participant BaseROS2Tool
  participant ServiceServer

  Client->>CallROS2ServiceTool: Invoke service call with service_name
  CallROS2ServiceTool->>BaseROS2Tool: is_writable(service_name)?
  alt Not Writable
    BaseROS2Tool-->>CallROS2ServiceTool: False
    CallROS2ServiceTool-->>Client: Raise ValueError
  else Writable
    BaseROS2Tool-->>CallROS2ServiceTool: True
    CallROS2ServiceTool->>ServiceServer: Call service
    ServiceServer-->>CallROS2ServiceTool: Service Response
    CallROS2ServiceTool-->>Client: Return response
  end
Loading

Assessment against linked issues

Objective Addressed Explanation
Reintroduce allowlist for topics, services, and actions (#479)

Possibly related PRs

Suggested reviewers

  • boczekbartek
  • rachwalk
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabb 8000 itai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/rai_core/rai/tools/ros2/base.py (2)

1-1: Fix incorrect copyright year

The copyright year is set to 2025, but it should be 2024 to match the current year and be consistent with other files in the codebase.

-# Copyright (C) 2025 Robotec.AI
+# Copyright (C) 2024 Robotec.AI

30-35: Improve parameter docstring clarity

The parameter descriptions should be more consistent and generic since they apply to topics, services, and actions.

-    readable : Optional[List[str]]
-        The topics that can be read. If the list is not provided, all topics can be read.
-    writable : Optional[List[str]]
-        The names (topics/actions/services) that can be written. If the list is not provided, all topics can be written.
+    readable : Optional[List[str]]
+        The names (topics/actions/services) that can be read. If the list is not provided, all names can be read.
+    writable : Optional[List[str]]
+        The names (topics/actions/services) that can be written. If the list is not provided, all names can be written.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9330a59 and 28d9a63.

📒 Files selected for processing (11)
  • src/rai_core/rai/tools/ros2/actions.py (6 hunks)
  • src/rai_core/rai/tools/ros2/base.py (1 hunks)
  • src/rai_core/rai/tools/ros2/services.py (2 hunks)
  • src/rai_core/rai/tools/ros2/topics.py (9 hunks)
  • tests/communication/ros2/__init__.py (1 hunks)
  • tests/communication/ros2/helpers.py (2 hunks)
  • tests/communication/ros2/test_api.py (6 hunks)
  • tests/communication/ros2/test_connectors.py (2 hunks)
  • tests/tools/ros2/test_action_tools.py (1 hunks)
  • tests/tools/ros2/test_service_tools.py (1 hunks)
  • tests/tools/ros2/test_topic_tools.py (5 hunks)
🧰 Additional context used
🧬 Code Definitions (7)
tests/communication/ros2/__init__.py (1)
tests/communication/ros2/helpers.py (3)
  • MessageSubscriber (98-108)
  • multi_threaded_spinner (188-202)
  • shutdown_executors_and_threads (205-215)
tests/communication/ros2/test_connectors.py (1)
tests/communication/ros2/helpers.py (1)
  • MessageSubscriber (98-108)
tests/tools/ros2/test_service_tools.py (1)
tests/communication/ros2/helpers.py (4)
  • ros_setup (219-222)
  • ServiceServer (66-76)
  • multi_threaded_spinner (188-202)
  • shutdown_executors_and_threads (205-215)
tests/communication/ros2/test_api.py (1)
tests/communication/ros2/helpers.py (1)
  • MessageSubscriber (98-108)
src/rai_core/rai/tools/ros2/services.py (1)
src/rai_core/rai/tools/ros2/base.py (2)
  • BaseROS2Tool (22-58)
  • is_writable (53-58)
src/rai_core/rai/tools/ros2/actions.py (3)
src/rai_core/rai/communication/ros2/connectors.py (1)
  • ROS2ARIConnector (44-194)
src/rai_core/rai/communication/ros2/messages.py (1)
  • ROS2ARIMessage (39-41)
src/rai_core/rai/tools/ros2/base.py (2)
  • BaseROS2Tool (22-58)
  • is_writable (53-58)
tests/tools/ros2/test_action_tools.py (1)
tests/communication/ros2/helpers.py (3)
  • ros_setup (219-222)
  • multi_threaded_spinner (188-202)
  • shutdown_executors_and_threads (205-215)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-and-test-ros2 (humble)
🔇 Additional comments (52)
tests/communication/ros2/__init__.py (1)

18-18: Good renaming of the helper class

The renaming from MessageReceiver to MessageSubscriber is a clearer and more descriptive name that better reflects the class's purpose in the ROS2 subscription pattern.

Also applies to: 26-26

tests/communication/ros2/test_connectors.py (1)

35-35: Consistent class renaming applied correctly

The import statement and instance creation have been properly updated to use MessageSubscriber instead of MessageReceiver, maintaining consistency with the class renaming in the helpers module.

Also applies to: 49-49

tests/communication/ros2/test_api.py (2)

35-35: Import statement updated correctly

The import statement has been properly updated to use MessageSubscriber instead of MessageReceiver.


50-50: Variable names consistently renamed

All variable instances have been properly renamed from message_receiver to message_subscriber to maintain consistency with the class renaming. The thoroughness in updating all occurrences is commendable.

Also applies to: 130-130, 150-150, 171-171, 192-192

src/rai_core/rai/tools/ros2/services.py (2)

27-27: Good implementation of BaseROS2Tool inheritance

The class now properly inherits from BaseROS2Tool which provides the common functionality for ROS2 tools, including access control for topic/service/action operations. This refactoring aligns with the allowlist feature implementation.

Also applies to: 38-38


46-47: Effective permission validation for services

Good addition of the permission check that ensures a service can only be called if it's on the writable list. This implements the allowlist feature described in the PR objective, helping to restrict LLM interaction to only specified services.

src/rai_core/rai/tools/ros2/base.py (2)

22-45: LGTM: Good implementation of the base class for ROS2 tools

The BaseROS2Tool class provides a solid foundation for implementing the allowlist functionality. The class structure and inheritance from BaseTool are appropriate.


46-58: LGTM: Well-implemented permission check methods

The is_readable and is_writable methods have appropriate logic for checking permissions. The forbidden list takes precedence, followed by readable/writable lists, with a default of allowing all if those lists are None.

tests/tools/ros2/test_service_tools.py (2)

56-67: LGTM: Good test for forbidden service behavior

The test correctly verifies that attempting to call a forbidden service raises a ValueError. The test's structure follows the same pattern as other tests in the file.


70-87: LGTM: Good test for writable service behavior

The test correctly verifies that calling a service that's in the writable list works as expected. The structure follows the same pattern as other tests, including proper setup and teardown of resources.

tests/tools/ros2/test_action_tools.py (2)

56-67: LGTM: Good test for forbidden action behavior

The test correctly verifies that attempting to start an action that is marked as forbidden raises a ValueError. The test follows the established pattern of other tests in the file.


70-87: LGTM: Good test for writable action behavior

The test correctly verifies that starting an action that's in the writable list works as expected. The test includes proper setup of the action server and verification of the response.

tests/communication/ros2/helpers.py (2)

17-17: LGTM: Updated import to include Any type

The import statement was correctly updated to include the Any type needed for the updated MessageSubscriber class.


98-108: LGTM: Good refactoring of MessageReceiver to MessageSubscriber

Renaming the class to MessageSubscriber better reflects its purpose. The addition of the msg_type parameter with a default of String makes the class more flexible while maintaining backward compatibility.

tests/tools/ros2/test_topic_tools.py (7)

42-42: Renaming consistency.

The renaming to MessageSubscriber aligns with the updated naming scheme and is consistent throughout the code.


71-83: Good test coverage for forbidden topic.

This test properly ensures a ValueError is raised when attempting to publish to a forbidden topic, covering the negative path for write operations.


85-103: Validating writable topic logic.

Publishing to a writable topic is validated here, and the test confirms the message is received correctly. This scenario thoroughly checks the positive path for write operations.


139-147: Verifying forbidden topic read logic.

This test covers the scenario where read operations on forbidden topics must raise a ValueError, confirming correct exception handling.


149-167: Ensuring readable topic functionality.

The test exercises reading from an explicitly allowed topic, validating successful reception of image data. This effectively checks the positive path for read operations.


178-186: Confirming forbidden topic exclusion.

Ensures that forbidden topics (like /rosout here) are properly excluded from the response. This prevents unintended visibility to restricted topics.


188-197: Verifying readable topic inclusion.

Checks that the configured readable topic is included in the response, confirming the read-allowlist mechanism works as expected.

src/rai_core/rai/tools/ros2/actions.py (11)

26-26: Additional typing imports.

Importing Annotated and other typing utilities is helpful for consistent type annotations and improved readability.


32-32: Switching to BaseROS2Tool.

Using BaseROS2Tool provides unified permission checks (readable, writable, forbidden). This aligns action-related tools with topic and service tools.


39-58: Introducing access control fields.

Defining readable, writable, and forbidden in the ROS2ActionToolkit enables fine-grained control over action usage. This addition is consistent with the overall allowlist approach.


66-68: Model config allowance.

Allowing arbitrary types in the model config ensures the fields storing ROS2 connectors and locks are permitted without pydantic validation issues.


70-79: Passing access control fields to action tools.

This ensures each tool enforces permission checks against the relevant lists, preserving the single responsibility for permission logic in the tools.


81-84: Extending CancelROS2ActionTool with permission fields.

By including readable, writable, and forbidden, the tool can uniformly enforce action-based permissions, even in cancellation flows.


87-90: Including permission fields in GetROS2ActionFeedbackTool.

Uniformly enforces read restrictions when retrieving feedback from an action.


122-122: Refactoring to BaseROS2Tool.

Inheriting from BaseROS2Tool centralizes permission checks for the StartROS2ActionTool.


134-135: Write permission check for actions.

Ensuring the action name is writable prevents starting an action on a forbidden or read-only resource.


153-153: Feedback retrieval inherits from BaseROS2Tool.

Creates consistency with the rest of the tools and maintains a uniform approach to permission checks.


196-196: Unifying cancel action tool.

Switching to BaseROS2Tool maintains consistent permission enforcement across all action-related operations.

src/rai_core/rai/tools/ros2/topics.py (20)

23-23: Extended typing imports.

Bringing in Annotated, Literal, etc., improves type safety and clarity in the code.


37-37: Consistent use of BaseROS2Tool.

Transitioning from BaseTool to BaseROS2Tool ensures the built-in permission checks are leveraged for topic interactions.


45-64: Adding allowlist and denylist fields.

readable, writable, and forbidden in ROS2TopicsToolkit align with the approach to control inbound/outbound topics. This design systematically enforces constraints at the toolkit level.


72-77: Publish tool constructor with permission fields.

The constructor now passes readable, writable, and forbidden for robust access control on publish operations.


78-83: Receive tool constructor with permission fields.

Similarly, including the same fields ensures read operations undergo uniform checks.


84-89: Image tool constructor with permission fields.

Ensures GetROS2ImageTool also enforces read restrictions consistently when retrieving images from topics.


90-95: Transform tool constructor with permission fields.

GetROS2TransformTool similarly inherits the base to enforce read access constraints, preventing transforms from forbidden or unreadable frames.


96-101: Topics names/types tool constructor with permission fields.

In GetROS2TopicsNamesAndTypesTool, we can now exclude forbidden topics from queries and categorize the rest as readable, writable, or both.


102-107: Message interface tool constructor with permission fields.

Allows read/writable checks when retrieving message interfaces, maintaining parity with other tools.


117-117: PublishROS2MessageTool extends BaseROS2Tool.

This refactor standardizes permission handling for publishing to a ROS2 topic.


123-124: Ensuring topic is writable before publish.

Raises ValueError otherwise, protecting from unintended writes to restricted topics.


137-137: ReceiveROS2MessageTool inherits from BaseROS2Tool.

This alignment guarantees read checks are consistently applied for message reception.


144-145: Verifying readability before receiving.

Blocking access to disallowed topics with a clear error message fosters transparent permission enforcement.


155-155: GetROS2ImageTool inherits from BaseROS2Tool.

Centralizes code for read checks, matching the approach for other read-based tools.


165-166: Permission check on images.

Raising an error for unreadable topics ensures consistent guardrails when fetching images.


186-186: GetROS2TopicsNamesAndTypesTool extends BaseROS2Tool.

Provides unified read/write/forbid checks for topic introspection.


193-193: Conditional check for access lists.

The logic handles the “no restrictions set” scenario gracefully by including all topics if none of the attributes are defined.


194-218: Detailed filtering of topics.

Categorizing topics into readable-only, writable-only, or both ensures clear visibility of allowed and forbidden resources.


226-226: GetROS2MessageInterfaceTool inherits BaseROS2Tool.

Ensures the tool can leverage the same permission system if future read checks are introduced for message types.


258-258: Aligned with BaseROS2Tool for transforms.

GetROS2TransformTool now follows the same consistent pattern of permission checks as other ROS2 tools.

Copy link
Member
@boczekbartek boczekbartek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maciejmajek Looks good! Left minor comments. Please fix CI ;)

@maciejmajek maciejmajek merged commit 0b2b2e5 into development Mar 27, 2025
5 checks passed
@maciejmajek maciejmajek deleted the feat/allowlist branch March 27, 2025 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reintroduce allowlist for topics, services and actions in RAI 2.0
2 participants
0