Replies: 2 comments 3 replies
-
I got that running, but I had to manually enable the
I guess this should actually be enabled by default, because whats the sense to encrypt data if everyone can access the view? |
Beta Was this translation helpful? Give feedback.
3 replies
-
Finally achieved this (note that I'm also updating an existing table with column -- Alter table user_preferences to hold a key_id (uuid) that references pgsodium.key.id
ALTER TABLE public.user_preferences ADD COLUMN key_id uuid REFERENCES pgsodium.key(id) DEFAULT (pgsodium.create_key()).id UNIQUE;
UPDATE "public"."user_preferences"
SET "key_id" = (pgsodium.create_key()).id;
-- -- Add columns key_id (uuid) to table user_tokens
ALTER TABLE public.user_tokens ADD COLUMN key_id uuid REFERENCES user_preferences(key_id);
-- -- Add security label that encrypts
SECURITY LABEL FOR pgsodium ON COLUMN user_tokens.token IS 'ENCRYPT WITH KEY COLUMN key_id';
CREATE OR REPLACE FUNCTION public.user_tokens_encrypt_secret_token()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
-- Check if key_id is not already set, else set it to user's key_id
IF NEW.key_id IS NULL THEN
NEW.key_id := (
SELECT key_id
FROM user_preferences
WHERE user_preferences.user_id = NEW.user_id
);
END IF;
-- Encrypt the token if it's not null and key_id is not null
NEW.token := CASE
WHEN NEW.token IS NULL THEN
NULL
ELSE
CASE
WHEN NEW.key_id IS NULL THEN
NULL
ELSE
pg_catalog.encode(
pgsodium.crypto_aead_det_encrypt(
pg_catalog.convert_to(NEW.token, 'utf8'),
pg_catalog.convert_to(('')::text, 'utf8'),
NEW.key_id::uuid,
NULL
),
'base64'
)
END
END;
RETURN NEW;
END;
$function$;
CREATE OR REPLACE TRIGGER user_tokens_encrypt_secret_trigger_token
BEFORE INSERT OR UPDATE OF token ON "public"."user_tokens"
FOR EACH ROW EXECUTE FUNCTION user_tokens_encrypt_secret_token();
-- -- Set token to trigger encryption
UPDATE user_tokens SET token = token;
-- -- -- Create View of decrypted data
CREATE OR REPLACE VIEW public.decrypted_user_tokens AS
SELECT user_tokens.id,
user_tokens.created_at,
user_tokens.user_id,
user_tokens.token,
CASE
WHEN user_tokens.token IS NULL THEN NULL::text
ELSE
CASE
WHEN user_tokens.key_id IS NULL THEN NULL::text
ELSE convert_from(pgsodium.crypto_aead_det_decrypt(decode(user_tokens.token, 'base64'::text), convert_to(''::text, 'utf8'::name), user_tokens.key_id, NULL::bytea), 'utf8'::name)
END
END AS decrypted_token,
user_tokens.revoked_at,
user_tokens.scope,
user_tokens.email,
user_tokens.key_id
FROM user_tokens;
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi Supabase,
I'm currently using pgsodium for transparent column encryption and I want to combine it with row-level security based based on the
user_id
. I have a table calledsecrets
with the following schema:I've enabled row-level security on this table like this:
Now, I want to enable transparent column encryption on the
secret
column using pgsodium, but I would like the encryption to be done with a user's unique key. The corresponding key_id should be specific to each user, and I want to store it in another table (e.g.,user_preferences
).Is the best approach to have a separate function such as
create_key_for_user(user_id)
, that is then referenced like this?(I don't have access to Vault at the moment)
Appreciate some guidance—thanks!
P.S. This is a duplicate of michelp/pgsodium#79, not sure the discussions there have a lot of visibility.
Beta Was this translation helpful? Give feedback.
All reactions