包策略¶
简介¶
使用包策略,您可以在账户级别为 Anaconda 的第三方 Python 包设置允许列表和阻止列表。这使您可以满足更严格的审核和安全要求,并可以更精细地控制环境中哪些包可用、哪些包被阻止。
有关 Snowpark Python 如何允许您从 Anaconda 引入第三方包的更多信息,请参阅 使用第三方包。
创建 Python UDF、UDTF 或存储过程时,将在创建 Python 环境时考虑允许列表和阻止列表。允许列表和阻止列表将适用于创建 Python 环境所需的所有包。如果无法使用指定的包创建环境,查询将失败。
执行 Python UDF、UDTF 或存储过程时,Snowflake 将检查允许列表和阻止列表,并确保包策略允许所有包。否则,查询将失败。
限制¶
仅当接受 Anaconda 法律条款后,包策略才会应用。
包策略不应用于内置函数,也不应用于原生应用程序。
实施和使用包策略¶
为了创建包策略对象,必须具有以下权限:
对计划在其中创建包策略的数据库和架构的 USAGE 权限。
对计划在其中创建包策略的架构的 CREATE PACKAGES POLICY 权限。
创建包策略对象后,必须具有以下权限才能将其应用于账户:
对包策略对象的 OWNERSHIP 权限。
账户的 APPLY PACKAGES POLICY 权限。
按照以下步骤实施包策略。
第 1 步:创建包策略管理员自定义角色¶
创建一个自定义角色,允许用户创建和管理包策略。在本主题中,示例自定义角色命名为 policy_admin
,尽管该角色可以有任何合适的名称。
如果自定义角色已存在,请继续下一步。
否则,请创建 policy_admin
自定义角色。
use role useradmin;
create role policy_admin;
第 2 步:授予 policy_admin
自定义角色权限¶
如果 policy_admin
自定义角色尚不具有以下权限,请授予这些权限,如下所示:
对包含包策略的数据库和架构的 USAGE 权限。
对将会包含包策略的架构的 CREATE PACKAGES POLICY 权限。
账户的 APPLY PACKAGES POLICY 权限。
use role securityadmin;
grant usage on database yourdb to role policy_admin;
grant usage, create packages policy on schema yourdb.yourschema to role policy_admin;
grant apply packages policy on account to role policy_admin;
第 3 步:创建新的包策略¶
使用 policy_admin
自定义角色,创建一个新的包策略,并指定语言、允许列表和阻止列表。ALLOWLIST、BLOCKLIST、ADDITIONAL_CREATION_BLOCKLIST 和 COMMENT 是可选参数。默认情况下,允许列表值为 ('*')
,而阻止列表值为 ()
。
如果在允许列表和阻止列表中都指定了某个包,则阻止列表优先。必须明确将 Python 运行时版本添加到允许列表中,还必须明确将父包的所有包和底层依赖项添加到允许列表中。
可以在允许列表或阻止列表中使用这些版本说明符来指定特定的包版本或版本范围:==
、<=
, >=
、<
,or >
。例如 numpy>=1.2.3
。可以使用通配符,例如 numpy==1.2.*
,这意味着 numpy 1.2 的任何微版本。
备注
目前,在允许列表或阻止列表中,每个包只能指定一个范围运算符。不支持指定多个范围运算符,例如 pkg>1.0, <1.5
. Because of this, to configure a policy to allow an interval of a package version, set one side of the range in the allowlist and the other side of the range in the blocklist. For example, to allow package versions greater than 1.0 and less than 1.5, set the allowlist to pkg>1.0
并将阻止列表设置为 pkg>1.5
。
USE ROLE policy_admin;
CREATE PACKAGES POLICY yourdb.yourschema.packages_policy_prod_1
LANGUAGE PYTHON
ALLOWLIST = ('numpy', 'pandas==1.2.3', ...)
BLOCKLIST = ('numpy==1.2.3', 'bad_package', ...)
ADDITIONAL_CREATION_BLOCKLIST = ('bad_package2', 'bad_package3', ...)
COMMENT = 'Packages policy for the prod_1 environment'
;
其中:
yourdb.yourschema.packages_policy_prod_1
包策略的完全限定名称。
LANGUAGE PYTHON
此包策略将应用于哪种语言。
ALLOWLIST = ('numpy', 'pandas==1.2.3', ...)
此包策略的允许列表。这是一个带有包规范的逗号分隔字符串。
BLOCKLIST = ('numpy==1.2.3', 'bad_package', ...)
此包策略的阻止列表。这是一个带有包规范的逗号分隔字符串。
ADDITIONAL_CREATION_BLOCKLIST = ('bad_package2', 'bad_package3', ...)
指定在创建时被阻止的包规范列表。若要取消设置此参数,请指定一个空列表。如果设置了
ADDITIONAL_CREATION_BLOCKLIST
,则它会在创建时追加到基本 BLOCKLIST。对于临时 UDFs 和匿名存储过程,ADDITIONAL_CREATION_BLOCKLIST
在创建和执行时都会追加到BLOCKLIST
。COMMENT = 'Packages policy for the prod_1 environment'
指定包策略目的的注释。
在上面的例子中,创建时应用的阻止列表将是 ADDITIONAL_CREATION_BLOCKLIST
加上 BLOCKLIST
,因此被阻止的包将是 numpy==1.2.3
、bad_package
、bad_package2
和 bad_package3
。执行时应用的组织列表将是:numpy==1.2.3
和 bad_package
。对于临时 UDFs 和匿名存储过程,包含 numpy==1.2.3
、bad_package
、bad_package2
和 bad_package3
的阻止列表将在创建和执行时应用。
要获取 Python 包的依赖项列表,请使用 SHOW_PYTHON_PACKAGES_DEPENDENCIES 函数。第一个参数是正在使用的 Python 运行时版本,第二个参数是显示依赖项的包的列表。例如,要显示 numpy
包的依赖项,请使用此命令。
USE ROLE ACCOUNTADMIN;
select SNOWFLAKE.SNOWPARK.SHOW_PYTHON_PACKAGES_DEPENDENCIES('3.8', ['numpy']);
结果是依赖项及其版本的列表。
['_libgcc_mutex==0.1', '_openmp_mutex==5.1', 'blas==1.0', 'ca-certificates==2023.05.30', 'intel-openmp==2021.4.0',
'ld_impl_linux-64==2.38', 'ld_impl_linux-aarch64==2.38', 'libffi==3.4.4', 'libgcc-ng==11.2.0', 'libgfortran-ng==11.2.0',
'libgfortran5==11.2.0', 'libgomp==11.2.0', 'libopenblas==0.3.21', 'libstdcxx-ng==11.2.0', 'mkl-service==2.4.0',
'mkl==2021.4.0', 'mkl_fft==1.3.1', 'mkl_random==1.2.2', 'ncurses==6.4', 'numpy-base==1.24.3', 'numpy==1.24.3',
'openssl==3.0.10', 'python==3.8.16', 'readline==8.2', 'six==1.16.0', 'sqlite==3.41.2', 'tk==8.6.12', 'xz==5.4.2', 'zlib==1.2.13']
要显示 Snowpark 环境中 Python 3.8 的依赖项,请调用该函数而不指定任何包。
select SNOWFLAKE.SNOWPARK.SHOW_PYTHON_PACKAGES_DEPENDENCIES('3.8', []);
如果想知道某个函数正在使用哪些包,可以使用 DESCRIBE FUNCTION 将其打印出来。这是识别包的所有依赖项的另一种方法。为此,创建一个函数并在包规范中提供顶级包。接下来,使用 DESCRIBE FUNCTION 获取所有包及其依赖项的列表。可以将此列表复制并粘贴到包允许列表中。请注意,必须暂时取消设置包策略,否则某些包可能会被阻止。以下示例显示如何查找“snowflake-snowpark-python”包的依赖项。
create or replace function my_udf()
returns string
language python
packages=('snowflake-snowpark-python')
runtime_version=3.10
handler='echo'
as $$
def echo():
return 'hi'
$$;
describe function my_udf();
如果要显示所有可用的包和版本,请查询 INFORMATION_SCHEMA.PACKAGES 视图。
select * from information_schema.packages;
如果想查看当前正在使用的包集,可以使用这个 SQL 语句。
-- at the database level
CREATE OR REPLACE VIEW USED_ANACONDA_PACKAGES
ASSELECT FUNCTION_NAME, VALUE PACKAGE_NAME
FROM (SELECT FUNCTION_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM INFORMATION_SCHEMA.FUNCTIONS
WHERE FUNCTION_LANGUAGE='PYTHON') USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES);
-- at the account level
CREATE OR REPLACE VIEW ACCOUNT_USED_ANACONDA_PACKAGES
AS SELECT FUNCTION_CATALOG, FUNCTION_SCHEMA, FUNCTION_NAME, VALUE PACKAGE_NAME
FROM (SELECT FUNCTION_CATALOG, FUNCTION_SCHEMA, FUNCTION_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM SNOWFLAKE.ACCOUNT_USAGE.FUNCTIONS
WHERE FUNCTION_LANGUAGE='PYTHON') USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES);
要获取 Anaconda 提供的第三方包的列表,请使用 GET_ANACONDA_PACKAGES_REPODATA 函数。参数是架构,可以是:linux-64
、linux-aarch64
、osx-64
、osx-arm64
、win-64
或 noarch
。
例如,要显示 Anaconda 中针对 linux-64
架构的第三方包列表,请使用此命令。
USE ROLE ACCOUNTADMIN;
select SNOWFLAKE.SNOWPARK.GET_ANACONDA_PACKAGES_REPODATA('linux-64');
第 4 步:设置账户的包策略¶
使用 policy_admin
自定义角色,通过 ALTER ACCOUNT 命令设置账户的策略。
use role policy_admin;
alter account set packages policy yourdb.yourschema.packages_policy_prod_1;
备注
要替换已为账户设置的包策略,请先取消设置包策略,然后为该账户设置新的包策略。或者,可以使用 FORCE 设置包策略,而不必取消设置包策略。例如:
alter account set packages policy yourdb.yourschema.packages_policy_prod_2 force;
如果想查看账户有哪些策略有效,可以使用这个 SQL 语句。
select * from table(information_schema.policy_references(ref_entity_domain=>'ACCOUNT', ref_entity_name=>'<your_account_name>'))
此查询的结果将显示名为 POLICY_STATUS
的列。
稍后,如果您想取消在账户上设置包策略,请使用此 SQL 语句。
alter account unset packages policy;
执行 DDL 命令所需的权限¶
下表总结了包策略 DDL 操作及其所需权限之间的关系。
操作 |
需要权限 |
---|---|
创建包策略 |
具有架构 CREATE PACKAGES POLICY 权限的角色。 |
修改包策略 |
对包策略具有 OWNERSHIP 权限的角色。 |
弃用包策略 |
对包策略具有 OWNERSHIP 权限的角色。 |
描述包策略 |
对包策略具有 OWNERSHIP 或 USAGE 权限的角色。 |
显示包策略 |
对包策略具有 OWNERSHIP 或 USAGE 权限的角色。 |
设置和取消设置包策略 |
对账户具有 APPLY PACKAGES POLICY 权限而且对包策略具有 OWNERSHIP 权限的角色。 |
包策略 DDL¶
Snowflake 提供以下 DDL 命令来管理包策略对象:
包策略可观测性¶
无权访问对账户设置的包策略的用户也可以看到其内容。
通过向包策略添加 USAGE 权限,用户可以控制谁可以查看包策略的内容。账户管理员或包策略所有者可以将此权限授予需要使用包策略的角色。
GRANT USAGE ON PACKAGES POLICY <packages policy name> TO ROLE <user role>;
CURRENT_PACKAGES_POLICY Information Schema 视图为当前账户中的每个 Snowpark 包策略显示一行。
select * from information_schema.current_packages_policy;
+------+----------+-----------+-----------+-------------------------------+---------+
| NAME | LANGUAGE | ALLOWLIST | BLOCKLIST | ADDITIONAL_CREATION_BLOCKLIST | COMMENT |
+------+----------+-----------+-----------+-------------------------------+---------+
| P1 | PYTHON | ['*'] | [] | [NULL] | [NULL] |
+------+----------+-----------+-----------+-------------------------------+---------+
要查看在数据库级别用于函数的 Anaconda 包,请使用此 SQL 语句。
USE DATABASE mydb;
CREATE OR REPLACE VIEW USED_ANACONDA_PACKAGES
AS
SELECT FUNCTION_NAME, VALUE PACKAGE_NAME
FROM (SELECT FUNCTION_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM INFORMATION_SCHEMA.FUNCTIONS
WHERE FUNCTION_LANGUAGE='PYTHON') USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES);
要查看在账户级别用于函数的 Anaconda 包,请使用此 SQL 语句。
USE DATABASE mydb;
CREATE OR REPLACE VIEW ACCOUNT_USED_ANACONDA_PACKAGES
AS
SELECT FUNCTION_CATALOG, FUNCTION_SCHEMA, FUNCTION_NAME, VALUE PACKAGE_NAME
FROM (SELECT FUNCTION_CATALOG, FUNCTION_SCHEMA, FUNCTION_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM SNOWFLAKE.ACCOUNT_USAGE.FUNCTIONS
WHERE FUNCTION_LANGUAGE='PYTHON') USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES);
要查看您账户中安装的所有 Anaconda 软件包,请使用此 SQL 语句。
USE DATABASE mydb;
CREATE OR REPLACE VIEW ACCOUNT_USED_ANACONDA_PACKAGES
AS
SELECT 'FUNCTION' TYPE, FUNCTION_CATALOG DATABASE, FUNCTION_SCHEMA SCHEMA, FUNCTION_NAME NAME, VALUE::STRING PACKAGE_NAME
FROM (SELECT FUNCTION_CATALOG, FUNCTION_SCHEMA, FUNCTION_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM SNOWFLAKE.ACCOUNT_USAGE.FUNCTIONS
WHERE FUNCTION_LANGUAGE='PYTHON' AND PACKAGES IS NOT NULL) USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES)
UNION
(SELECT 'PROCEDURE' TYPE, PROCEDURE_CATALOG DATABASE, PROCEDURE_SCHEMA SCHEMA, PROCEDURE_NAME, VALUE::STRING PACKAGE_NAME
FROM (SELECT PROCEDURE_CATALOG, PROCEDURE_SCHEMA,PROCEDURE_NAME,PARSE_JSON(PACKAGES)
PACKAGES FROM SNOWFLAKE.ACCOUNT_USAGE.PROCEDURES
WHERE PROCEDURE_LANGUAGE='PYTHON' AND PACKAGES IS NOT NULL) USED_PACKAGES,LATERAL FLATTEN(USED_PACKAGES.PACKAGES));