# 8.4 The Manager's Override (Security Definers) ![The Manager's Override](assets/arch_access_security_definer.png) We have a perfectly secure Cafe. The `secrets` table is protected by a Bouncer (Row-Level Security), ensuring the `cafe_waiter` can never read the `cafe_manager`'s safe code. But what if the Waiter *needs* to perform an auditing task that requires reading all the secrets? We don't want to make the Waiter a permanent Manager—that's too dangerous. We need to grant them **temporary, delegated authority**. ## The Magical Stamp (Security Definer) Postgres allows functions to be defined as `SECURITY DEFINER`. This is like a **Magical Stamp** given to the Waiter by the Manager. Normally, when you run a function (`SECURITY INVOKER`), the Elephant asks, "Who is running this?" With a `SECURITY DEFINER` function, the Elephant asks, "Who *created* this stamp?" Let's log in as the `postgres` Superuser (the highest level Manager) and create a stamp for the Waiters. ```sql -- Creating the Magical Stamp CREATE OR REPLACE FUNCTION read_all_secrets() RETURNS SETOF secrets AS $ SELECT * FROM secrets; $ LANGUAGE sql SECURITY DEFINER SET search_path = public; -- Revoke it from the general public, and give it ONLY to the waiters REVoke ALL ON FUNCTION read_all_secrets() FROM PUBLIC; GRANT EXECUTE ON FUNCTION read_all_secrets() TO cafe_waiter; ``` ## Using the Stamp Now, let's watch what happens when the lowly Waiter tries to read the `secrets` table directly versus using the Magical Stamp. ```sql SET ROLE cafe_waiter; -- Normal Read (Bouncer blocks the view) SELECT * FROM secrets; -- Literal Output: -- id | owner | secret -- ---+-------------+-------------------------- -- 2 | cafe_waiter | The Chef burned the toast -- Using the Stamp (Bouncer steps aside) SELECT * FROM read_all_secrets(); -- Literal Output: -- id | owner | secret -- ---+--------------+--------------------------- -- 1 | cafe_manager | The safe code is 555-1234 -- 2 | cafe_waiter | The Chef burned the toast ``` When the `read_all_secrets()` function runs, the Elephant temporarily treats the Waiter as if they were the `postgres` superuser! They bypass RLS entirely. As soon as the function ends, the magic wears off, and they are a lowly Waiter again. > [!WARNING] The `search_path` Trap > Never hand out a Magical Stamp without explicitly setting the `search_path` (as we did with `SET search_path = public`). If you don't map out exactly what ledger the stamp applies to, a malicious Waiter could create a fake `secrets` table in their own private schema, tricking the Manager's stamp into reading the wrong data! --- [[Chapter 8/8.3 - The VIP List (Row-Level Security)|← 8.3 - The VIP List]] | [[Chapter 8/8.0 - The Bouncers and the VIP List|↑ 8.0 - The Bouncers]] | [[Chapter 9/9.0 - The End|9.0 - The End →]]