deploy_permission_validation.sql 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. -- Copyright Materialize, Inc. and contributors. All rights reserved.
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License in the LICENSE file at the
  6. -- root of this repository, or online at
  7. --
  8. -- http://www.apache.org/licenses/LICENSE-2.0
  9. --
  10. -- Unless required by applicable law or agreed to in writing, software
  11. -- distributed under the License is distributed on an "AS IS" BASIS,
  12. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. -- See the License for the specific language governing permissions and
  14. -- limitations under the License.
  15. -- The deployment user must be a superuser OR
  16. --
  17. -- Have CREATE and USAGE rights on the database
  18. -- Have CREATECLUSTER rights
  19. -- Have OWNERSHIP rights on the production clusters and schemas
  20. {% macro deploy_validate_permissions(clusters=[], schemas=[]) %}
  21. {% set is_super_user %}
  22. SELECT mz_is_superuser();
  23. {% endset %}
  24. {% set super_user = run_query(is_super_user) %}
  25. {% if execute %}
  26. {% if not super_user.rows[0][0] %}
  27. {{ internal_ensure_database_permission() }}
  28. {{ internal_ensure_createcluster_permission() }}
  29. {{ internal_ensure_schema_ownership(schemas) }}
  30. {{ internal_ensure_cluster_ownership(clusters) }}
  31. {% endif %}
  32. {% endif %}
  33. {% endmacro %}
  34. {% macro internal_ensure_database_permission() %}
  35. {% set database_permissions %}
  36. WITH create_permission AS (
  37. SELECT count(*) = 0 AS missing_create
  38. FROM mz_internal.mz_show_my_database_privileges
  39. WHERE privilege_type = 'CREATE' AND name = current_database()
  40. ),
  41. usage_permission AS (
  42. SELECT count(*) = 0 AS missing_usage
  43. FROM mz_internal.mz_show_my_database_privileges
  44. WHERE privilege_type = 'USAGE' AND name = current_database()
  45. )
  46. SELECT missing_create, missing_usage, quote_ident(current_role), current_database()
  47. FROM create_permission, usage_permission;
  48. {% endset %}
  49. {% set database_check = run_query(database_permissions) %}
  50. {% if execute %}
  51. {% if database_check.rows[0][0] or database_check[0][1] %}
  52. {{ exceptions.raise_compiler_error("""
  53. Missing necessary permissions to execute a deployment. The current role """ ~
  54. database_check.rows[0][2] ~ """ needs CREATE and USAGE privileges on database """ ~
  55. database_check.rows[0][3] ~ """.
  56. Hint: `GRANT USAGE, CREATE ON DATABASE """ ~ database_check.rows[0][2] ~ """ TO """ ~ database_check.rows[0][3] ~ """;`
  57. """) }}
  58. {% endif %}
  59. {% endif %}
  60. {% endmacro %}
  61. {% macro internal_ensure_createcluster_permission() %}
  62. {% set has_create_cluster = run_query("SELECT has_system_privilege('CREATECLUSTER') IS FALSE, current_user()") %}
  63. {% if execute %}
  64. {% if has_create_cluster.rows[0][0] %}
  65. {{ exceptions.raise_compiler_error("""
  66. Missing necessary permissions to execute a deployment. The current role
  67. """ ~ has_create_cluster.rows[0][1] ~ """ needs CREATECLUSTER privlidges.
  68. Hint: `GRANT CREATECLUSTER ON SYSTEM TO """ ~ has_create_cluster.rows[0][1] ~ """;`
  69. """) }}
  70. {% endif %}
  71. {% endif %}
  72. {% endmacro %}
  73. {% macro internal_ensure_cluster_ownership(clusters=[]) %}
  74. {% set has_cluster_ownership %}
  75. WITH clusters_under_deployment AS (
  76. SELECT name, owner_id FROM mz_clusters
  77. WHERE name IN (
  78. {% if clusters|length > 0 %}
  79. {% for cluster in clusters %}
  80. {% set origin_cluster = adapter.generate_final_cluster_name(cluster, force_deploy_suffix=False) %}
  81. {{ dbt.string_literal(origin_cluster) }}{% if not loop.last %},{% endif %}
  82. {% endfor %}
  83. {% else %}
  84. NULL
  85. {% endif %}
  86. )
  87. ),
  88. cluster_with_ownership AS (
  89. SELECT c.name FROM clusters_under_deployment c
  90. INNER JOIN mz_roles ON c.owner_id = mz_roles.id
  91. WHERE mz_roles.name = current_role
  92. ),
  93. missing_ownership AS (
  94. SELECT name
  95. FROM cluster_with_ownership
  96. EXCEPT
  97. SELECT name
  98. FROM clusters_under_deployment
  99. )
  100. SELECT name, quote_ident(current_role)
  101. FROM missing_ownership
  102. {% endset %}
  103. {% set cluster_ownership = run_query(has_cluster_ownership) %}
  104. {% if execute %}
  105. {% if cluster_ownership|length > 0 %}
  106. {{ exceptions.raise_compiler_error("""
  107. Missing necessary permissions to execute a deployment. The current role """
  108. ~ cluster_ownership.rows[0][1] ~ """ needs to be an owner of cluster """ ~ cluster_ownership.rows[0][0] ~ """.
  109. Hint: `ALTER CLUSTER """ ~ cluster_ownership.rows[0][0] ~ """ OWNER TO """ ~ cluster_ownership.rows[0][1] ~ """;`
  110. """)}}
  111. {% endif %}
  112. {% endif %}
  113. {% endmacro %}
  114. {% macro internal_ensure_schema_ownership(schemas=[]) %}
  115. {% set has_schema_ownership %}
  116. WITH schemas_under_deployment AS (
  117. SELECT mz_schemas.*
  118. FROM mz_schemas
  119. JOIN mz_databases ON mz_schemas.database_id = mz_databases.id
  120. WHERE mz_databases.name = current_database() AND mz_schemas.name IN (
  121. {% if schemas|length > 0 %}
  122. {% for schema in schemas %}
  123. {{ dbt.string_literal(schema) }}{% if not loop.last %},{% endif %}
  124. {% endfor %}
  125. {% else %}
  126. NULL
  127. {% endif %}
  128. )
  129. ),
  130. schemas_with_ownership AS (
  131. SELECT s.name FROM schemas_under_deployment s
  132. INNER JOIN mz_roles ON s.owner_id = mz_roles.id
  133. WHERE mz_roles.name = current_role
  134. ),
  135. missing_ownership AS (
  136. SELECT name
  137. FROM schemas_with_ownership
  138. EXCEPT
  139. SELECT name
  140. FROM schemas_under_deployment
  141. )
  142. SELECT name, quote_ident(current_role)
  143. FROM missing_ownership
  144. {% endset %}
  145. {% set schema_ownership = run_query(has_schema_ownership) %}
  146. {% if execute %}
  147. {% if schema_ownership|length > 0 %}
  148. {{ exceptions.raise_compiler_error("""
  149. Missing necessary permissions to execute a deployment. The current role """
  150. ~ schema_ownership.rows[0][1] ~ """ needs to be an owner of cluster """ ~
  151. schema_ownership.rows[0][0] ~ """.
  152. Hint: `ALTER SCHEMA """ ~ schema_ownership.rows[0][0] ~ """ OWNER TO """ ~ schema_ownership.rows[0][1] ~ """;`
  153. """)}}
  154. {% endif %}
  155. {% endif %}
  156. {% endmacro %}