检查 REST 目录配置

您可以使用以下场景来检查是否为 Iceberg REST 目录正确配置了授权和访问控制,以便 Snowflake 可以与目录服务器进行交互。

使用 SYSTEM$VERIFY_CATALOG_INTEGRATION

You can use the SYSTEM$VERIFY_CATALOG_INTEGRATION function to check your catalog integration configuration.

以下示例演示了系统函数如何捕获和报告目录集成配置不当的问题。

The following example statement creates a REST catalog integration using an invalid OAuth client secret (this runs without error):

CREATE CATALOG INTEGRATION my_rest_cat_int
  CATALOG_SOURCE = ICEBERG_REST
  TABLE_FORMAT = ICEBERG
  CATALOG_NAMESPACE = 'default'
  REST_CONFIG = (
    CATALOG_URI = 'https://abc123.us-west-2.aws.myapi.com/polaris/api/catalog'
    CATALOG_NAME = 'my_catalog_name'
  )
  REST_AUTHENTICATION = (
    TYPE = OAUTH
    OAUTH_CLIENT_ID = '123AbC ...'
    OAUTH_CLIENT_SECRET = '1365910abIncorrectSecret ...'
    OAUTH_ALLOWED_SCOPES = ('all-apis', 'sql')
  )
  ENABLED = TRUE;

Use the system function to verify the catalog integration, expecting failure:

SELECT SYSTEM$VERIFY_CATALOG_INTEGRATION('my_rest_cat_int');

Output:

+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                                                              SYSTEM$VERIFY_CATALOG_INTEGRATION('MY_REST_CAT_INT')                                                                                                               |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {                                                                                                                                                                                                                                                                               |
|  "success" : false,                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                                                                    |
|   "errorCode" : "004155",                                                                                                                                                                                                                                                       |
|   "errorMessage" : "SQL Execution Error: Failed to perform OAuth client credential flow for the REST Catalog integration MY_REST_CAT_INT due to error: SQL execution error: OAuth2 Access token request failed with error 'unauthorized_client:The client is not authorized'.." |
| }                                                                                                                                                                                                                                                                               |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

检查 OAuth 的配置

按照以下步骤使用远程 REST 目录检查 OAuth 的配置。

第 1 步:检索访问令牌

Use a curl command to retrieve an access token from your catalog. The following example requests an access token from Snowflake Open Catalog:

curl -X POST https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/oauth/tokens \
    -H "Accepts: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    --data-urlencode "grant_type=client_credentials" \
    --data-urlencode "scope=PRINCIPAL_ROLE:ALL" \
    --data-urlencode "client_id=<my_client_id>" \
    --data-urlencode "client_secret=<my_client_secret>" | jq

其中:

  • https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/oauth/tokens is the endpoint for retrieving an OAuth token (getToken (https://github.com/apache/iceberg/blob/apache-iceberg-1.6.1/open-api/rest-catalog-open-api.yaml#L132)).
  • scope is the same as the value that you specify for OAUTH_ALLOWED_SCOPES parameter when you create a catalog integration. For multiple scopes, use a space as a separator.
  • my_client_id is the same client ID that you specify for the OAUTH_CLIENT_ID parameter when you create a catalog integration.
  • my_client_secret is the same client secret that you specify for the OAUTH_CLIENT_SECRET parameter when you create a catalog integration.

返回值示例:

{
  "access_token": "xxxxxxxxxxxxxxxx",
  "token_type": "bearer",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "expires_in": 3600
}

第 2 步:验证访问令牌权限

使用在上一步中检索到的访问令牌,验证自己是否拥有访问目录服务器的权限。

You can use a curl command to list the configuration settings for your catalog:

curl -X GET "https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/config?warehouse=<warehouse>" \
    -H "Accepts: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq

其中:

  • ?warehouse=warehouse optionally specifies the warehouse name to request from your catalog (if supported). For Snowflake Open Catalog, the warehouse name is your catalog name.
  • ACCESS_TOKEN is a variable that contains the access_token that you retrieved in the previous step.

返回值示例:

{
  "defaults": {
    "default-base-location": "s3china://my-bucket/polaris/"
  },
  "overrides": {
    "prefix": "my-catalog"
  }
}

第 3 步:从目录中加载表

You can also make a GET request to load a table. Snowflake uses the loadTable (https://github.com/apache/iceberg/blob/apache-iceberg-1.6.1/open-api/rest-catalog-open-api.yaml#L616) operation to load table data from your REST catalog.

curl -X GET "https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/<prefix>/namespaces/<namespace>/tables/<table>" \
    -H "Accepts: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq

其中:

  • prefix optionally specifies the prefix obtained from the previous getConfig response.
  • namespace is the namespace of the table you want to retrieve. If the namespace is nested, use the %1F separator; for example, parentNamespace%1FchildNamespace.
  • table is the table name.

检查持有者令牌的配置

按照以下步骤在远程 REST 目录中检查使用持有者令牌的配置。

第 1 步:验证访问令牌权限

Use a curl command to verify that you have permission to access your catalog server:

curl -X GET "https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/config?warehouse=<warehouse>" \
    -H "Accepts: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: Bearer ${BEARER_TOKEN}" | jq

其中:

返回值示例:

{
  "defaults": {
    "default-base-location": "s3china://my-bucket/polaris"
  },
  "overrides": {
    "prefix": "my-catalog"
  }
}

第 2 步:从目录中加载表

You can also make a GET request to load a table. Snowflake uses the loadTable (https://github.com/apache/iceberg/blob/apache-iceberg-1.6.1/open-api/rest-catalog-open-api.yaml#L616) operation to load table data from your REST catalog.

curl -X GET "https://xx123xx.us-west-2.aws.snowflakecomputing.cn/polaris/api/catalog/v1/<prefix>/namespaces/<namespace>/tables/<table>" \
    -H "Accepts: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: Bearer ${BEARER_TOKEN}" | jq

其中:

  • prefix optionally specifies the prefix obtained from the previous getConfig response.
  • namespace is the namespace of the table you want to retrieve. If the namespace is nested, use the %1F separator; for example, parentNamespace%1FchildNamespace.
  • table is the table name.

检查 SigV4 的配置

按照以下步骤通过 AWS 检查 SigV4 的配置。

第 1 步:将用户添加到 IAM 角色信任关系中

When you create a REST catalog integration for SigV4, Snowflake provisions an AWS IAM user for your Snowflake account. You add that Snowflake IAM user to the trust relationship for an IAM role with permission to access your API Gateway resources.

To test your configuration, you can assume the role as a user in your AWS account after you add your AWS user to the role’s trust policy document. To retrieve your current IAM user ARN, use the sts get-caller-identity (https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/get-caller-identity.html) command for the AWS Command Line Interface (CLI) (https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) :

aws sts get-caller-identity

输出示例:

{
  "UserId": "ABCDEFG1XXXXXXXXXXX",
  "Account": "123456789XXX",
  "Arn": "arn:aws:iam::123456789XXX:user/managed/my_user"
}

更新后的信任策略文档应包括 Snowflake 用户 ARN 和用户 ARN,具体如下:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "<snowflake_iam_user_arn>",
          "<my_iam_user_arn>"
        ]
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "my_external_id"
        }
      }
    }
  ]
}

For full instructions, see Update a role trust policy (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-trust-policy.html) in the AWS IAM documentation.

第 2 步:假设 IAM 角色以获取临时凭证

To get temporary security credentials for AWS, use the sts assume-role (https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/assume-role.html) command for the AWS CLI.

aws sts assume-role \
  --role-arn <my_role_arn> \
  --role-session-name <session_name>

其中:

  • my_role_arn is the Amazon Resource Name (ARN) of the IAM role that you’ve configured for Snowflake.
  • session_name is a string identifier of your choice for the assumed role session; for example, my_rest_session.

输出示例:

{
  "Credentials": {
      "AccessKeyId": "XXXXXXXXXXXXXXXXXXXXX",
      "SecretAccessKey": "XXXXXXXXXXXXXXXXXXXXX",
      "SessionToken": "XXXXXXXXXXXXXXXXXXXXX",
      "Expiration": "2024-10-09T08:13:15+00:00"
  },
  "AssumedRoleUser": {
      "AssumedRoleId": "{AccessKeyId}:my_rest_catalog_session",
      "Arn": "arn:aws:sts::123456789XXX:assumed-role/my_catalog_role/my_rest_catalog_session"
  }
}

Note

If the assume-role command fails, it means that your current AWS user isn’t included in the role’s trust policy as an allowed principal.

Similarly, if the Snowflake IAM user ARN isn’t included in your trust policy, Snowflake won’t be able to connect to your API Gateway resources. For more information, see Configure the trust relationship in IAM.

第 3 步:确认 IAM 角色是否拥有正确的权限

使用在上一步中检索到的临时凭证,验证 IAM 角色是否拥有调用 API Gateway APIs 的权限。

You can use a curl command to list the configuration settings for your catalog:

curl -v -X GET  "https://123xxxxxxx.execute-api.us-west-2.amazonaws.com/test_v2/v1/config?warehouse=<warehouse>" \
  --user "$AWS_ACCESS_KEY_ID":"$AWS_SECRET_ACCESS_KEY" \
  --aws-sigv4 "aws:amz:us-west-2:execute-api" \
  -H "x-amz-security-token: $AWS_SESSION_TOKEN"

其中:

  • 123xxxxxxx.execute-api.us-west-2.amazonaws.com is your API Gateway hostname.
  • test_v2 is the name of the stage that your API is deployed to.
  • v1/config specifies the getConfig (https://github.com/apache/iceberg/blob/apache-iceberg-1.6.1/open-api/rest-catalog-open-api.yaml#L65) operation from the Iceberg catalog OpenAPI definition.
  • ?warehouse=warehouse optionally specifies the warehouse name to request from your catalog (if supported).
  • $AWS_ACCESS_KEY_ID is a variable that contains the AccessKeyId that you retrieved using the sts assume-role command.
  • $AWS_SECRET_ACCESS_KEY is a variable that contains the SecretAccessKey that you retrieved using the sts assume-role command.
  • aws:amz:us-west-2:execute-api is the signing name of the SigV4 protocol. For AWS Glue, use aws:amz:us-west-2:glue instead.
  • $AWS_SESSION_TOKEN is a variable that contains the SessionToken that you retrieved using the sts assume-role command.

返回值示例:

{
  "defaults": {},
  "overrides": {
    "prefix": "my-catalog"
  }
}

You can also make a GET request to load a table. Snowflake uses the loadTable (https://github.com/apache/iceberg/blob/apache-iceberg-1.6.1/open-api/rest-catalog-open-api.yaml#L616) operation to load table data from your REST catalog.

curl -v -X GET "https://123xxxxxxx.execute-api.us-west-2.amazonaws.com/test_v2/v1/<prefix>/namespaces/<namespace>/tables/<table>" \
    --user "$AWS_ACCESS_KEY_ID":"$AWS_SECRET_ACCESS_KEY" \
    --aws-sigv4 "aws:amz:us-west-2:execute-api" \
    -H "x-amz-security-token: $AWS_SESSION_TOKEN"

其中:

  • prefix optionally specifies the prefix obtained from the previous getConfig response.
  • namespace is the namespace of the table you want to retrieve. If the namespace is nested, use the %1F separator; for example, parentNamespace%1FchildNamespace.
  • table is the table name.

专用 API

For a private API, you can specify your VPC endpoint and private Amazon API Gateway hostname in the same curl commands.

例如:

curl -v -X GET  "https://vpce-xxxxxxxxxxxxxxxxxxxxxxxxxx.execute-api.us-west-2.vpce.amazonaws.com/test_v2/v1/config?warehouse=<warehouse>" \
  --user "$AWS_ACCESS_KEY_ID":"$AWS_SECRET_ACCESS_KEY" \
  --aws-sigv4 "aws:amz:us-west-2:execute-api" \
  -H "x-amz-security-token: $AWS_SESSION_TOKEN"
  -H "Host: abc1defgh2.execute-api.us-west-2.amazonaws.com"

其中:

  • https://vpce-xxxxxxxxxxxxxxxxxxxxxxxxxx.execute-api.us-west-2.vpce.amazonaws.com/... is the hostname of your VPC endpoint.
  • abc1defgh2.execute-api.us-west-2.amazonaws.com is the hostname of your private API in Amazon API Gateway.