diff --git a/README.md b/README.md index 7993ed3..ea95be1 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,9 @@ SELECT eql_v2.add_column('users', 'encrypted_email'); **Note:** This function allows you to encrypt and decrypt data but does not enable searchable encryption. See [Searching data with EQL](#searching-data-with-eql) for enabling searchable encryption. + **Important:** These functions must be run after any modifications to the configuration. diff --git a/src/config/config_test.sql b/src/config/config_test.sql index da140d0..c84ca2e 100644 --- a/src/config/config_test.sql +++ b/src/config/config_test.sql @@ -25,11 +25,11 @@ DO $$ BEGIN -- Add indexes - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); ASSERT (SELECT _search_config_exists('users', 'name', 'match')); -- Add index with cast - PERFORM eql_v2.add_search_config('users', 'name', 'unique', 'int'); + PERFORM eql_v2.add_search_config('users', 'name', 'unique', 'int', migrating => true); ASSERT (SELECT _search_config_exists('users', 'name', 'unique')); ASSERT (SELECT EXISTS (SELECT id FROM eql_v2_configuration c @@ -60,7 +60,7 @@ DO $$ BEGIN -- Add indexes - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); ASSERT (SELECT _search_config_exists('users', 'name', 'match')); ASSERT (SELECT EXISTS (SELECT id FROM eql_v2_configuration c @@ -68,7 +68,7 @@ DO $$ c.data #> array['tables', 'users', 'name', 'indexes'] ? 'match')); -- Add index with cast - PERFORM eql_v2.add_search_config('blah', 'vtha', 'unique', 'int'); + PERFORM eql_v2.add_search_config('blah', 'vtha', 'unique', 'int', migrating => true); ASSERT (SELECT _search_config_exists('blah', 'vtha', 'unique')); ASSERT (SELECT EXISTS (SELECT id FROM eql_v2_configuration c @@ -107,11 +107,11 @@ $$ LANGUAGE plpgsql; DO $$ BEGIN - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); ASSERT (SELECT _search_config_exists('users', 'name', 'match')); -- Pending configuration contains the path `user/name.match.option` - PERFORM eql_v2.modify_search_config('users', 'name', 'match', 'int', '{"option": "value"}'::jsonb); + PERFORM eql_v2.modify_search_config('users', 'name', 'match', 'int', '{"option": "value"}'::jsonb, migrating => true); ASSERT (SELECT _search_config_exists('users', 'name', 'match')); ASSERT (SELECT EXISTS (SELECT id FROM eql_v2_configuration c @@ -162,7 +162,7 @@ DO $$ BEGIN ASSERT (SELECT _search_config_exists('users', 'blah', 'match', 'active')); - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); -- index added to name ASSERT (SELECT _search_config_exists('users', 'name', 'match' )); @@ -205,7 +205,7 @@ DO $$ -- reset the table PERFORM create_table_with_encrypted(); - PERFORM eql_v2.add_column('encrypted', 'e'); + PERFORM eql_v2.add_column('encrypted', 'e', migrating => true); PERFORM assert_count( 'Pending configuration was created', @@ -213,7 +213,7 @@ DO $$ 1); - PERFORM eql_v2.remove_column('encrypted', 'e'); + PERFORM eql_v2.remove_column('encrypted', 'e', migrating => true); PERFORM assert_no_result( 'Pending configuration was removed', diff --git a/src/config/functions.sql b/src/config/functions.sql index 491ec76..9215611 100644 --- a/src/config/functions.sql +++ b/src/config/functions.sql @@ -1,6 +1,8 @@ -- REQUIRE: src/config/types.sql -- REQUIRE: src/config/functions_private.sql --- +-- REQUIRE: src/encrypted/functions.sql + + -- Customer-facing configuration functions -- Depends on private functions for implemenation -- @@ -10,7 +12,7 @@ -- Adds an index term to the configuration -- -CREATE FUNCTION eql_v2.add_search_config(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}') +CREATE FUNCTION eql_v2.add_search_config(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}', migrating boolean DEFAULT false) RETURNS jsonb AS $$ @@ -54,6 +56,13 @@ AS $$ DO UPDATE SET data = _config; + IF NOT migrating THEN + PERFORM eql_v2.migrate_config(); + PERFORM eql_v2.activate_config(); + END IF; + + -- PERFORM eql_v2.add_encrypted_constraint(table_name, column_name); + -- exeunt RETURN _config; END; @@ -121,12 +130,12 @@ $$ LANGUAGE plpgsql; -CREATE FUNCTION eql_v2.modify_search_config(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}') +CREATE FUNCTION eql_v2.modify_search_config(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}', migrating boolean DEFAULT false) RETURNS jsonb AS $$ BEGIN PERFORM eql_v2.remove_search_config(table_name, column_name, index_name); - RETURN eql_v2.add_search_config(table_name, column_name, index_name, cast_as, opts); + RETURN eql_v2.add_search_config(table_name, column_name, index_name, cast_as, opts, migrating); END; $$ LANGUAGE plpgsql; @@ -200,7 +209,7 @@ $$ LANGUAGE plpgsql; -CREATE FUNCTION eql_v2.add_column(table_name text, column_name text, cast_as text DEFAULT 'text') +CREATE FUNCTION eql_v2.add_column(table_name text, column_name text, cast_as text DEFAULT 'text', migrating boolean DEFAULT false) RETURNS jsonb AS $$ DECLARE @@ -231,6 +240,11 @@ AS $$ DO UPDATE SET data = _config; + IF NOT migrating THEN + PERFORM eql_v2.migrate_config(); + PERFORM eql_v2.activate_config(); + END IF; + PERFORM eql_v2.add_encrypted_constraint(table_name, column_name); -- exeunt @@ -240,7 +254,7 @@ $$ LANGUAGE plpgsql; -CREATE FUNCTION eql_v2.remove_column(table_name text, column_name text) +CREATE FUNCTION eql_v2.remove_column(table_name text, column_name text, migrating boolean DEFAULT false) RETURNS jsonb AS $$ DECLARE @@ -289,6 +303,11 @@ AS $$ PERFORM eql_v2.remove_encrypted_constraint(table_name, column_name); + IF NOT migrating THEN + PERFORM eql_v2.migrate_config(); + PERFORM eql_v2.activate_config(); + END IF; + -- exeunt RETURN _config; diff --git a/src/encryptindex/functions_test.sql b/src/encryptindex/functions_test.sql index 18a77f6..9945f72 100644 --- a/src/encryptindex/functions_test.sql +++ b/src/encryptindex/functions_test.sql @@ -154,9 +154,8 @@ CREATE TABLE users -- An encrypting config should exist DO $$ BEGIN - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); PERFORM eql_v2.migrate_config(); - ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active')); ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'encrypting')); ASSERT (SELECT NOT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'pending')); @@ -164,6 +163,29 @@ DO $$ $$ LANGUAGE plpgsql; +-- Encrypting config without `migrating = true` is immediately active +DO $$ + BEGIN + TRUNCATE TABLE eql_v2_configuration; + PERFORM eql_v2.add_search_config('users', 'name', 'match'); + ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active')); + END; +$$ LANGUAGE plpgsql; + + +-- migrate_config() should raise an exception when no pending configuration exists +DO $$ + BEGIN + TRUNCATE TABLE eql_v2_configuration; + PERFORM eql_v2.add_search_config('users', 'name', 'match'); + + PERFORM assert_exception( + 'eql_v2.migrate_config() should raise an exception when no pending configuration exists', + 'SELECT eql_v2.migrate_config()' + ); + END; +$$ LANGUAGE plpgsql; + -- ----------------------------------------------- -- With existing active config and an updated schema using a raw JSONB column -- Start encryptindexing @@ -204,7 +226,7 @@ CREATE TABLE users -- An encrypting config should exist DO $$ BEGIN - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); PERFORM eql_v2.migrate_config(); ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active')); @@ -254,7 +276,7 @@ CREATE TABLE users -- An encrypting config should exist DO $$ BEGIN - PERFORM eql_v2.add_search_config('users', 'name', 'match'); + PERFORM eql_v2.add_search_config('users', 'name', 'match', migrating => true); PERFORM eql_v2.migrate_config(); -- need to encrypt first PERFORM eql_v2.activate_config();