CREATE CREDENTIAL#
Creates a server-level credential. A credential is a named record that holds an identity and, optionally, a secret; features that authenticate to an external resource reference it by name. A server-level credential belongs to the server as a whole: its name is unique server-wide, and it is visible from every virtual database.
Syntax#
Arguments#
credential_name
The name of the credential. Must be unique on the server — creating a second credential with the same name
raises an error. The name may be at most 128 characters and must not start with # (a leading # is
reserved for system credentials).
IDENTITY = ‘identity_name‘
The identity presented when connecting to the external resource. Certain reserved values select an
authentication mode: SHARED ACCESS SIGNATURE, MANAGED IDENTITY, USER IDENTITY, S3 ACCESS KEY.
Any other value is treated as a basic user identity.
Note
Every mode above can be stored, but not every mode can yet authenticate a read. A storage read
authenticates with SHARED ACCESS SIGNATURE or with a basic identity and password.
MANAGED IDENTITY and USER IDENTITY are refused when a read tries to use them, and
S3 ACCESS KEY needs an s3:// location, which no reader serves yet. See
Authenticated reads from remote storage below.
SECRET = ‘secret‘
The secret — for example a password, a SAS token, or an access key. Optional: identity-only credentials such
as MANAGED IDENTITY omit it.
FOR CRYPTOGRAPHIC PROVIDER provider_name
Accepted for SQL Server compatibility, but always rejected (error 15151): the server registers no cryptographic (EKM) provider, so no credential can be created for one.
Remarks#
The secret is never stored or shown in clear text. It is protected at rest, and it is redacted wherever
statement text is logged or traced (for example sys.qua_recent_statements). The sys.credentials
catalog view exposes the identity metadata only — never the secret.
A credential is cluster-wide: created once, it is available on every node of the cluster, and dropping it removes it everywhere.
A server-level credential and a database scoped credential may carry the same name; they are independent
records. Use CREATE DATABASE SCOPED CREDENTIAL when the credential should belong to — and move with — one
virtual database; use CREATE CREDENTIAL for one credential shared by all databases on the cluster.
IF NOT EXISTS is not supported.
How credentials are used#
A credential is resolved on every use — never cached — so creating, rotating or dropping one takes effect on the next statement that needs it.
External data sources. CREATE EXTERNAL DATA SOURCE ... CREDENTIAL = name binds a credential by
name. Each read through the data source resolves the name to a database scoped credential in the
database where the reading statement runs; when none exists, Querona falls back to the server-level
credential of that name — an extension over SQL Server, where only a database scoped credential can bind
to an external data source. The name is validated when the data source is created, and
ALTER EXTERNAL DATA SOURCE ... SET CREDENTIAL = name re-points the binding under the same check: a
name that resolves at neither scope fails the statement with error 46516. Because resolution is per use,
a database scoped credential created later under the same name overrides the server-level one for its
database from the next read on.
Bulk reads from a URL. When the path of OPENROWSET (BULK …) is a remote http(s) URL and the data source does not carry
its own CREDENTIAL, the read authenticates through server-level credentials only — as in SQL Server,
database scoped credentials never participate in this lookup. A credential matches when its name equals
the URL, or is a prefix of it that ends at a path-segment boundary (the URL continues with / right
after the name); matching is case-insensitive over the whole string, and the longest matching name wins.
A name ending in a slash never matches a longer URL. With no matching credential the read fails with
error 15151: Cannot find the CREDENTIAL 'https://...'.
AI provider API keys. A registered AI model carries no API key. The key resolves at call time from a credential named by the model’s endpoint URL, matched with the same prefix rule as URL bulk reads: a server-level credential is the cluster-wide default for the provider, and a database scoped credential of the same name overrides it inside its own database. See qua_add_external_ai_model.
Using a credential requires no permission on the credential itself — matching SQL Server. Any principal allowed to run the consuming statement (a query through the external data source, a bulk read from a URL, an AI function call) uses the matching credential; the secret is never shown to that principal. Plan credential scope accordingly: a server-level credential is usable from every database by anyone permitted to run such statements, so prefer a database scoped credential when access should follow one database’s security boundary.
Authenticated reads from remote storage#
When a matching credential is found, it is applied as the request is built - a shared access
signature is appended to the outgoing request’s query string, and a basic identity and password become an
Authorization header. The location you wrote is never rewritten, so the secret cannot reach the stored
data-source location, a log, a trace, or the text of an error: a failed read names the location exactly as
you stated it.
A credential is applied per location. A connection that names several locations authenticates each one on its own terms, so a local folder listed beside a remote container is still read with the Querona service identity.
Some pairings cannot work, and each is refused rather than silently ignored - a credential that looks applied but is not is indistinguishable from one that authenticated:
Pairing |
What happens |
|---|---|
A local path or |
Refused by |
A plain |
Refused, both when the data source is created or altered and when a read is attempted. The
signature or password would cross the network unencrypted, where anything on the path can read it,
and a signature stays usable for its whole validity once read. State the location with |
A plain |
Allowed. That traffic never leaves the machine, so a storage emulator or a co-located service can be read authenticated. |
|
Refused at the read: this version obtains no token for an ambient environment identity. |
|
Refused. An S3-compatible key signs an |
|
Refused. Reading anonymously here would report a private location as unreachable while naming a credential that does exist. |
Note
Authenticated remote reads cover delimited text today. The other file formats - text, XML, PDF, QVD, Parquet, Excel - are read from the local file system, so a credential does not apply to them.
Permissions#
Requires the connection-management permission (CreateConnection) on the server.
Examples#
A basic identity and secret
CREATE CREDENTIAL AppCred
WITH IDENTITY = 'reporting_user', SECRET = 'strong-secret';
A shared access signature, named after the resource it opens
CREATE CREDENTIAL [https://acct.blob.core.windows.net/cont]
WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = 'sv=2022-11-02&ss=b&srt=co&sp=r&sig=...';
An identity-only credential (no secret)
CREATE CREDENTIAL MiCred
WITH IDENTITY = 'MANAGED IDENTITY';