What you will be able to do
- Explain the difference between private and public endpoints and what the Snowflake ingress proxy enforces
- Configure controlled egress with egress network rules and an external access integration
- Pass credentials into containers with Snowflake secrets instead of plain values in the specification
- Choose the right tool for container logs and compute pool usage while giving out the least access
1.Ingress: private by default, public through a proxy
Every port a service listens on is declared as an endpoint in the specification. By default, endpoints are private. Only service functions and other services can call them. Setting public: true gives the endpoint a unique Snowflake hostname reachable from the internet. Because this is a privileged operation, the owner role must hold BIND SERVICE ENDPOINT on the account.
endpoints:
- name: <endpoint name>
port: <port number>
protocol : < TCP / HTTP >
public: truePublic traffic never reaches your container directly. A Snowflake proxy sits in front of the service and filters both requests and responses. Idle connections are closed after 90 seconds, and users can sign out at /sfc-endpoint/logout, after which they have to authenticate to Snowflake again.
| Direction | Proxy behaviour |
|---|---|
| Request | Refuses to forward the banned HTTP methods TRACE and CONNECT |
| Request | Removes X-SF-SPCS-Authorization, and removes Authorization when it contains a Snowflake token |
| Response | Returns 403 instead of an executable Content-Type such as application/x-sh |
| Response | Removes the Server, X-Powered-By, X-XSS-Protection and Public-Key-Pins headers |
| Response | Sets X-Frame-Options to DENY and X-Content-Type-Options to nosniff, and adds a Content-Security-Policy |
| Response | Returns the CORS settings from the specification and removes CORS headers sent by the service |
Checkpoint 1 of 7· Exam question
A security engineer is drafting the VALUE_LIST for a network rule (MODE = EGRESS, TYPE = HOST_PORT) that will back an external access integration for a service. Which TWO entries are valid for Snowpark Container Services egress?(Select 2)
Correct answers: A, C — 'api.vendor.example.com:443' to allow HTTPS calls to exactly one fully named vendor host.; 'db.vendor.example.com:5432' to allow outbound connections to a PostgreSQL server on a high port.
- A. Correct: a fully qualified hostname with an allowed port is the standard HOST_PORT form, and port 443 is permitted for egress.
- B. Incorrect: wildcards are not supported in SPCS egress host lists, so every hostname must be written out in full.
- C. Correct: egress permits ports 22, 80, 443 and anything from 1024 upward, so a database on port 5432 can be allowed by hostname.
- D. Incorrect: port 25 is outside the permitted set of 22, 80, 443 and 1024 and above, so this entry cannot be used for container egress.
- E. Incorrect: SPCS egress relies on HOST_PORT rules naming hostnames and ports; a CIDR-style IPV4 rule is not how container egress is granted.
Checkpoint 2 of 7· Check yourself
A web app on a public SPCS endpoint returns CORS headers from its own code. A browser client still sees different CORS behaviour. Why?
CORS for public endpoints is configured in corsSettings in the specification. The proxy throws away whatever the container sends.
“Note that the proxy removes any CORS headers returned by the service.”Source: docs.snowflake.com
Sources1
2.Egress: network rules and external access integrations
Outbound access is the reverse problem. By default, services have only limited internet access. To allow a destination, an administrator creates one or more egress network rules and gathers them, together with any secrets, into an external access integration (EAI). The service is then configured to use that EAI. Any destination that no rule allows is denied. Snowflake gives ACCOUNTADMIN as an example of a role that can create an EAI. Creating a network rule requires CREATE NETWORK RULE on the schema.
Checkpoint 3 of 7· Fill the gap
Which MODE value makes this rule usable in an external access integration?
CREATE OR REPLACE NETWORK RULE google_apis_network_rule
MODE = ?
TYPE = HOST_PORT
VALUE_LIST = ('translation.googleapis.com');Rules used by an external access integration describe outbound destinations, so they use MODE = EGRESS.
Source: docs.snowflake.comSPCS adds some limits. VALUE_LIST needs full host names, and wildcards such as *.googleapis.com are rejected. If you leave out the port, it defaults to 443. SPCS accepts only rules for ports 22, 80, 443 and 1024 and above. The EAI also applies to the browser: for a public web app, the proxy copies the EAI's network rules into the page's Content-Security-Policy, so the page can reach only the sites the service can reach.
Checkpoint 4 of 7· Check yourself
An engineer wants a service to call every Google API host and writes VALUE_LIST = ('*.googleapis.com'). What is the result for SPCS?
Egress rules for SPCS need full host names, which keeps each allowed destination explicit.
“you must provide a full host name. Wildcards (for example, *.googleapis.com) are not supported.”Source: docs.snowflake.com
3.Keeping secrets out of the YAML
The containers.env field looks like an easy place for an API key, but every process in the container can read those variables, and the specification itself is metadata. Snowflake asks customers not to put personal, sensitive or regulated data there. The right approach is to store the credential in a Snowflake secret object and reference it from the specification.
secrets: # optional list
- snowflakeSecret:
objectName: <object-name> # specify this or objectReference
objectReference: <reference-name> # specify this or objectName
directoryPath: <path> # specify this or envVarName
envVarName: <name> # specify this or directoryPath
secretKeyRef: username | password | secret_string # specify only with envVarNamesnowflakeSecret names the secret with objectName. In a Native App with containers, it uses objectReference instead. You then choose where the value appears in the container: envVarName puts one key, chosen with secretKeyRef (username, password or secret_string), into an environment variable, and directoryPath writes the secret to files. The service's owner role needs READ on every secret it references, so access to secrets is controlled by grants rather than by whoever can read the YAML.
Checkpoint 5 of 7· Check yourself
CREATE SERVICE fails when the specification references a Snowflake secret through snowflakeSecret.objectName. Which grant is most likely missing?
The owner role, which is the role that creates the service, must hold READ on each secret the specification references.
“Note that, the role that is creating the service (owner role) will need the READ privilege on the secrets referenced.”Source: docs.snowflake.com
Sources3
4.Monitoring: container logs and compute pool usage
Unless you opt out, Snowflake collects whatever containers write to stdout and stderr into the account's event table. spec.logExporters chooses which streams are kept (all, stderr only, or none), and the LOG_LEVEL parameter on CREATE SERVICE or ALTER SERVICE sets the severity. Logs written as JSON with a body key are stored as structured records. Any other output goes into the value column. Anything the code prints ends up in a table, so do not log secrets.
| Method | What it returns | Access consideration |
|---|---|---|
| <service_name>!SPCS_GET_LOGS | Event-table logs for one service or job, one day by default | Service owner role or MONITOR on the service. No access to the whole event table is needed |
| Query the event table directly | Historical logs, filtered on RESOURCE_ATTRIBUTES such as snow.service.name | Requires full access to the event table |
| SYSTEM$GET_SERVICE_LOGS | Logs of a container that is currently running, not saved to the event table | Most useful during development and testing |
SELECT TIMESTAMP, RESOURCE_ATTRIBUTES, RECORD_ATTRIBUTES, VALUE
FROM <current_event_table_for_your_account>
WHERE timestamp > dateadd(hour, -1, current_timestamp())
AND RESOURCE_ATTRIBUTES:"snow.service.name" = '<service_name>'
AND RECORD_TYPE = 'LOG'
ORDER BY timestamp DESC
LIMIT 10;For compute pools, the exam guide mentions a SERVICE_USAGE_HISTORY view. The documentation in these sources does not describe a view by that name. The pool-level view it does document is ACCOUNT_USAGE.SNOWPARK_CONTAINER_SERVICES_HISTORY. It returns hourly credits for each compute pool over 365 days, with up to three hours of latency, and its IS_EXCLUSIVE and APPLICATION_NAME columns show pools created for applications. An unexpected rise in a pool's credits is a signal worth investigating. Every monitoring method still requires the right privileges on the services, jobs and compute pools involved.
Checkpoint 6 of 7· Exam question
Which privilege must the owner role of a service hold before the service can be created with an endpoint declared as public: true in its specification?
Correct answer: A — BIND SERVICE ENDPOINT, granted at the account level to the role that will own the new service.
- A. Correct: exposing an endpoint to the internet is gated by the BIND SERVICE ENDPOINT privilege on the owner role, so public exposure is an explicit grant.
- B. Incorrect: CREATE INTEGRATION is for integration objects such as external access integrations, and it does not control public ingress endpoints.
- C. Incorrect: OPERATE on a compute pool permits suspending and resuming the pool; it does not authorize binding a public endpoint.
- D. Incorrect: MONITOR on an image repository relates to viewing repository information and has no role in enabling public endpoints.
Checkpoint 7 of 7· Match them up
Match each monitoring need to the tool that fits
Tap a term, then the definition that fits it.
SPCS_GET_LOGS is limited to one service and needs only owner or MONITOR rights. SYSTEM$GET_SERVICE_LOGS reads from live containers. The account usage view reports pool credits, and logExporters controls which streams are collected.
“The caller does not need access to the entire event table, which can be beneficial for customers with strict information-security requirements.”Source: docs.snowflake.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.A service endpoint can be reached from the internet unless you explicitly block it.Why is that wrong?
Endpoints are private by default. Only service functions and other services can call them until public: true is set, and that requires BIND SERVICE ENDPOINT.
Covered in Ingress: private by default, public through a proxy
2.To let someone read one service's logs, you have to grant them access to the account's event table.Why is that wrong?
<service_name>!SPCS_GET_LOGS needs only the owner role or MONITOR on that service, so the rest of the event table stays restricted.
Covered in Monitoring: container logs and compute pool usage
3.Putting an API key in containers.env is safe because only the main process reads it.Why is that wrong?
Every process in the container can read env values, and specification metadata should not contain sensitive data. Use containers.secrets with a Snowflake secret instead.
Covered in Keeping secrets out of the YAML
Practise it for real
Find and read a service's container logs while using as little access as possible
1.Run SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
Why: Container logs go to the account's active event table, so you need to know which table that is.
You should see: The EVENT_TABLE parameter value, which is the fully qualified name of the active event table.
2.As a role with MONITOR on the service, run SELECT * FROM TABLE(mydb.myschema.my_test_job!SPCS_GET_LOGS());
Why: This shows that log access can be limited to one service without opening the whole event table.
You should see: Rows with TIMESTAMP, INSTANCE_ID, CONTAINER_NAME, LOG and RECORD_ATTRIBUTES for the past day.
3.As a role with full event table access, run the event-table query filtered on RESOURCE_ATTRIBUTES:"snow.service.name" and RECORD_TYPE = 'LOG'.
Why: A direct query reaches historical logs and every resource attribute, but it requires broad access.
You should see: Up to 10 log rows from the last hour, newest first.
Stuck? Get a nudge
If SPCS_GET_LOGS returns nothing, check whether spec.logExporters or LOG_LEVEL is filtering out the streams you expected.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://docs.snowflake.com/en/developer-guide/snowpark-container-services/service-network-communicationsOfficial docs
“Creating a public endpoint is a privileged operation and the service’s owner role must have the BIND SERVICE ENDPOINT privilege on the account.”
↩︎ Ingress: private by default, public through a proxy“the proxy does not forward the request to your service: TRACE CONNECT”
↩︎ Ingress: private by default, public through a proxy“the Snowflake proxy sets this response header to DENY, preventing other web pages from using an iframe to the web page for your service.”
↩︎ Ingress: private by default, public through a proxy“If there is no activity on a connection to an ingress endpoint for 90 seconds, Snowflake terminates the connection.”
↩︎ Ingress: private by default, public through a proxy“By default, services have limited permissions to access the internet.”
↩︎ Egress: network rules and external access integrations“Snowpark Container Services supports only the network rules that allow ports 22, 80, 443, and 1024+.”
↩︎ Egress: network rules and external access integrations“The Snowflake proxy applies the same network restrictions on the service and the web page by adding a Content-Security-Policy (CSP) header in the response.”
↩︎ Egress: network rules and external access integrations“By default, service endpoints are private. Only service functions and service-to-service communications can make requests to the private endpoints.”
↩︎ Exam trap 1“Note that the proxy removes any CORS headers returned by the service.”
↩︎ Checkpoint“you must provide a full host name. Wildcards (for example, *.googleapis.com) are not supported.”
↩︎ Checkpoint - 2.https://docs.snowflake.com/en/developer-guide/external-network-access/creating-using-external-network-accessOfficial docs
“An attempt to access a network location that is not specified by an allowed network rule will be denied.”
↩︎ Egress: network rules and external access integrations“If you omit a port number, Snowflake will use the default port number for external access, 443.”
↩︎ Egress: network rules and external access integrations - 3.https://docs.snowflake.com/en/developer-guide/snowpark-container-services/specification-referenceOfficial docs
“Customers should ensure that no personal data, sensitive data, export-controlled data, or other regulated data is entered as metadata in the specification file.”
↩︎ Keeping secrets out of the YAML“Use the envVarName field to pass the secret as environment variables or directoryPath to write the secrets to local container files.”
↩︎ Keeping secrets out of the YAML“All processes in the container have access to these environment variables”
↩︎ Exam trap 3“Note that, the role that is creating the service (owner role) will need the READ privilege on the secrets referenced.”
↩︎ Checkpoint - 4.https://docs.snowflake.com/en/developer-guide/snowpark-container-services/monitoring-servicesOfficial docs
“You control which streams are collected (all, standard error only, or none)”
↩︎ Monitoring: container logs and compute pool usage“A user needs the appropriate privileges on services, jobs, and compute pools to access the monitoring data.”
↩︎ Monitoring: container logs and compute pool usage“The caller needs either the service owner role or a role with the MONITOR privilege on the service.”
↩︎ Exam trap 2“The caller does not need access to the entire event table, which can be beneficial for customers with strict information-security requirements.”
↩︎ Checkpoint - 5.https://docs.snowflake.com/en/sql-reference/account-usage/snowpark_container_services_historyOfficial docs
“can be used to return the hourly compute pool credit usage for an account within the last 365 days (1 year).”
↩︎ Monitoring: container logs and compute pool usage