diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index f26ae5e0..36a0d08e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -214,7 +214,11 @@ packages/ │ │ ├── parser.rs # SQL parsing entry point │ │ └── context/ # Session state (statements, portals, metadata) │ ├── proxy/ # Encryption service, schema management, config -│ └── config/ # Configuration parsing +│ ├── config/ # Configuration parsing +│ ├── cli/ # CLI argument parsing +│ ├── connect/ # Database connection management +│ ├── tls/ # TLS configuration and setup +│ └── log/ # Logging targets and configuration ├── eql-mapper/ # SQL type inference and transformation │ └── src/ │ ├── inference/ # Type inference engine diff --git a/CHANGELOG.md b/CHANGELOG.md index db3602a8..398d0b41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Added -- **Cipher cache miss metric**: New Prometheus counter `cipherstash_proxy_keyset_cipher_cache_miss_total` tracks cache misses requiring cipher initialization. This complements the `cipherstash_proxy_keyset_cipher_cache_hit_total` metric, and can be used to calculate cache hit/miss ratio. +- **Cipher cache miss metric**: New Prometheus counter `cipherstash_proxy_keyset_cipher_cache_miss_total` tracks cache misses requiring cipher initialization. This complements the `cipherstash_proxy_keyset_cipher_cache_hits_total` metric, and can be used to calculate cache hit/miss ratio. - **Cipher init duration metric**: New Prometheus histogram `cipherstash_proxy_keyset_cipher_init_duration_seconds` tracks cipher initialization time including ZeroKMS network calls. - **Encrypt/decrypt timing**: Debug logs for `encrypt_eql` and `decrypt_eql` now include `duration_ms`. - **Cache eviction logging**: ScopedCipher cache eviction events are now logged under the `ZEROKMS` target. diff --git a/CLAUDE.md b/CLAUDE.md index 309cec56..61267dcc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,9 +18,9 @@ Key capabilities: **Core Proxy (`packages/cipherstash-proxy/`):** - `postgresql/` - PostgreSQL wire protocol implementation, message parsing, and client handling -- `encrypt/` - Integration with CipherStash ZeroKMS for key management and encryption operations +- `proxy/zerokms/` - ZeroKMS client initialization and key management - `config/` - Configuration management for database connections, TLS, and encryption settings -- `eql/` - EQL v2 types and encryption abstractions +- `proxy/encrypt_config/` - Encryption configuration and schema management **EQL Mapper (`packages/eql-mapper/`):** - SQL parsing and type inference engine @@ -29,7 +29,9 @@ Key capabilities: **Integration Tests (`packages/cipherstash-proxy-integration/`):** - Comprehensive test suite covering encryption scenarios -- Language-specific integration tests (Python, Go, Elixir) + +**Language Integration Tests (`tests/python/`, `tests/integration/golang/`):** +- Language-specific integration tests (Python, Go) **Showcase (`packages/showcase/`):** - Healthcare data model demonstrating EQL v2 encryption @@ -82,7 +84,7 @@ mise run reset # Full test suite (hygiene + unit + integration) mise run test -# Hygiene checks only +# Hygiene checks (compilation, formatting, clippy) mise run check # Unit tests only @@ -117,6 +119,7 @@ mise run postgres:down ### Authentication & Encryption Proxy requires CipherStash credentials configured in `mise.local.toml`: ```toml +[env] CS_WORKSPACE_CRN = "crn:region:workspace-id" CS_CLIENT_ACCESS_KEY = "your-access-key" CS_DEFAULT_KEYSET_ID = "your-keyset-id" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 623c1e35..4ce5aa93 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,8 +34,8 @@ Please do not create a public GitHub issue. ## Code of Conduct This project has adopted the [Contributor Covenant](https://www.contributor-covenant.org/). -For more information see the [Code of Conduct FAQ](./CODE_OF_CONDUCT.md) or contact support@cipherstash.com with any questions. +For more information see the [Code of Conduct](./CODE_OF_CONDUCT.md) or contact support@cipherstash.com with any questions. ## Licensing -See the [LICENSE](./LICENSE) file for our project's licensing. +See the [LICENSE](./LICENSE.md) file for our project's licensing. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fded1e84..12beb708 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -430,7 +430,7 @@ To use a different version of EQL, set the path to the desired EQL release file PostgreSQL port numbers are 4 digits: -- The first two digits denote non-TLS (`55`) or non-TLS (`56`) +- The first two digits denote non-TLS (`55`) or TLS (`56`) - The last two digits denote the version of PostgreSQL PostgreSQL latest always runs on `5532`. @@ -475,7 +475,7 @@ All containers use the same credentials and database, defined in `tests/pg/commo POSTGRES_DB="cipherstash" POSTGRES_USER="cipherstash" PGUSER="cipherstash" -POSTGRES_PASSWORD="password" +POSTGRES_PASSWORD="p@ssword" ``` PostgreSQL configuration files live at: @@ -501,7 +501,7 @@ Environment files: If you ever get confused about where your configuration is coming from, run `mise cfg` to get a list of config files in use. -Certificates are generated by `mkcert`, and live in `tests/tls/`. +Certificates are generated by `openssl`, and live in `tests/tls/`. #### Configuration: development endpoints diff --git a/README.md b/README.md index 05ff580b..4947886e 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,6 @@ -## Proxy V2 now available - -[Read the announcement](https://cipherstash.com/blog/introducing-proxy) - CipherStash Proxy provides transparent, *searchable* encryption for your existing Postgres database. CipherStash Proxy: @@ -68,9 +64,15 @@ cd proxy # Sign up, create a workspace, and generate credentials # Visit: https://dashboard.cipherstash.com/sign-up -# Put credentials in .env.proxy.docker -# Copy the credentials from the dashboard and paste them into .env.proxy.docker using your preferred text editor. -nano .env.proxy.docker +# Create .env.proxy.docker with your CipherStash credentials +# Replace the placeholder values with your actual credentials from the dashboard +cat > .env.proxy.docker << 'EOF' +CS_WORKSPACE_CRN=crn:...your-workspace-crn... +CS_CLIENT_ACCESS_KEY=your-client-access-key +CS_DEFAULT_KEYSET_ID=your-keyset-id +CS_CLIENT_ID=your-client-id +CS_CLIENT_KEY=your-client-key +EOF # Start the containers docker compose up diff --git a/SECURITY.md b/SECURITY.md index 77f1b241..6dac22c8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,10 +13,7 @@ This repository contains the source code for CipherStash Proxy, including: ### CipherStash Proxy -| Version | Supported | -| ------- | ------------------ | -| 2.1.x | :white_check_mark: | -| < 2.1 | :x: | +**Security fixes are released for the latest release line.** Security reports are welcome for any version, but fixes land in the latest release — if you are running an older version, plan to upgrade to receive them. All software follows semantic versioning and undergoes internal security review, automated analysis, and reproducible builds as part of our SDLC. @@ -74,7 +71,7 @@ The following are **in scope**: The following are **out of scope**: -- Example [schema](./docs/sql/schema-example.sql) and [configuration](./cipherstash-proxy-example.toml) (though we are still grateful for any relevant disclosires there) +- Example [schema](./docs/sql/schema-example.sql) and [configuration](./cipherstash-proxy-example.toml) (though we are still grateful for any relevant disclosures there) - Social engineering, physical attacks, or denial-of-service - Attacks requiring privileged access to developer machines or CI/CD infrastructure @@ -92,7 +89,7 @@ To maintain a strong security posture, contributors MUST: ### 🛡 Coding & dependency hygiene - Avoid adding dependencies unless necessary - Keep dependencies updated and vetted -- Use TypeScript for all new code +- Use Rust for all new code - Ensure all code paths that handle keys or encrypted data include type-safe boundaries ### 🔍 Testing & review diff --git a/cipherstash-proxy-example.toml b/cipherstash-proxy-example.toml index 1851d6a8..77319993 100644 --- a/cipherstash-proxy-example.toml +++ b/cipherstash-proxy-example.toml @@ -1,14 +1,13 @@ [tls] -type = "Path" # To provide paths to PEM files -certificate = "tests/tls/server.cert" -private_key = "tests/tls/server.key" +certificate_path = "tests/tls/server.cert" +private_key_path = "tests/tls/server.key" -# type = "Pem" # To directly provide PEM contents -# certificate = """-----BEGIN CERTIFICATE----- +# To directly provide PEM contents: +# certificate_pem = """-----BEGIN CERTIFICATE----- # ...your certificate content here... # -----END CERTIFICATE----- # """ -# private_key = """-----BEGIN PRIVATE KEY----- +# private_key_pem = """-----BEGIN PRIVATE KEY----- # ...your private key content here... # -----END PRIVATE KEY----- # """ diff --git a/docs/errors.md b/docs/errors.md index 670df8b7..9d8e5adf 100644 --- a/docs/errors.md +++ b/docs/errors.md @@ -5,6 +5,7 @@ - Authentication errors: - [Database](#authentication-failed-database) - [Client](#authentication-failed-client) + - [ZeroKMS](#zerokms-authentication-failed) - Mapping errors: - [Invalid parameter](#mapping-invalid-parameter) @@ -15,8 +16,7 @@ - Encrypt errors: - [Column could not be encrypted](#encrypt-column-could-not-be-encrypted) - - [Column could not be encrypted](#encrypt-column-could-not-be-encrypted) - - [Could not decrypt data for keyset](#encrypt-encrypt-could-not-decrypt-data-for-keyset) + - [Could not decrypt data for keyset](#encrypt-could-not-decrypt-data-for-keyset) - [KeysetId could not be parsed](#encrypt-keyset-id-could-not-be-parsed) - [KeysetId could not be set](#encrypt-keyset-id-could-not-be-set) - [KeysetName could not be set](#encrypt-keyset-name-could-not-be-set) @@ -26,6 +26,8 @@ - [Unknown table](#encrypt-unknown-table) - [Unknown index term](#encrypt-unknown-index-term) - [Column configuration mismatch](#encrypt-column-config-mismatch) + - [Missing encrypt configuration](#encrypt-missing-encrypt-configuration) + - [Unexpected SET keyset](#encrypt-unexpected-set-keyset) - Decrypt errors: - [Column could not be deserialised](#encrypt-column-could-not-be-deserialised) @@ -91,7 +93,7 @@ Client authentication failed. Check username and password. -## ZeroKMS +## ZeroKMS Authentication failed when connecting to ZeroKMS. @@ -184,7 +186,7 @@ The parameter type is not supported. ### Error message ``` -Encryption of PostgreSQL {name} (OID {oid}) types is not currently supported. +Encryption of EQL column {column_type} using strategy {eql_term} is not supported. ``` ### How to fix @@ -218,6 +220,8 @@ When `mapping_errors_enabled` is `false` (the default), then type check errors a When `mapping_errors_enabled` is `true`, then type check errors are raised, and statement execution halts. +Configure this setting with the environment variable `CS_DEVELOPMENT__ENABLE_MAPPING_ERRORS` or in the TOML config file under `[development] enable_mapping_errors = true`. + In our experience, most production systems have a relatively small number of columns that require protection. As SQL is large and complex, instead of blocking statements with type check errors that are false negatives, the default behaviour of Proxy is to allow the statement. @@ -577,6 +581,41 @@ If the error persists, please contact CipherStash [support](https://cipherstash. +## Missing encrypt configuration + +The encrypted column type does not have a matching encrypt configuration. + + +### Error message + +``` +Missing encrypt configuration for column type `{plaintext_type}`. +``` + +### How to fix + +1. Define the encrypted configuration for the column type using [EQL](https://github.com/cipherstash/encrypt-query-language). +2. If this error persists, please contact CipherStash [support](https://cipherstash.com/support) as this may indicate a bug. + + + + + +## Unexpected SET keyset + +A `SET CIPHERSTASH.KEYSET` statement was used when a default keyset has already been configured. + + +### Error message + +``` +Cannot SET CIPHERSTASH.KEYSET if a default keyset has been configured. +``` + +### How to fix + +1. Remove the `SET CIPHERSTASH.KEYSET` statement from your application code. +2. Or remove the `default_keyset_id` from the proxy configuration to allow dynamic keyset selection. diff --git a/docs/how-to/index.md b/docs/how-to/index.md index 4a2bd8ae..9f8309cc 100644 --- a/docs/how-to/index.md +++ b/docs/how-to/index.md @@ -58,7 +58,7 @@ services: ``` -For a fully-working example, go to [`docker-compose.yml`](./docker-compose.yml). +For a fully-working example, go to [`docker-compose.yml`](../../docker-compose.yml). Follow the steps in [Getting started](../README.md#getting-started) to see it in action. Once you have set up a `docker-compose.yml`, start the Proxy container: @@ -132,7 +132,27 @@ Read the full list of configuration options and what they do in the [reference d ## Running Proxy locally -TODO: Add instructions for running Proxy locally +To run CipherStash Proxy locally for development: + +```bash +# Install prerequisites +mise trust --yes && mise install + +# Start PostgreSQL and install EQL +mise run postgres:up --extra-args "--detach --wait" +mise run postgres:setup + +# Run Proxy as a local process +mise run proxy +``` + +Alternatively, run Proxy in a container: + +```bash +mise run proxy:up --extra-args "--detach --wait" +``` + +See [Configuring Proxy](#configuring-proxy) for required environment variables and configuration options. ## Setting up the database schema @@ -233,14 +253,14 @@ The third SQL statement adds an `ope` index, which supports the same range and o `ore` and `ope` are alternatives for range and ordering queries — add one or the other to a column, not both. `ore` is the recommended default. `ope` produces ciphertexts that sort under PostgreSQL's native byte ordering, which makes ordering and range scans cheaper, but as an order-preserving scheme it reveals more about the relative order of stored values than `ore` does. Choose based on your performance and threat-model requirements; see the [EQL `INDEX` documentation](https://github.com/cipherstash/encrypt-query-language/blob/main/docs/reference/INDEX.md) for the full tradeoffs. -> ![IMPORTANT] +> [!IMPORTANT] > Adding, updating, or deleting encrypted indexes on columns that already contain encrypted data will not re-index that data. To use the new indexes, you must `SELECT` the data out of the column, and `UPDATE` it again. To learn how to use encrypted indexes for other encrypted data types like `text`, `int`, `boolean`, `date`, and `jsonb`, see the [EQL documentation](https://github.com/cipherstash/encrypt-query-language/blob/main/docs/reference/INDEX.md). When deploying CipherStash Proxy into production environments with real data, we recommend that you apply these database schema changes with the normal tools and process you use for making changes to your database schema. -To see more examples of how to modify your database schema, check out [the example schema](./sql/schema-example.sql) from [Getting started](#getting-started). +To see more examples of how to modify your database schema, check out [the example schema](../sql/schema-example.sql) from [Getting started](#getting-started). ## Encrypting data in an existing database diff --git a/docs/reference/encrypt-tool.md b/docs/reference/encrypt-tool.md index 7e2ed144..8c02cfa3 100644 --- a/docs/reference/encrypt-tool.md +++ b/docs/reference/encrypt-tool.md @@ -12,7 +12,7 @@ CipherStash Proxy includes an `encrypt` tool – a CLI application to encrypt ex ## Using the `encrypt` tool Encrypt the `source` column data in `table` into the specified encrypted `target` column. -The `encrypt` tool connects to CipherStash Proxy using the `cipherstash.toml` configuration or `ENV` variables. +The `encrypt` tool connects to CipherStash Proxy using the `cipherstash-proxy.toml` configuration or `ENV` variables. ``` cipherstash-proxy encrypt [OPTIONS] --table --columns ... @@ -25,7 +25,7 @@ At a high-level, the process for encrypting a column in the database is: 1. Add a new encrypted destination column with the appropriate encryption configuration. 2. Using CipherStash Proxy to process: 1. Select from the original plaintext column. - 2. Update the encrpted column to set the plaintext value. + 2. Update the encrypted column to set the plaintext value. 3. Drop the original plaintext column. 4. Rename the encrypted column to the original plaintext column name. diff --git a/docs/reference/index.md b/docs/reference/index.md index 964c8d0b..e3ac358f 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -8,6 +8,9 @@ This page contains reference documentation for configuring CipherStash Proxy and - [Recommended settings for development](#recommended-settings-for-development) - [Per-target log levels](#per-target-log-levels) - [Docker-specific configuration](#docker-specific-configuration) +- [Command line interface](#command-line-interface) +- [Multitenant operation](#multitenant-operation) +- [Disabling encrypted mapping](#disabling-encrypted-mapping) - [Prometheus metrics](#prometheus-metrics) - [Available metrics](#available-metrics) - [Troubleshooting ZeroKMS connections](#troubleshooting-zerokms-connections) @@ -16,7 +19,7 @@ This page contains reference documentation for configuring CipherStash Proxy and ## Proxy config options -You can configure CipherStash Proxy with a config file, enviroment variables, or a combination of the two – see [Configuring Proxy](#configuring-proxy) for instructions. +You can configure CipherStash Proxy with a config file, environment variables, or a combination of the two – see [Configuring Proxy](../how-to/index.md#configuring-proxy) for instructions. The following are all the configuration options available for Proxy, with their equivalent environment variables: @@ -29,7 +32,7 @@ The following are all the configuration options available for Proxy, with their # Env: CS_SERVER__HOST host = "0.0.0.0" -# Proxy host posgt +# Proxy host port # Optional # Default: `6432` # Env: CS_SERVER__PORT @@ -60,8 +63,8 @@ worker_threads = "4" # Env: CS_SERVER__THREAD_STACK_SIZE thread_stack_size = "2097152" -# Cipher cache size (number of entries) -# Sets the maximum number of encryption/decryption operations to cache +# Cipher cache size (number of keyset-scoped ciphers) +# Sets the maximum number of keyset-scoped ciphers to cache (internal sizing is calculated per entry) # Optional # Default: `64` # Env: CS_SERVER__CIPHER_CACHE_SIZE @@ -78,11 +81,11 @@ cipher_cache_ttl_seconds = "3600" [database] # Database host address # Optional -# Default: `0.0.0.0` +# Default: `127.0.0.1` # Env: CS_DATABASE__HOST -host = "0.0.0.0" +host = "127.0.0.1" -# Database host post +# Database host port # Optional # Default: `5432` # Env: CS_DATABASE__PORT @@ -199,7 +202,7 @@ format = "pretty" # Log format # Optional # Valid values: `stdout | stderr` -# Default: `info` +# Default: `stdout` # Env: CS_LOG__OUTPUT output = "stdout" @@ -238,7 +241,7 @@ slow_db_response_min_duration_ms = "100" # Env: CS_PROMETHEUS__ENABLED enabled = "false" -# Prometheus exporter post +# Prometheus exporter port # Optional # Default: `9930` # Env: CS_PROMETHEUS__PORT @@ -311,10 +314,6 @@ As a convenience for production deployments, with the below environment variable CS_DATABASE__INSTALL_AWS_RDS_CERT_BUNDLE="true" ``` -## Command line options - - - ## Command line interface The CipherStash Proxy accepts command line arguments. @@ -562,6 +561,8 @@ If the proxy is running on a host other than localhost, access on that host. | `cipherstash_proxy_statements_session_duration_seconds_sum` | Count | Total time CipherStash Proxy spent processing SQL statements | | `cipherstash_proxy_statements_encrypted_total` | Counter | Number of SQL statements that required encryption | | `cipherstash_proxy_statements_passthrough_total` | Counter | Number of SQL statements that did not require encryption | +| `cipherstash_proxy_statements_passthrough_mapping_disabled_total` | Counter | Number of SQL statements passed through because mapping was disabled | +| `cipherstash_proxy_slow_statements_total` | Counter | Number of SQL statements that exceeded the slow statement threshold | | `cipherstash_proxy_statements_total` | Counter | Total number of SQL statements processed by CipherStash Proxy | | `cipherstash_proxy_statements_unmappable_total` | Counter | Total number of unmappable SQL statements processed by CipherStash Proxy | @@ -629,9 +630,9 @@ rate(cipherstash_proxy_keyset_cipher_cache_hits_total[5m]) ## Supported architectures -CipherStash Proxy is [available as a Docker container image](https://hub.docker.com/r/cipherstash/proxy) for `linux/arm64` architectures. +CipherStash Proxy is [available as a Docker container image](https://hub.docker.com/r/cipherstash/proxy) for `linux/arm64` and `linux/amd64` architectures. -If you're interested in a Docker image for other architectures (like `linux/amd64`), upvote [this idea](https://github.com/cipherstash/proxy/discussions/214). +For other architecture requests, see [this discussion](https://github.com/cipherstash/proxy/discussions/214). diff --git a/docs/reference/message-flow.md b/docs/reference/message-flow.md index 74293eb7..0ec46c41 100644 --- a/docs/reference/message-flow.md +++ b/docs/reference/message-flow.md @@ -4,9 +4,6 @@ Below are the flow diagrams for the message handling in CipherStash Proxy for Po ### Parse -![Parse message](./images/parse.svg "Parse") - - ```mermaid --- config: @@ -27,8 +24,6 @@ flowchart LR ### Bind -![Bind message](./images/bind.svg "Bind") - ```mermaid --- config: diff --git a/docs/reference/searchable-json.md b/docs/reference/searchable-json.md index c45589fb..6b5e3798 100644 --- a/docs/reference/searchable-json.md +++ b/docs/reference/searchable-json.md @@ -6,7 +6,7 @@ This document outlines the supported JSONB functions and operators in CipherStas ## Table of Contents - [Setup](#setup) -- [Important Limtiations](#important-limitations) +- [Important Limitations](#important-limitations) - [Operators](#operators) - [->](#field_access_operator) - [->>](#field_access_as_text_operator) @@ -302,7 +302,7 @@ SELECT encrypted_jsonb @> '{"number": 99}' FROM cipherstash; ```sql -- nested object -SELECT encrypted_jsonb @> '{"object": {"string": "world", "number": 99},' FROM cipherstash; +SELECT encrypted_jsonb @> '{"object": {"string": "world", "number": 99}}' FROM cipherstash; ---------- ?column? @@ -334,7 +334,7 @@ SELECT '{ .. }' <@ encrypted_column FROM table_name; ```sql -- field/value returns true -SELECT '{"number": 1}' @> encrypted_jsonb FROM cipherstash; +SELECT '{"number": 1}' <@ encrypted_jsonb FROM cipherstash; ---------- ?column? @@ -345,7 +345,7 @@ SELECT '{"number": 1}' @> encrypted_jsonb FROM cipherstash; ```sql -- field/value returns false if no match -SELECT '{"number": 99}' @> encrypted_jsonb FROM cipherstash; +SELECT '{"number": 99}' <@ encrypted_jsonb FROM cipherstash; ---------- ?column? @@ -357,7 +357,7 @@ SELECT '{"number": 99}' @> encrypted_jsonb FROM cipherstash; ```sql -- nested object -SELECT '{"object": {"string": "world", "number": 99}' @> encrypted_jsonb FROM cipherstash; +SELECT '{"object": {"string": "world", "number": 99}}' <@ encrypted_jsonb FROM cipherstash; ---------- ?column? @@ -627,84 +627,6 @@ SELECT jsonb_array_length(jsonb_path_query(encrypted_jsonb, '$.unknown')) FROM c (0 rows) ``` ---------------------------------------------------------------- - - - - - - - - - -======================================= - - - - - - - - ---------------------------------------------------------------- - - - -## Containment Operators - -> **Note:** Containment operators work directly with JSONB literals without requiring explicit `::jsonb` type casts. The examples below use the simplified syntax intentionally. - -### `@>` (Contains Operator) - -Tests whether the left JSONB value contains the right JSONB value. - -**Syntax:** -```sql -SELECT encrypted_jsonb @> '{"field": "value"}' FROM table_name; -``` - -**Examples:** -```sql --- Check if contains string field -SELECT encrypted_jsonb @> '{"string": "hello"}' FROM encrypted; - --- Check if contains numeric field -SELECT encrypted_jsonb @> '{"number": 42}' FROM encrypted; - --- Check if contains array -SELECT encrypted_jsonb @> '{"array_number": [42, 84]}' FROM encrypted; - --- Check if contains nested object -SELECT encrypted_jsonb @> '{"nested": {"number": 1815, "string": "world"}}' FROM encrypted; -``` - -**Supported Containment Types:** -- String fields -- Numeric fields -- Complete arrays -- Nested objects - -### `<@` (Contained By Operator) - -Tests whether the left JSONB value is contained by the right JSONB value. - -**Syntax:** -```sql -SELECT '{"field": "value"}' <@ encrypted_jsonb FROM table_name; -``` - -**Examples:** -```sql --- Check if value is contained by the document -SELECT '{"string": "hello"}' <@ encrypted_jsonb FROM encrypted; - --- Check numeric containment -SELECT '{"number": 42}' <@ encrypted_jsonb FROM encrypted; - --- Check array containment -SELECT '{"array_string": ["hello", "world"]}' <@ encrypted_jsonb FROM encrypted; -``` - ## Comparison Operators in WHERE Clauses All standard comparison operators work with JSON field extraction: diff --git a/packages/cipherstash-proxy/README.md b/packages/cipherstash-proxy/README.md index d6b3702e..a8418533 100644 --- a/packages/cipherstash-proxy/README.md +++ b/packages/cipherstash-proxy/README.md @@ -2,4 +2,4 @@ The core proxy engine for CipherStash Proxy. -Please refer to [the top level README](../../README.md) for local development documentation. +Please refer to the [development guide](../../DEVELOPMENT.md) for local development documentation. diff --git a/packages/showcase/README.md b/packages/showcase/README.md index 2b3cc1eb..92db1e29 100644 --- a/packages/showcase/README.md +++ b/packages/showcase/README.md @@ -443,6 +443,7 @@ ORDER BY jsonb_path_query_first(pii, '$.insurance.coverage.copays.primary_care') 2. **Configure CipherStash credentials** in `mise.local.toml`: ```toml + [env] CS_WORKSPACE_CRN = "crn:region:workspace-id" CS_CLIENT_ACCESS_KEY = "your-access-key" CS_DEFAULT_KEYSET_ID = "your-keyset-id" @@ -464,7 +465,7 @@ Execute the comprehensive JSONB demonstration: cargo run --package showcase # Or run with mise -mise run showcase +mise run test:integration:showcase ``` ### Expected Output diff --git a/tests/integration/elixir_test/README.md b/tests/integration/elixir_test/README.md index 6813b1e9..ececd748 100644 --- a/tests/integration/elixir_test/README.md +++ b/tests/integration/elixir_test/README.md @@ -8,6 +8,7 @@ The tests can be run using [mise](https://mise.jdx.dev/). From the project root directory, run: ``` -test:integration:lang:elixir +mise run test:integration:lang:elixir ``` +> **Note:** Elixir integration tests are currently disabled pending a fix for test flakiness. diff --git a/tests/integration/golang/README.md b/tests/integration/golang/README.md index 5a4fe9a7..697d2ef1 100644 --- a/tests/integration/golang/README.md +++ b/tests/integration/golang/README.md @@ -29,7 +29,7 @@ Alternatively, to run the tests outside of the container: ``` bash # Tell the tests where to find Proxy -export DATABASE_URL="postgresql://cipherstash:password@localhost:6432/cipherstash" +export DATABASE_URL="postgresql://cipherstash:p%40ssword@localhost:6432/cipherstash" # Run the tests go test -v ./... diff --git a/tests/python/README.md b/tests/python/README.md index 784c76f5..bab89f51 100644 --- a/tests/python/README.md +++ b/tests/python/README.md @@ -1,6 +1,14 @@ +# Python integration tests +Language-integration tests that exercise CipherStash Proxy from Python clients. +From the repo root, the canonical entry point is: +```sh +mise run test:integration:lang:python +``` + +To run the suite manually: Install pipx https://pipx.pypa.io/stable/installation/