如何通过dbt的on-run-end hook修复Snowflake共享权限丢失问题?
我在跨区域的两个Snowflake账户间共享并上架了一张表,定时dbt任务重建表后,共享会丢失该表的SELECT权限。于是在dbt项目中添加on-run-end钩子自动重新授权,但dbt Cloud运行时出现错误:
002003 (02000): SQL compilation error:
Share '"account_locator.PLATINUM_SNOWFLAKE_SECURE_SHARE_1234"' does not exist or not authorized.
手动用accountadmin或sa_dbtcloud身份执行GRANT SELECT ON TABLE platinum.aggregations.table TO SHARE PLATINUM_SNOWFLAKE_SECURE_SHARE_1234;可以成功,但dbt Cloud执行钩子就报错,且错误信息里的共享名被自动加上了账户定位器前缀,而钩子配置里并没有写。
当前dbt_project.yml的钩子配置:
on-run-end: - "{% if target.name | lower == 'prod' %} GRANT SELECT ON TABLE platinum.aggregations.table TO SHARE PLATINUM_SNOWFLAKE_SECURE_SHARE_1234; {% endif %}"
原因分析
dbt Cloud执行SQL时,Snowflake的会话上下文会自动给未加引号的共享名拼接账户定位器前缀,导致引用了不存在的跨账户共享(实际你的共享是当前账户内的)。
解决方法
1. 给共享名加单引号(优先推荐)
修改钩子配置,为共享名添加单引号,阻止Snowflake自动添加前缀:
on-run-end: - "{% if target.name | lower == 'prod' %} GRANT SELECT ON TABLE platinum.aggregations.table TO SHARE 'PLATINUM_SNOWFLAKE_SECURE_SHARE_1234'; {% endif %}"
这样SQL会精确指向当前账户内的目标共享,不会自动拼接额外前缀。
2. 验证dbt Cloud使用的角色权限
虽然手动执行没问题,还是要确认sa_dbtcloud角色的权限:
- 确保角色拥有
GRANT SELECT ON TABLE platinum.aggregations.table的权限 - 执行
SHOW GRANTS TO ROLE sa_dbtcloud;,检查是否包含USAGE ON SHARE PLATINUM_SNOWFLAKE_SECURE_SHARE_1234权限
3. 显式指定共享的完全限定名(备选)
如果第一种方法无效,直接写共享的完全限定名(当前账户定位器+共享名):
on-run-end: - "{% if target.name | lower == 'prod' %} GRANT SELECT ON TABLE platinum.aggregations.table TO SHARE '<你的账户定位器>.PLATINUM_SNOWFLAKE_SECURE_SHARE_1234'; {% endif %}"
把<你的账户定位器>替换成手动执行成功的那个Snowflake账户的定位器。
内容的提问来源于stack exchange,提问作者June Heath

