A Storage Integration is a Snowflake object that centrally manages authentication when Snowflake accesses external cloud storage (S3, Azure Blob, or GCS). Instead of embedding access keys and secrets directly in stage definitions, you configure access delegation to an IAM role or service principal on the cloud provider side. This removes the need to distribute and rotate long-lived keys.
When you create a Storage Integration, Snowflake internally provisions a service account specific to the cloud provider (an IAM user ARN in the case of AWS). You then configure a Trust Policy on the cloud side that allows this service account to assume the role, enabling Snowflake to access the storage securely.
| Concept | Description |
|---|---|
| Storage Integration | Account-level authentication object in Snowflake |
| STORAGE_ALLOWED_LOCATIONS | List of cloud storage paths permitted for access |
| STORAGE_BLOCKED_LOCATIONS | List of paths denied even within allowed locations |
| External Stage | Stage definition that references a Storage Integration |
| DESCRIBE INTEGRATION | Command to retrieve the IAM ARN and External ID generated by Snowflake |
┌──────────────────────┐
│ Snowflake │
│ Storage Integration │
│ (STORAGE_AWS_IAM_ │
│ USER_ARN を保持) │
└────────┬─────────────┘
│ 1. Assume Role リクエスト
│ (External ID を付与)
▼
┌──────────────────────┐
│ AWS IAM Role │
│ (Trust Policy で │
│ Snowflake ARN + │
│ External ID を許可)│
└────────┬─────────────┘
│ 2. 一時クレデンシャル発行
▼
┌──────────────────────┐
│ S3 Bucket │
│ /orders/ │
│ (IAM Roleの権限で │
│ 読み取り/書き込み) │
└──────────────────────┘-- AWS S3用 Storage Integration
CREATE OR REPLACE STORAGE INTEGRATION s3_orders_int
TYPE = EXTERNAL_STAGE
STORAGE_PROVIDER = 'S3'
ENABLED = TRUE
STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/snowflake-access-role'
STORAGE_ALLOWED_LOCATIONS = (
's3://company-data-lake/orders/',
's3://company-data-lake/returns/'
)
STORAGE_BLOCKED_LOCATIONS = (
's3://company-data-lake/orders/secrets/'
);-- Azure Blob Storage用 Storage Integration
CREATE OR REPLACE STORAGE INTEGRATION azure_data_int
TYPE = EXTERNAL_STAGE
STORAGE_PROVIDER = 'AZURE'
ENABLED = TRUE
AZURE_TENANT_ID = 'a]1b2c3d4-e5f6-7890-abcd-ef1234567890'
STORAGE_ALLOWED_LOCATIONS = (
'azure://myaccount.blob.core.windows.net/data-container/input/'
);-- Google Cloud Storage用 Storage Integration
CREATE OR REPLACE STORAGE INTEGRATION gcs_analytics_int
TYPE = EXTERNAL_STAGE
STORAGE_PROVIDER = 'GCS'
ENABLED = TRUE
STORAGE_ALLOWED_LOCATIONS = (
'gcs://analytics-bucket/raw/',
'gcs://analytics-bucket/processed/'
);After creating a Storage Integration, run DESCRIBE INTEGRATION to retrieve the service account information that Snowflake generated. You then plug these values into the Trust Policy on the cloud side.
DESC INTEGRATION s3_orders_int;
-- 主要な出力項目(AWSの場合)
-- ┌─────────────────────────────┬──────────────────────────────────────┐
-- │ property │ property_value │
-- ├─────────────────────────────┼──────────────────────────────────────┤
-- │ STORAGE_AWS_IAM_USER_ARN │ arn:aws:iam::987654321098:user/abc123│
-- │ STORAGE_AWS_EXTERNAL_ID │ ABC123_SFCRole=2_dGVzdA== │
-- │ STORAGE_ALLOWED_LOCATIONS │ s3://company-data-lake/orders/,... │
-- │ STORAGE_BLOCKED_LOCATIONS │ s3://company-data-lake/orders/sec... │
-- └─────────────────────────────┴──────────────────────────────────────┘Take the STORAGE_AWS_IAM_USER_ARN and STORAGE_AWS_EXTERNAL_ID returned by DESCRIBE INTEGRATION and apply them to the Trust Policy of the IAM role on the AWS side.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::987654321098:user/abc123"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "ABC123_SFCRole=2_dGVzdA=="
}
}
}
]
}Grant the IAM role permissions for GetObject / ListBucket (read access) on the S3 bucket, and add PutObject / DeleteObject (write access) if needed.
-- Storage Integrationを参照するExternal Stage
CREATE OR REPLACE STAGE ext_orders_stage
URL = 's3://company-data-lake/orders/'
STORAGE_INTEGRATION = s3_orders_int
FILE_FORMAT = (TYPE = 'PARQUET');
-- ステージ上のファイル確認
LIST @ext_orders_stage;
-- データロード
COPY INTO ORDERS
FROM @ext_orders_stage
PATTERN = '.*\.parquet'
ON_ERROR = 'CONTINUE';
-- データアンロード
COPY INTO @ext_orders_stage/export/
FROM ORDERS
FILE_FORMAT = (TYPE = 'PARQUET')
HEADER = TRUE;| Aspect | Direct authentication (embedded keys) | Storage Integration |
|---|---|---|
| Security | Low (plain-text keys exposed in stage definition) | High (IAM role delegation, no keys) |
| Key management | Manual rotation required | Temporary credentials issued automatically |
| Key rotation | Requires recreating the stage | Not required (handled on the cloud side) |
| Access scope | Depends on the key's permissions | Controlled via ALLOWED/BLOCKED_LOCATIONS |
| Sharing across stages | Keys configured per stage | One Integration shared across multiple stages |
| Recommendation | Not recommended (legacy) | Recommended (official best practice) |
| Operation | Required privilege | Target role |
|---|---|---|
| CREATE INTEGRATION | CREATE INTEGRATION (account level) | ACCOUNTADMIN or a delegated role |
| ALTER / DROP INTEGRATION | OWNERSHIP ON INTEGRATION | Role that owns the Integration |
| Reference from a stage | USAGE ON INTEGRATION | Role that creates the stage |
| DESCRIBE INTEGRATION | USAGE ON INTEGRATION | Anyone reviewing configuration |
-- 権限付与の例
-- ACCOUNTADMINがIntegrationを作成
USE ROLE ACCOUNTADMIN;
CREATE STORAGE INTEGRATION s3_orders_int ...;
-- データエンジニアロールにUSAGE権限を付与
GRANT USAGE ON INTEGRATION s3_orders_int TO ROLE DATA_ENGINEER;
-- DATA_ENGINEERがステージを作成
USE ROLE DATA_ENGINEER;
CREATE STAGE ext_orders
URL = 's3://company-data-lake/orders/'
STORAGE_INTEGRATION = s3_orders_int;| Error / Symptom | Cause | Resolution |
|---|---|---|
| Failure using stage area. Cause: Access Denied | Snowflake's ARN is not configured in the IAM role's Trust Policy | Set STORAGE_AWS_IAM_USER_ARN from DESC INTEGRATION in the Trust Policy |
| External ID mismatch | The ExternalId in the Trust Policy doesn't match the DESC output | Copy STORAGE_AWS_EXTERNAL_ID exactly and reconfigure |
| Insufficient privileges on integration | The stage-creating role lacks USAGE privilege | GRANT USAGE ON INTEGRATION ... TO ROLE ... |
| ListBucket Access Denied | IAM policy is missing s3:ListBucket | Add ListBucket to the IAM policy (Resource: bucket ARN) |
| KMS Access Denied | Insufficient KMS permissions on an SSE-KMS encrypted bucket | Add kms:Decrypt and kms:GenerateDataKey to the IAM policy |
| Files in the specified path are invisible | The stage URL doesn't match STORAGE_ALLOWED_LOCATIONS | Verify the URL is within the prefix range of ALLOWED_LOCATIONS |
Architect / Data Engineer
問題 1
A team created an External Stage to load Parquet files from S3 into Snowflake. The CREATE STAGE statement specifies the STORAGE_INTEGRATION parameter, but running LIST @stage returns an 'Access Denied' error. DESCRIBE on the Storage Integration returns normally. What is the most likely cause?
正解: A
Since DESCRIBE INTEGRATION returns successfully, the Snowflake-side Integration configuration itself is correct. An Access Denied error points to a permissions issue on the AWS side, and the most common cause is that the IAM role's Trust Policy doesn't correctly reference Snowflake's service account (STORAGE_AWS_IAM_USER_ARN) and ExternalId (STORAGE_AWS_EXTERNAL_ID). Option B (FILE_FORMAT) would only surface during data parsing, not on a LIST call. Option C (warehouse): a warehouse is needed for LIST, but the 'Access Denied' message indicates a permissions issue, not a warehouse problem. Option D (BLOCKED_LOCATIONS): specifying the entire bucket in BLOCKED_LOCATIONS would error at Integration creation time, so it wouldn't manifest here.
Can I create an External Stage without a Storage Integration?
Technically, you can create an External Stage by specifying AWS_KEY_ID and AWS_SECRET_KEY directly. However, the credentials are embedded in the stage definition in plain text, which can be exposed to other roles via SHOW STAGES — a significant security risk. The official Snowflake documentation strongly recommends Storage Integrations, which use IAM role-based access delegation and remove the need to manage long-lived keys. Certification exams also frame Storage Integration as the 'more secure option.'
How do STORAGE_ALLOWED_LOCATIONS and STORAGE_BLOCKED_LOCATIONS interact?
STORAGE_ALLOWED_LOCATIONS is an explicit list of cloud storage paths that the Storage Integration is permitted to access. STORAGE_BLOCKED_LOCATIONS is an exclusion list that denies access to specific sub-paths even if they fall within an allowed location. For example, you can permit all of s3://data-bucket/ while excluding s3://data-bucket/secrets/. Combining the two lets you enforce fine-grained access control aligned with the principle of least privilege.
What is the best practice for using multiple Storage Integrations?
The recommended pattern is to separate Storage Integrations by environment (prod/staging/dev). Each Integration's STORAGE_ALLOWED_LOCATIONS should permit only the bucket paths for that environment, and USAGE ON INTEGRATION should be granted to environment-specific roles. This eliminates the risk of developers accidentally touching production buckets. From an audit perspective, it also makes it easier to track access logs per Integration through ACCOUNT_USAGE.ACCESS_HISTORY.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Snowflake Certifications: All 11 Exams Explained (2026)
Every SnowPro certification — Associate, Core, Specialty, Ad...
Snowflake Exam Difficulty Ranking: All 11 Certs Compared (2026)
All 11 SnowPro exams ranked by difficulty with study-time es...
Snowflake Study Guide: Fastest Pass Route by Exam (2026)
How to pass SnowPro certifications efficiently — official ma...
SnowPro Core (COF-C03): Complete Exam Guide (2026)
Pass the SnowPro Core exam — six domains, scope, sample ques...
SnowPro Associate Platform (SOL-C01): Complete Guide (2026)
The entry-level SnowPro Associate exam — scope, weighting, s...