-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add rust example for simple roundtrip and Python examples. (#14)
- Loading branch information
Showing
19 changed files
with
2,962 additions
and
13 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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,69 @@ | ||
# IronCore Labs Alloy SDK Examples | ||
|
||
This directory contains some examples of using the IronCore Labs Alloy SDK to protect sensitive data. | ||
|
||
This SDK can be used in two different modes: Standalone and SaaS Shield. In Standalone mode, you will need to provide | ||
your own secrets. In SaaS Shield mode, the TSP will derive secrets for you. | ||
|
||
# Standalone client | ||
|
||
Standalone mode is designed to support fully offline programs and therefore does not require any additional setup. | ||
In a production environment, you would have to manage secrets for your tenants, but this example provides dummy | ||
secrets for convenience. | ||
|
||
# SaaS Shield client | ||
|
||
In order to use SaaS Shield mode, you need to run one or more _Tenant Security Proxies_ (TSPs) in your environment. | ||
This service is provided as a Docker container, so it is easy to run the proxy on any computer that has Docker | ||
installed. IronCore Labs hosts the Docker container on a publicly accessible container registry, so you can pull | ||
the image from there and run it locally. | ||
|
||
The TSP has a companion Docker container, the _Tenant Security Logdriver_ (LD) that runs alongside it in your environment. | ||
It is also hosted on the same publicly accessible container registry. | ||
|
||
In addition to the Docker containers, you need a configuration file that specifies how the TSP and LD should communicate | ||
with the IronCore Labs Configuration Broker and Data Control Platform, which work together to enable the end-to-end | ||
encryption that keeps all of the tenant KMS configuration information secure. To simplify the process of running | ||
these examples, we have created a demo vendor and tenants that you can use for the examples; all the necessary | ||
configuration information is included in the `demo-tsp.conf` file in this directory. | ||
**NOTE:** Normally, the file containing the configuration would be generated by the vendor and loaded into a | ||
Kubernetes secret or similar mechanism for securely loading the configuration into the docker container. We | ||
have included this configuration in the repository as a convenience. Also note that these accounts are all | ||
created in IronCore's staging infrastructure. | ||
|
||
The following command will get a TSP and LD running together on your computer with the provided configuration. | ||
The `docker-compose` command will pull both container images, then start them up together on a subnetwork, so they can | ||
communicate with each other. | ||
|
||
```bash | ||
docker-compose -f docker-compose.yml up | ||
``` | ||
|
||
The TSP will be listening locally on port 32804. | ||
|
||
Once the TSP and LD are running, you can experiment with the example programs. | ||
|
||
Each of the examples executes as an individual tenant of our demo SaaS vendor. There are six tenants defined; | ||
their IDs are the following: | ||
|
||
- tenant-gcp | ||
- tenant-aws | ||
- tenant-azure | ||
- tenant-gcp-l | ||
- tenant-aws-l | ||
- tenant-azure-l | ||
|
||
The last three are similar to the first three, but they have [key leasing](https://ironcorelabs.com/docs/saas-shield/what-is-key-leasing/) enabled. | ||
|
||
By default, an example will use the `tenant-gcp` tenant. If you would like to experiment with a different tenant, just do: | ||
|
||
```bash | ||
export TENANT_ID=<select tenant ID> | ||
``` | ||
|
||
before running the example. | ||
|
||
# Additional Resources | ||
|
||
If you would like some more in-depth information, our website features a section of technical | ||
documentation about our different [products](https://ironcorelabs.com/docs/). |
This file contains 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,8 @@ | ||
SERVICE_ACCOUNT_ID=d413a647febbac39ae4760cb06046652eab75c215e587ff3 | ||
SERVICE_CONFIG_ID=777 | ||
SERVICE_ENCRYPTION_PRIVATE_KEY=YiqyMDbPmnD8hVGNd3Rq9X+jT3/gXln2IET9m5b97NA= | ||
SERVICE_SIGNING_PRIVATE_KEY=9lAJ3a1Cb4xTL9jD/qdt53pBSG6m9ZNWWFs2WsMN2Mpp+huxRRRM3ry83nu6PfBg4WgBa9oB3V+XN+/BTlQLAg== | ||
SERVICE_SEGMENT_ID=698 | ||
API_KEY=0WUaXesNgbTAuLwn | ||
IRONCORE_ENV=stage | ||
RUST_LOG=info |
This file contains 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,23 @@ | ||
version: "3.3" | ||
services: | ||
tenant-security-proxy: | ||
env_file: | ||
- ./demo-tsp.conf | ||
ports: | ||
- 32804:7777 | ||
- 32805:9000 | ||
image: gcr.io/ironcore-images/tenant-security-proxy:4 | ||
links: | ||
- tenant-security-logdriver | ||
tenant-security-logdriver: | ||
environment: | ||
- LOGDRIVER_EVENT_PRODUCER_URL=tcp://tenant-security-proxy:5555 | ||
env_file: | ||
- ./demo-tsp.conf | ||
ports: | ||
- 32806:9001 | ||
image: gcr.io/ironcore-images/tenant-security-logdriver:4 | ||
volumes: | ||
- type: bind | ||
source: /tmp | ||
target: /logdriver |
This file contains 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 @@ | ||
ironcore_alloy_examples.egg-info/ |
This file contains 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,48 @@ | ||
# Python Examples | ||
|
||
## Setup | ||
|
||
To run the examples, you must first activate the virtual environment; we use `hatch` to manage this. | ||
If you don't have `hatch` installed, directions for installing it can be found | ||
[here](https://hatch.pypa.io/latest/install/). | ||
|
||
From the `examples/python` folder, run | ||
|
||
```bash | ||
hatch shell | ||
``` | ||
|
||
Once the environment is activated, decide if you would like to run the Standalone or SaaS Shield examples and navigate | ||
to the respective directory. If you choose SaaS Shield, be sure to startup the TSP as described [here](../README.md). | ||
|
||
## Examples | ||
|
||
### Vector roundtrip | ||
|
||
This example shows creating a plaintext vector associated with a tenant, encrypting the vector, then decrypting it. | ||
Because of floating point arithmetic, the decrypted vector may not perfectly match the plaintext. | ||
|
||
``` | ||
python vector-roundtrip.py | ||
``` | ||
|
||
Each time you run the example, the encrypted vector will change significantly, but nearest-neighbor searches | ||
will still function. | ||
|
||
### Vector search | ||
|
||
This example shows creating a plaintext vector associated with a tenant, encrypting the vector, then generating | ||
query vectors that can be used for nearest-neighbor searches on the original plaintext. | ||
|
||
``` | ||
python vector-search.py | ||
``` | ||
|
||
### Standard roundtrip | ||
|
||
This example shows creating a plaintext document containing personal information associated with a tenant, encrypting | ||
the document, then decrypting it. | ||
|
||
``` | ||
python standard-roundtrip.py | ||
``` |
This file contains 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,8 @@ | ||
# hatch shell | ||
|
||
[project] | ||
name = "ironcore-alloy-examples" | ||
authors = [{ name = "IronCore Labs", email = "[email protected]" }] | ||
requires-python = ">=3.7" | ||
dependencies = ["ironcore-alloy"] | ||
dynamic = ["version"] |
This file contains 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,40 @@ | ||
import ironcore_alloy as alloy | ||
import os | ||
import asyncio | ||
import json | ||
|
||
|
||
async def main(): | ||
tenant_id = os.environ.get('TENANT_ID', 'tenant-gcp') | ||
api_key = os.environ.get('API_KEY', '0WUaXesNgbTAuLwn') | ||
tsp_uri = "http://localhost:32804" | ||
approximation_factor = 7.2 | ||
config = alloy.SaasShieldConfiguration(tsp_uri, api_key, False, approximation_factor) | ||
sdk = alloy.SaasShield(config) | ||
|
||
jim_original = json.dumps({ | ||
"name": "Jim Bridger", | ||
"address": "2825-519 Stone Creek Rd, Bozeman, MT 59715", | ||
"ssn": "000-12-2345" | ||
}) | ||
metadata = alloy.AlloyMetadata.new_simple(tenant_id) | ||
# Encrypt Jim's personal information | ||
encrypted = await sdk.standard().encrypt({"jim": bytes(jim_original, "utf-8")}, metadata) | ||
# Store off the `document` and `edek` | ||
|
||
# ----------------------------- | ||
|
||
# Later, retrieve the `document` and `edek` | ||
encrypted_recreated = alloy.EncryptedDocument(encrypted.edek, encrypted.document) | ||
# Decrypt Jim's personal information | ||
decrypted = await sdk.standard().decrypt(encrypted_recreated, metadata) | ||
jim_decrypted = json.loads(decrypted["jim"]) | ||
|
||
print("Decrypted SSN: ", jim_decrypted["ssn"]) | ||
print("Decrypted address: ", jim_decrypted["address"]) | ||
print("Decrypted name: ", jim_decrypted["name"]) | ||
|
||
|
||
if __name__ == '__main__': | ||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(main()) |
This file contains 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,29 @@ | ||
import ironcore_alloy as alloy | ||
import os | ||
import asyncio | ||
|
||
|
||
async def main(): | ||
tenant_id = os.environ.get('TENANT_ID', 'tenant-gcp') | ||
api_key = os.environ.get('API_KEY', '0WUaXesNgbTAuLwn') | ||
tsp_uri = "http://localhost:32804" | ||
approximation_factor = 7.2 | ||
config = alloy.SaasShieldConfiguration(tsp_uri, api_key, False, approximation_factor) | ||
sdk = alloy.SaasShield(config) | ||
|
||
data = [1.2, -1.23, 3.24, 2.37] | ||
print("Plaintext vector: ", data) | ||
plaintext = alloy.PlaintextVector(data, "contacts", "conversation-sentiment") | ||
metadata = alloy.AlloyMetadata.new_simple(tenant_id) | ||
encrypted = await sdk.vector().encrypt(plaintext, metadata) | ||
print("Encrypted vector: ", encrypted.encrypted_vector) | ||
# Store off encrypted_vector and paired_icl_info | ||
|
||
decrypted = await sdk.vector().decrypt(encrypted, metadata) | ||
print("Decrypted vector: ", decrypted.plaintext_vector) | ||
print("Note that the encryption/decryption is lossy due to floating point math.") | ||
|
||
|
||
if __name__ == '__main__': | ||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(main()) |
This file contains 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,34 @@ | ||
import ironcore_alloy as alloy | ||
import os | ||
import asyncio | ||
|
||
|
||
async def main(): | ||
tenant_id = os.environ.get('TENANT_ID', 'tenant-gcp') | ||
api_key = os.environ.get('API_KEY', '0WUaXesNgbTAuLwn') | ||
tsp_uri = "http://localhost:32804" | ||
approximation_factor = 7.2 | ||
config = alloy.SaasShieldConfiguration(tsp_uri, api_key, False, approximation_factor) | ||
sdk = alloy.SaasShield(config) | ||
|
||
data = [1.2, -1.23, 3.24, 2.37] | ||
print("Plaintext vector: ", data) | ||
plaintext = alloy.PlaintextVector(data, "contacts", "conversation-sentiment") | ||
metadata = alloy.AlloyMetadata.new_simple(tenant_id) | ||
encrypted = await sdk.vector().encrypt(plaintext, metadata) | ||
print("Encrypted vector: ", encrypted.encrypted_vector) | ||
# Store off `encrypted_vector` and `paired_icl_data`. | ||
# Note that `paired_icl_data` is required for decryption. If you only need to support querying, | ||
# then storing `paired_icl_data` is not required. | ||
|
||
search_vector = alloy.PlaintextVector([1.4, -1.32, 4.32, 2.37], "contacts", "conversation-sentiment") | ||
query_vectors = (await sdk.vector().generate_query_vectors({"vec_1": search_vector}, metadata))["vec_1"] | ||
query_vectors_embeddings = map(lambda vector: vector.encrypted_vector, query_vectors) | ||
print("Query vectors: ", list(query_vectors_embeddings)) | ||
print("Note that the query vectors are a nested list. If this tenant had an in-rotation key, two vectors") | ||
print("would be in the result. In that case, both vectors must be used in conjunction when querying.") | ||
|
||
|
||
if __name__ == '__main__': | ||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(main()) |
Oops, something went wrong.