@@ -238,6 +238,121 @@ anon 用法参考:
238238- [ 《PostgreSQL 敏感信息遮掩插件 anon (Anonymizer) - security label provider - anon》] ( ../201911/20191115_03.md )
239239- [ 《Anonymization & Data Masking for PostgreSQL - 自动脱敏控制 - oracle data vault - postgresql-anonymizer》] ( ../201908/20190817_03.md )
240240
241+
242+ ` git clone --depth 1 https://gitlab.com/dalibo/postgresql_anonymizer/ `
243+
244+ security label的实现逻辑如下:
245+
246+ ![ pic] ( 20230707_01_pic_001.jpg )
247+
248+ security label的实现核心是通过钩子加入一些执行代码, 例如将原始值进行修改, 限制权限等.
249+
250+ 以anon插件为例.
251+
252+ 使用` _PG_init ` 注册了几个钩子函数, 在parser analyze产生raw query tree后植入代码逻辑. 在ProcessUtility (也就是ddl, dcl等语句)后执行代码逻辑.
253+
254+
255+ ```
256+ /*
257+ * Register the extension and declare its GUC variables
258+ */
259+ void
260+ _PG_init(void)
261+ {
262+
263+ ...
264+
265+ /* Install the hooks */
266+ prev_post_parse_analyze_hook = post_parse_analyze_hook;
267+ post_parse_analyze_hook = pa_post_parse_analyze_hook;
268+
269+ prev_ProcessUtility_hook = ProcessUtility_hook;
270+ ProcessUtility_hook = pa_ProcessUtility_hook;
271+
272+
273+
274+
275+
276+ /* Hook for plugins to get control at end of parse analysis */
277+ typedef void (*post_parse_analyze_hook_type) (ParseState *pstate,
278+ Query *query,
279+ JumbleState *jstate);
280+
281+
282+ /* Hook for plugins to get control in ProcessUtility() */
283+ typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
284+ const char *queryString,
285+ bool readOnlyTree,
286+ ProcessUtilityContext context,
287+ ParamListInfo params,
288+ QueryEnvironment *queryEnv,
289+ DestReceiver *dest, QueryCompletion *qc);
290+ ```
291+
292+ anon pa_post_parse_analyze_hook钩子的逻辑:
293+
294+ ```
295+ /*
296+ * Post-parse-analysis hook: mask query
297+ * https://github.com/taminomara/psql-hooks/blob/master/Detailed.md#post_parse_analyze_hook
298+ */
299+ static void
300+ #if PG_VERSION_NUM >= 140000
301+ pa_post_parse_analyze_hook(ParseState *pstate, Query *query, JumbleState *jstate)
302+ #else
303+ pa_post_parse_analyze_hook(ParseState *pstate, Query *query)
304+ #endif
305+ {
306+ char * policy = NULL;
307+
308+ if (prev_post_parse_analyze_hook)
309+ #if PG_VERSION_NUM >= 140000
310+ prev_post_parse_analyze_hook(pstate, query, jstate);
311+ #else
312+ prev_post_parse_analyze_hook(pstate, query);
313+ #endif
314+
315+ if (!IsTransactionState()) return;
316+ if (!guc_anon_transparent_dynamic_masking) return;
317+
318+ policy = pa_get_masking_policy(GetUserId());
319+ if (policy)
320+ pa_rewrite(query,policy);
321+
322+ return;
323+ }
324+ ```
325+
326+
327+
328+ PostgreSQL 中post_parse_analyze_hook 钩子的植入部位:
329+
330+ ```
331+ /*
332+ * parse_analyze_fixedparams
333+ * Analyze a raw parse tree and transform it to Query form.
334+ *
335+ * Optionally, information about $n parameter types can be supplied.
336+ * References to $n indexes not defined by paramTypes[] are disallowed.
337+ *
338+ * The result is a Query node. Optimizable statements require considerable
339+ * transformation, while utility-type statements are simply hung off
340+ * a dummy CMD_UTILITY Query node.
341+ */
342+ Query *
343+ parse_analyze_fixedparams(RawStmt *parseTree, const char *sourceText,
344+ const Oid *paramTypes, int numParams,
345+ QueryEnvironment *queryEnv)
346+ {
347+ .......
348+
349+ if (post_parse_analyze_hook)
350+ (*post_parse_analyze_hook) (pstate, query, jstate);
351+ ......
352+ }
353+ ```
354+
355+
241356## security label provider: sepgsql
242357
243358https://www.postgresql.org/docs/16/sepgsql.html
0 commit comments