-
Notifications
You must be signed in to change notification settings - Fork 3
initial scaffolding for SDK encryption #37
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
Open
Lance-Drane
wants to merge
9
commits into
candidate-0.9.0
Choose a base branch
from
30-add-encryption
base: candidate-0.9.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
94e17fb
30 - initial scaffolding for SDK encryption
Lance-Drane 0e64d7e
Adds cryptography dependency
marshallmcdonnell e3b1eec
Adds encryption module to _internal
marshallmcdonnell 5915bc2
Adds public_key to universal core capability
marshallmcdonnell 990d197
Adds encryption to service w/ testing + fixes
marshallmcdonnell b4c4b43
Added encryption to client + fix to service
marshallmcdonnell 9ff8f5d
Adds tests for client encryption code
marshallmcdonnell f1738f9
Adds 5_hello_world_rsa example + integration test
marshallmcdonnell 6dd6664
Adding candidate branches for ci workflow
marshallmcdonnell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # Hello World with RSA Encryption Example | ||
|
|
||
| This example demonstrates how to use RSA encryption with INTERSECT services. | ||
|
|
||
| ## Overview | ||
|
|
||
| RSA encryption provides end-to-end encryption for messages between clients and services: | ||
| - Clients encrypt requests using the service's public key | ||
| - Services encrypt responses using the client's public key | ||
| - Each party decrypts messages using their own private key | ||
|
|
||
| ## Files | ||
|
|
||
| - `hello_service.py` - Service implementation with RSA encryption enabled | ||
| - `hello_client.py` - Client implementation that sends RSA encrypted messages | ||
| - `hello_service_schema.json` - Service schema defining available operations | ||
|
|
||
| ## Key Features | ||
|
|
||
| 1. **Automatic RSA Key Generation**: | ||
| - Both service and client automatically generate RSA key pairs internally | ||
| - No manual key management required | ||
| - Service automatically handles public key requests from clients | ||
|
|
||
| 2. **Transparent Encryption**: | ||
| - Simply set `encryption_scheme='RSA'` when sending messages | ||
| - INTERSECT SDK handles all encryption/decryption automatically | ||
| - Public key exchange happens automatically in the background | ||
|
|
||
| ## Running the Example | ||
|
|
||
| 1. Start the service: | ||
| ```bash | ||
| python -m examples.5_hello_world_rsa.hello_service | ||
| ``` | ||
|
|
||
| 2. In another terminal, run the client: | ||
| ```bash | ||
| python -m examples.5_hello_world_rsa.hello_client | ||
| ``` | ||
|
|
||
| ## Expected Output | ||
|
|
||
| Client output: | ||
| ``` | ||
| Hello, hello_client! | ||
| ``` | ||
|
|
||
| ## How It Works | ||
|
|
||
| 1. Client starts and generates its RSA key pair | ||
| 2. Client sends encrypted message to service (encryption_scheme='RSA') | ||
| 3. Client first fetches service's public key via `intersect_sdk.get_public_key` | ||
| 4. Client encrypts the request using service's public key | ||
| 5. Service receives encrypted request and decrypts it using its private key | ||
| 6. Service processes the request and generates a response | ||
| 7. Service fetches client's public key (if not cached) | ||
| 8. Service encrypts response using client's public key | ||
| 9. Client receives encrypted response and decrypts it using its private key | ||
| 10. Client prints the decrypted response | ||
|
|
||
| ## Security Notes | ||
|
|
||
| - Each service and client automatically generates its own unique RSA key pair on startup | ||
| - Private keys are managed internally by the SDK and never transmitted | ||
| - Public keys are exchanged automatically via the INTERSECT messaging system | ||
| - RSA encryption uses 2048-bit keys for strong security | ||
| - No manual key management is required - the SDK handles everything automatically |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Init file for hello world RSA encryption example.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| """ | ||
| Hello World Client with RSA Encryption | ||
|
|
||
| This example demonstrates how to use RSA encryption when sending messages to INTERSECT services. | ||
| The client will encrypt requests using the service's public key and decrypt responses using its own private key. | ||
| """ | ||
|
|
||
| import time | ||
|
|
||
| from intersect_sdk import ( | ||
| HierarchyConfig, | ||
| IntersectClient, | ||
| IntersectServiceConfig, | ||
| ) | ||
| from intersect_sdk.shared_callback_definitions import IntersectDirectMessageParams | ||
|
|
||
| """ | ||
| step one: create IntersectServiceConfig | ||
|
|
||
| Note: The client automatically generates an RSA key pair internally. | ||
| You don't need to manually create or manage encryption keys. | ||
| """ | ||
| config = IntersectServiceConfig( | ||
| brokers=[ | ||
| { | ||
| 'username': 'intersect_username', | ||
| 'password': 'intersect_password', | ||
| 'port': 1883, | ||
| 'protocol': 'mqtt5.0', | ||
| } | ||
| ], | ||
| hierarchy=HierarchyConfig( | ||
| organization='hello-organization', | ||
| facility='hello-facility', | ||
| system='hello-system', | ||
| subsystem='hello-subsystem-client', | ||
| service='hello-client', | ||
| ), | ||
| ) | ||
|
|
||
| """ | ||
| step two: set up callback and then instantiate client | ||
| """ | ||
|
|
||
|
|
||
| def user_callback(source: str, operation: str, has_error: bool, payload: dict) -> None: | ||
| if has_error: | ||
| print(f'Error from {source}: {payload}') | ||
| else: | ||
| print(payload) | ||
|
|
||
|
|
||
| intersect_client = IntersectClient( | ||
| config.hierarchy, | ||
| config=config, | ||
| ) | ||
|
|
||
| """ | ||
| step three: start up client with user callback | ||
| """ | ||
| intersect_client.startup(user_callback=user_callback) | ||
|
|
||
| """ | ||
| step four: send message with RSA encryption | ||
| Note the encryption_scheme='RSA' parameter | ||
| """ | ||
| message_params = IntersectDirectMessageParams( | ||
| destination='hello-organization.hello-facility.hello-system.hello-subsystem.hello-service', | ||
| operation='HelloExample.say_hello_to_name', | ||
| payload='hello_client', | ||
| encryption_scheme='RSA', # Enable RSA encryption | ||
| ) | ||
|
|
||
| intersect_client.send_message(message_params) | ||
| time.sleep(3) | ||
|
|
||
| """ | ||
| step five: shut down client | ||
| """ | ||
| intersect_client.shutdown() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| """ | ||
| Hello World Service with RSA Encryption | ||
|
|
||
| This example demonstrates how to use RSA encryption with INTERSECT services. | ||
| The service will encrypt responses to clients using the client's public key. | ||
| """ | ||
|
|
||
| import logging | ||
|
|
||
| from intersect_sdk import ( | ||
| HierarchyConfig, | ||
| IntersectBaseCapabilityImplementation, | ||
| IntersectService, | ||
| IntersectServiceConfig, | ||
| default_intersect_lifecycle_loop, | ||
| intersect_message, | ||
| intersect_status, | ||
| ) | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class HelloServiceCapabilityImplementation(IntersectBaseCapabilityImplementation): | ||
| """Capability implementation with RSA encryption support.""" | ||
|
|
||
| intersect_sdk_capability_name = 'HelloExample' | ||
|
|
||
| @intersect_status() | ||
| def status(self) -> str: | ||
| """Basic status function which returns a hard-coded string.""" | ||
| return 'Up' | ||
|
|
||
| @intersect_message() | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. may want to explicitly set the encryption schemes to the |
||
| def say_hello_to_name(self, name: str) -> str: | ||
| """Takes in a string parameter and says 'Hello' to the parameter!""" | ||
| return f'Hello, {name}!' | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| """ | ||
| Create a service with RSA encryption enabled. | ||
|
|
||
| The service automatically generates an RSA key pair internally. | ||
| When clients request RSA encryption, the service will: | ||
| 1. Fetch the client's public key | ||
| 2. Encrypt the response using the client's public key | ||
| 3. The client decrypts using its private key | ||
| """ | ||
|
|
||
| from_config_file = { | ||
| 'brokers': [ | ||
| { | ||
| 'username': 'intersect_username', | ||
| 'password': 'intersect_password', | ||
| 'port': 1883, | ||
| 'protocol': 'mqtt5.0', | ||
| } | ||
| ], | ||
| 'hierarchy': { | ||
| 'organization': 'hello-organization', | ||
| 'facility': 'hello-facility', | ||
| 'system': 'hello-system', | ||
| 'subsystem': 'hello-subsystem', | ||
| 'service': 'hello-service', | ||
| }, | ||
| } | ||
|
|
||
| config = IntersectServiceConfig(**from_config_file) | ||
|
|
||
| """ | ||
| step two: create instances of your capabilities, which you will inject into the service | ||
| """ | ||
| capabilities = [HelloServiceCapabilityImplementation()] | ||
|
|
||
| """ | ||
| step three: create the service using your capability and configuration | ||
| """ | ||
| intersect_service = IntersectService(capabilities, config) | ||
|
|
||
| """ | ||
| step four: utilize the default_intersect_lifecycle_loop function to manage startup, | ||
| the user lifecycle loop, and shutdown automatically. You must pass it the service | ||
| and a function containing your optional lifecycle code to execute. | ||
| """ | ||
| default_intersect_lifecycle_loop(intersect_service) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/INTERSECT-SDK/python-sdk/main/src/intersect_sdk/_internal/schema.schema.json", | ||
| "intersect_sdk_version": "0.8.0", | ||
| "name": "hello-organization.hello-facility.hello-system.hello-subsystem.hello-service", | ||
| "capabilities": [ | ||
| { | ||
| "name": "HelloExample", | ||
| "functions": [ | ||
| { | ||
| "name": "say_hello_to_name", | ||
| "parameters": { | ||
| "type": "string" | ||
| }, | ||
| "returns": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| ], | ||
| "encryption_schemes": [ | ||
| "NONE", | ||
| "RSA" | ||
| ] | ||
| } | ||
| ] | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will need to call
intersect_sdk.get_public_keybefore callingsay_hello_to_name