Connecting to SQL Server with Integrated Security (Kerberos)
Connect Flink SQL to a Kerberos-secured SQL Server with no username or password, using the JDBC connector's JavaKerberos authentication mode.
On this page
Run a FlinkSQL deployment against a Kerberos-only Microsoft SQL Server with no username or password. This works identically for source and sink tables and needs no custom image or Helm chart change.
Applies to: Ververica Platform 3.1.1, VVR 4.5.0, Flink 1.20 (JDK 11), SQL Server 2019/2022, SQL deployments.
Components
Kerberos is a three-party protocol, not a direct Flink-to-SQL-Server secret:
- KDC (Active Directory domain controller): issues tickets and holds the service principal names (SPNs) and accounts.
- Client (the Flink TaskManager, using the
mssql-jdbcdriver): uses a keytab to get a ticket-granting ticket (TGT), then a service ticket for the SQL Server SPN. - SQL Server: validates the ticket with its own keytab, then maps the principal to a SQL login through AD/LDAP.
How the handshake works
- The TaskManager authenticates its principal against the KDC using the keytab (an AS-REQ) and receives a TGT.
- The TaskManager requests a service ticket from the KDC for the SQL Server SPN (
MSSQLSvc/host:1433). - The TaskManager connects to SQL Server and presents the service ticket. No username or password is sent.
- SQL Server resolves the principal to a SQL login through LDAP against the KDC, then authenticates the connection.
No jaas.conf file is needed: the platform logs in from the keytab, and because security.kerberos.login.contexts includes SQLJDBCDriver, Flink installs a JAAS entry under that name that mssql-jdbc picks up automatically.
What You Need
- A realm (for example
EXAMPLE.COM) and a KDC hostname reachable from the Flink pods on TCP 88 and 389. - An SPN registered to the SQL Server service account, in the form
MSSQLSvc/<SQL_HOST>:1433. - A client principal (for example
flinksvc@EXAMPLE.COM) and its keytab. - A
krb5.conffor the realm. See the appendix for a sample. - On SQL Server: an AD login for the principal, mapped to a DB user with rights on the target table.
- Network reachability from the Flink pods to the KDC (ports 88, 389) and to SQL Server (port 1433).
Step 1: Connector Jars
VVR ships no SQL Server connector out of the box. Combine the Apache Flink JDBC connector with the Microsoft JDBC driver (versions shown are for Flink 1.20 / JDK 11):
Upload jars to the platform artifact store and reference them with s3i:// URIs. Plain https:// Maven URLs are not fetched.
Step 2: Register the Kerberos Configuration
Upload the keytab and krb5.conf to the artifact store, then register the configuration once per namespace using the REST API. In Ververica Platform 3.1.1 the console UI does not expose Kerberos, so the API is currently the only way to register it:
1POST /api/v2/kerberos-configs (header: Workspace: <workspace>)Step 3: FlinkSQL (No Username or Password)
Kerberos flags live in the url property; set serverSpn explicitly. A source table uses the same WITH clause (drop the PRIMARY KEY).
1CREATE TEMPORARY TABLE mssql_sink (
2 id BIGINT, payload STRING, ts TIMESTAMP(3),
3 PRIMARY KEY (id) NOT ENFORCED
4) WITH (
5 'connector' = 'jdbc',
6 'url' = 'jdbc:sqlserver://<SQL_HOST>:1433;databaseName=<DB>;integratedSecurity=true;authenticationScheme=JavaKerberos;serverSpn=<SPN>;encrypt=true;trustServerCertificate=false',
7 'table-name' = 'dbo.<TABLE>',
8 'driver' = 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
9);Step 4: Deployment Configuration
1spec:
2 template:
3 spec:
4 artifact:
5 kind: SQLSCRIPT
6 versionName: vera-4.5-jdk11-flink-1.20
7 sqlScript: |-
8 -- DDL from Step 3 (+ INSERT INTO mssql_sink SELECT ... for a sink)
9 additionalDependencies:
10 - s3i://<ARTIFACT_STORE>/artifacts/namespaces/<ns>/flink-connector-jdbc-sqlserver-3.3.0-1.20.jar
11 - s3i://<ARTIFACT_STORE>/artifacts/namespaces/<ns>/mssql-jdbc-12.6.1.jre11.jar
12 flinkConfiguration:
13 security.kerberos.login.contexts: Client,KafkaClient,SQLJDBCDriver
14 kerberosConfig:
15 kerberosEnabled: true
16 kerberosClusterName: kerberos
17 principal: <PRINCIPAL>
18 keytabPath: s3i://<ARTIFACT_STORE>/artifacts/namespaces/<ns>/flinksvc.keytab
19 krb5ConfPath: s3i://<ARTIFACT_STORE>/artifacts/namespaces/<ns>/krb5.confsecurity.kerberos.login.contextsmust includeSQLJDBCDriver.kerberosConfigneeds both: akerberosClusterNamematching the config registered in Step 2 (an unregistered name fails withResourceDoesNotExist), and the inlinekeytabPath+krb5ConfPath+principal(omitting the paths fails the appmanager). In Ververica Platform 3.1.1, the paths are effectively given twice: once in the registered config, once inline. Both are required.
The core jdbc connector already comes from the Custom Connector, so only the dialect and driver are listed as Additional Dependencies here. A pod template on a SQL deployment causes “Failed to create the Kubernetes resources: empty” and no pod starts. Use the native kerberosConfig above to mount the keytab and krb5.conf instead.
Step 5: Deploy and Verify
Start the deployment. The JobManager starts first, then the TaskManager (an artifact-fetcher init container stages the jars, keytab, and krb5.conf), then the job runs.
1sqlcmd -S <SQL_HOST> -E -d <DB> -Q "SELECT COUNT(*) FROM dbo.<TABLE>;"
2kubectl -n <ns> exec <jobmanager-pod> -c flink-main-container -- ls /flink/usrlib/ # all 3 jars presentTLS
encrypt=true is required by SQL Server 2022. In production, keep trustServerCertificate=false and add the SQL Server CA to the JVM truststore using env.java.opts (-Djavax.net.ssl.trustStore=...).
Notes and Limitations (Ververica Platform 3.1.1)
- Kerberos configuration is API-only: the console UI has no Kerberos page. Register the config using
POST /api/v2/kerberos-configsand setkerberosConfigon the deployment through the YAML view or the API. - A pod template on a SQL deployment causes “Failed to create the Kubernetes resources: empty” and no pod starts. Use the native
kerberosConfigfield instead. - Dependencies must be in the artifact store (
s3i://);https://URLs are not fetched. - Editing an existing SQL deployment might not take effect, since configuration is cached per SQL file and the YAML view merges. If a change does not apply, create a new SQL file or a fresh deployment.
- The SQL editor validator cannot load the dialect, so it might report a dialect error even when the deployment runs fine. Rely on an actual run to confirm.
Generalizing Beyond SQL Server
This pattern is not specific to Microsoft SQL Server: it generalizes to any Kerberos-secured JDBC target, including Oracle (Kerberos/GSS-API authentication) and PostgreSQL (GSSAPI authentication). The keytab, krb5.conf, kerberosConfig registration, and security.kerberos.login.contexts steps above stay the same across drivers. The differences are driver-specific: the JDBC URL flags (for example, Oracle's oracle.net.authentication_services=(KERBEROS5) versus PostgreSQL's gsslib=gssapi), the login-context name the driver expects, and which driver JAR to stage as an Additional Dependency alongside the jdbc Custom Connector.
Appendix: Sample krb5.conf
1[libdefaults]
2 default_realm = EXAMPLE.COM
3 dns_lookup_realm = false
4 dns_lookup_kdc = false
5 rdns = false
6 dns_canonicalize_hostname = false
7 udp_preference_limit = 1
8[realms]
9 EXAMPLE.COM = {
10 kdc = dc1.example.com
11 admin_server = dc1.example.com
12 }
13[domain_realm]
14 .example.com = EXAMPLE.COM
15 example.com = EXAMPLE.COM