-- Copyright Materialize, Inc. and contributors. All rights reserved. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License in the LICENSE file at the -- root of this repository, or online at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- The deployment user must be a superuser OR -- -- Have CREATE and USAGE rights on the database -- Have CREATECLUSTER rights -- Have OWNERSHIP rights on the production clusters and schemas {% macro deploy_validate_permissions(clusters=[], schemas=[]) %} {% set is_super_user %} SELECT mz_is_superuser(); {% endset %} {% set super_user = run_query(is_super_user) %} {% if execute %} {% if not super_user.rows[0][0] %} {{ internal_ensure_database_permission() }} {{ internal_ensure_createcluster_permission() }} {{ internal_ensure_schema_ownership(schemas) }} {{ internal_ensure_cluster_ownership(clusters) }} {% endif %} {% endif %} {% endmacro %} {% macro internal_ensure_database_permission() %} {% set database_permissions %} WITH create_permission AS ( SELECT count(*) = 0 AS missing_create FROM mz_internal.mz_show_my_database_privileges WHERE privilege_type = 'CREATE' AND name = current_database() ), usage_permission AS ( SELECT count(*) = 0 AS missing_usage FROM mz_internal.mz_show_my_database_privileges WHERE privilege_type = 'USAGE' AND name = current_database() ) SELECT missing_create, missing_usage, quote_ident(current_role), current_database() FROM create_permission, usage_permission; {% endset %} {% set database_check = run_query(database_permissions) %} {% if execute %} {% if database_check.rows[0][0] or database_check[0][1] %} {{ exceptions.raise_compiler_error(""" Missing necessary permissions to execute a deployment. The current role """ ~ database_check.rows[0][2] ~ """ needs CREATE and USAGE privileges on database """ ~ database_check.rows[0][3] ~ """. Hint: `GRANT USAGE, CREATE ON DATABASE """ ~ database_check.rows[0][2] ~ """ TO """ ~ database_check.rows[0][3] ~ """;` """) }} {% endif %} {% endif %} {% endmacro %} {% macro internal_ensure_createcluster_permission() %} {% set has_create_cluster = run_query("SELECT has_system_privilege('CREATECLUSTER') IS FALSE, current_user()") %} {% if execute %} {% if has_create_cluster.rows[0][0] %} {{ exceptions.raise_compiler_error(""" Missing necessary permissions to execute a deployment. The current role """ ~ has_create_cluster.rows[0][1] ~ """ needs CREATECLUSTER privlidges. Hint: `GRANT CREATECLUSTER ON SYSTEM TO """ ~ has_create_cluster.rows[0][1] ~ """;` """) }} {% endif %} {% endif %} {% endmacro %} {% macro internal_ensure_cluster_ownership(clusters=[]) %} {% set has_cluster_ownership %} WITH clusters_under_deployment AS ( SELECT name, owner_id FROM mz_clusters WHERE name IN ( {% if clusters|length > 0 %} {% for cluster in clusters %} {% set origin_cluster = adapter.generate_final_cluster_name(cluster, force_deploy_suffix=False) %} {{ dbt.string_literal(origin_cluster) }}{% if not loop.last %},{% endif %} {% endfor %} {% else %} NULL {% endif %} ) ), cluster_with_ownership AS ( SELECT c.name FROM clusters_under_deployment c INNER JOIN mz_roles ON c.owner_id = mz_roles.id WHERE mz_roles.name = current_role ), missing_ownership AS ( SELECT name FROM cluster_with_ownership EXCEPT SELECT name FROM clusters_under_deployment ) SELECT name, quote_ident(current_role) FROM missing_ownership {% endset %} {% set cluster_ownership = run_query(has_cluster_ownership) %} {% if execute %} {% if cluster_ownership|length > 0 %} {{ exceptions.raise_compiler_error(""" Missing necessary permissions to execute a deployment. The current role """ ~ cluster_ownership.rows[0][1] ~ """ needs to be an owner of cluster """ ~ cluster_ownership.rows[0][0] ~ """. Hint: `ALTER CLUSTER """ ~ cluster_ownership.rows[0][0] ~ """ OWNER TO """ ~ cluster_ownership.rows[0][1] ~ """;` """)}} {% endif %} {% endif %} {% endmacro %} {% macro internal_ensure_schema_ownership(schemas=[]) %} {% set has_schema_ownership %} WITH schemas_under_deployment AS ( SELECT mz_schemas.* FROM mz_schemas JOIN mz_databases ON mz_schemas.database_id = mz_databases.id WHERE mz_databases.name = current_database() AND mz_schemas.name IN ( {% if schemas|length > 0 %} {% for schema in schemas %} {{ dbt.string_literal(schema) }}{% if not loop.last %},{% endif %} {% endfor %} {% else %} NULL {% endif %} ) ), schemas_with_ownership AS ( SELECT s.name FROM schemas_under_deployment s INNER JOIN mz_roles ON s.owner_id = mz_roles.id WHERE mz_roles.name = current_role ), missing_ownership AS ( SELECT name FROM schemas_with_ownership EXCEPT SELECT name FROM schemas_under_deployment ) SELECT name, quote_ident(current_role) FROM missing_ownership {% endset %} {% set schema_ownership = run_query(has_schema_ownership) %} {% if execute %} {% if schema_ownership|length > 0 %} {{ exceptions.raise_compiler_error(""" Missing necessary permissions to execute a deployment. The current role """ ~ schema_ownership.rows[0][1] ~ """ needs to be an owner of cluster """ ~ schema_ownership.rows[0][0] ~ """. Hint: `ALTER SCHEMA """ ~ schema_ownership.rows[0][0] ~ """ OWNER TO """ ~ schema_ownership.rows[0][1] ~ """;` """)}} {% endif %} {% endif %} {% endmacro %}