Securing External Stages
Hardening your data ingestion pathways: Storage Integrations, Private Link, and IAM best practices.
External stages (S3, Azure Blob, GCS) are the most common way data enters Snowflake. However, they are also a common attack vector if misconfigured. Hardcoding AWS Access Keys into stage definitions is a practice from 2018—in 2025, we have better tools.
1. Storage Integrations are Mandatory
Never use credentials (AWS_KEY_ID, AWS_SECRET_KEY) in a CREATE STAGE command. Instead, use a Storage Integration.
This object establishes a trust relationship between Snowflake and your Cloud Provider (using IAM Roles in AWS or
Service Principals in Azure).
CREATE STORAGE INTEGRATION s3_int
TYPE = EXTERNAL_STAGE
STORAGE_PROVIDER = 'S3'
ENABLED = TRUE
STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/my-snowflake-role'
STORAGE_ALLOWED_LOCATIONS = ('s3://my-bucket/data/');sqlThis ensures that:
- Credentials are not exposed in DDL.
- You can rotate keys/roles on the cloud side without breaking Snowflake objects.
- You can strictly limit which buckets Snowflake can access.
2. Network Isolation (Private Link)
If you are on an Enterprise edition or higher, use Private Link (AWS) or Private Endpoints (Azure). This ensures that traffic between your VPC/VNet and Snowflake never traverses the public internet. It significantly reduces the surface area for man-in-the-middle attacks.
3. Encryption
Ensure your external buckets have Server-Side Encryption (SSE) enabled. Snowflake handles the decryption transparently using the permissions granted to the integration.
4. Directory Tables for Observability
Turn on highly convenient Directory Tables on your stages.
CREATE STAGE my_stage
URL='s3://bucket/path'
STORAGE_INTEGRATION = s3_int
DIRECTORY = (ENABLE = TRUE);sqlThis allows you to query the stage contents (SELECT * FROM DIRECTORY(@my_stage)) to audit what files are present,
their sizes, and last modified timestamps effectively.
5. Least Privilege
When configuring the Cloud IAM Role:
- Grant
GetObjectonly for loading. - Grant
PutObjectonly for unloading. - Restrict the
Resourcescope to specific prefixes, not the whole bucket.
Conclusion
Securing your connection to the outside world is step one in a robust security posture. By forcing the use of Storage Integrations and implementing Private Connectivity, you close the biggest doors to potential data exfiltration.