|
| 1 | +--- |
| 2 | +title: "Tutorial: Configure Microsoft Entra ID authentication manually for SQL Server on containers and Kubernetes" |
| 3 | +description: Learn how to enable Microsoft Entra authentication for SQL Server on Linux containers without using Azure Arc. |
| 4 | +author: rwestMSFT |
| 5 | +ms.author: randolphwest |
| 6 | +ms.date: 12/12/2025 |
| 7 | +ms.service: sql |
| 8 | +ms.subservice: linux |
| 9 | +ms.topic: tutorial |
| 10 | +ms.custom: |
| 11 | + - linux-related-content |
| 12 | +helpviewer_keywords: |
| 13 | + - "authentication [SQL Server] on Linux, Microsoft Entra" |
| 14 | + - "authenticate [SQL Server] Linux" |
| 15 | +--- |
| 16 | +# Tutorial: Configure Microsoft Entra ID authentication manually for SQL Server on containers and Kubernetes |
| 17 | + |
| 18 | +[!INCLUDE [sql-linux](../../includes/applies-to-version/sql-linux.md)] |
| 19 | + |
| 20 | +This tutorial walks you through manually enabling Microsoft Entra ID authentication for [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] running in containers. Because Azure Arc doesn't currently support [container workloads](../../sql-server/azure-arc/overview.md) for this scenario, you can configure Microsoft Entra ID authentication directly, for standalone containers and Kubernetes deployments. |
| 21 | + |
| 22 | +For all other deployment scenarios, you should configure Microsoft Entra ID authentication through Azure Arc. |
| 23 | + |
| 24 | +## Prerequisites |
| 25 | + |
| 26 | +- Microsoft Entra ID is configured for your tenant. |
| 27 | + |
| 28 | +- [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] can reach Microsoft Entra ID endpoints. |
| 29 | + |
| 30 | +- A Microsoft Entra application is registered. |
| 31 | + |
| 32 | + Follow the directions in [Tutorial: Set up Microsoft Entra authentication for SQL Server with app registration](../../relational-databases/security/authentication-access/azure-ad-authentication-sql-server-setup-tutorial.md), and upload the certificate to the created registered application, that you create in the first step of the tutorial. |
| 33 | + |
| 34 | +- A supported [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] Linux container image. |
| 35 | + |
| 36 | +- Access to Docker or a Kubernetes cluster with `kubectl`. |
| 37 | + |
| 38 | +## Overview of the configuration |
| 39 | + |
| 40 | +Deployment models require: |
| 41 | + |
| 42 | +1. A certificate associated with the Microsoft Entra application |
| 43 | + |
| 44 | +1. [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] configured with: |
| 45 | + |
| 46 | + - Certificate path |
| 47 | + - Microsoft Entra application (client) ID |
| 48 | + - Microsoft Entra tenant ID |
| 49 | + |
| 50 | +1. At least one Microsoft Entra login created in [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)]. |
| 51 | + |
| 52 | +The difference between environments is how the certificate and configuration are supplied: |
| 53 | + |
| 54 | +- **Containers**: environment variables or mounted files |
| 55 | +- **Kubernetes**: ConfigMaps and Secrets |
| 56 | + |
| 57 | +## Create the certificate |
| 58 | + |
| 59 | +You need a certificate for [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] to authenticate to Microsoft Entra ID. For production environments, use a certificate issued by a trusted Certificate Authority (CA). |
| 60 | + |
| 61 | +In this example, you can create a self-signed certificate using OpenSSL. |
| 62 | + |
| 63 | +1. Create a self-signed certificate with the following command, and follow the prompts on-screen: |
| 64 | + |
| 65 | + ```bash |
| 66 | + openssl req -x509 -newkey rsa:4096 \ |
| 67 | + -keyout mssql-entra-id-key.pem \ |
| 68 | + -out mssql-entra-id-cert.pem \ |
| 69 | + -days 365 -nodes |
| 70 | + ``` |
| 71 | + |
| 72 | +1. Verify the files: |
| 73 | + |
| 74 | + ```bash |
| 75 | + ls -lrt | grep mssql-entra-id |
| 76 | + ``` |
| 77 | + |
| 78 | + [!INCLUDE [ssresult-md](../../includes/ssresult-md.md)] |
| 79 | + |
| 80 | + ```output |
| 81 | + -rw------- 1 user user 3272 Sep 11 19:13 mssql-entra-id-key.pem |
| 82 | + -rw-rw-r-- 1 user user 2139 Sep 11 19:13 mssql-entra-id-cert.pem |
| 83 | + ``` |
| 84 | + |
| 85 | +1. Convert the certificate to `.pfx`. Leave the export password empty. |
| 86 | + |
| 87 | + ```bash |
| 88 | + openssl pkcs12 \ |
| 89 | + -inkey mssql-entra-id-key.pem \ |
| 90 | + -in mssql-entra-id-cert.pem \ |
| 91 | + -nodes -export \ |
| 92 | + -out mssql-entra-id.pfx |
| 93 | + ``` |
| 94 | + |
| 95 | + > [!IMPORTANT] |
| 96 | + > If you use an export password, [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] fails to start. |
| 97 | +
|
| 98 | +1. Verify the files: |
| 99 | + |
| 100 | + ```bash |
| 101 | + ls -lrt | grep mssql-entra-id |
| 102 | + ``` |
| 103 | + |
| 104 | + [!INCLUDE [ssresult-md](../../includes/ssresult-md.md)] |
| 105 | + |
| 106 | + ```output |
| 107 | + -rw------- 1 user user 3272 Sep 11 19:13 mssql-entra-id-key.pem |
| 108 | + -rw-rw-r-- 1 user user 2139 Sep 11 19:13 mssql-entra-id-cert.pem |
| 109 | + -rw-rw-r-- 1 user user 2139 Sep 11 19:14 mssql-entra-id.pfx |
| 110 | + ``` |
| 111 | + |
| 112 | +1. Upload the *public certificate* to the registered Microsoft Entra application. If you obtain a trusted certificate from a CA, upload that instead. |
| 113 | + |
| 114 | + :::image type="content" source="media/container-kubernetes-microsoft-entra-deployment/certificate.png" alt-text="Screenshot of uploaded certificates in the Azure portal."::: |
| 115 | + |
| 116 | +## Configure SQL Server containers (standalone) |
| 117 | + |
| 118 | +1. Run [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] in a container with Microsoft Entra authentication enabled: |
| 119 | + |
| 120 | + ```bash |
| 121 | + docker run --name sql2025-entra \ |
| 122 | + -e ACCEPT_EULA=Y \ |
| 123 | + -e MSSQL_SA_PASSWORD='<password>' \ |
| 124 | + -e MSSQL_AAD_CLIENT_ID='<client-id>' \ |
| 125 | + -e MSSQL_AAD_PRIMARY_TENANT='<tenant-id>' \ |
| 126 | + -e MSSQL_AAD_CERTIFICATE_FILE_PATH='/var/opt/mssql/mssql-entra-id.pfx' \ |
| 127 | + -p 1433:1433 \ |
| 128 | + -v /tmp/sqlcontainer/mssql-entra-id.pfx:/var/opt/mssql/mssql-entra-id.pfx:ro \ |
| 129 | + -d mcr.microsoft.com/mssql/server:2025-latest |
| 130 | + ``` |
| 131 | + |
| 132 | +1. Verify inside the container: |
| 133 | + |
| 134 | + ```sql |
| 135 | + docker exec -it <container-id> bash |
| 136 | + cat /var/opt/mssql/log/errorlog | grep Entra |
| 137 | + ``` |
| 138 | + |
| 139 | + [!INCLUDE [ssresult-md](../../includes/ssresult-md.md)] |
| 140 | + |
| 141 | + ```output |
| 142 | + Microsoft Entra ID authentication is enabled. This is an informational message only; no user action is required. |
| 143 | + ``` |
| 144 | + |
| 145 | +Continue to the step to [create the Microsoft Entra](#create-microsoft-entra-logins) logins. |
| 146 | + |
| 147 | +## Configure SQL Server containers on Kubernetes |
| 148 | + |
| 149 | +The following diagram describes the steps for this deployment. |
| 150 | + |
| 151 | +:::image type="content" source="media/container-kubernetes-microsoft-entra-deployment/flow-diagram.png" alt-text="Diagram showing the flow diagram for Microsoft Entra ID authentication in a Kubernetes deployment." lightbox="media/container-kubernetes-microsoft-entra-deployment/flow-diagram.png"::: |
| 152 | + |
| 153 | +### Step 1: Create a Secret for the certificate |
| 154 | + |
| 155 | +1. Encode the `.pfx` file: |
| 156 | + |
| 157 | + ```bash |
| 158 | + base64 -w0 mssql-entra-id.pfx |
| 159 | + ``` |
| 160 | + |
| 161 | +1. Create `mssql-entra-cert.yaml`: |
| 162 | + |
| 163 | + ```yaml |
| 164 | + apiVersion: v1 |
| 165 | + kind: Secret |
| 166 | + metadata: |
| 167 | + name: mssql-entra-cert |
| 168 | + type: Opaque |
| 169 | + data: |
| 170 | + mssql-entra-id: <BASE64_ENCODED_CERT> |
| 171 | + ``` |
| 172 | +
|
| 173 | +1. Apply the Secret: |
| 174 | +
|
| 175 | + ```bash |
| 176 | + kubectl apply -f mssql-entra-cert.yaml |
| 177 | + ``` |
| 178 | + |
| 179 | +### Step 2: Create the SA password secret |
| 180 | + |
| 181 | +The following command creates the `sa` account password that you use to sign into your [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] deployment. Replace `<password>` with a strong password. |
| 182 | + |
| 183 | +> [!NOTE] |
| 184 | +> [!INCLUDE [password-complexity](../includes/password-complexity.md)] |
| 185 | +
|
| 186 | +```bash |
| 187 | +kubectl create secret generic mssql \ |
| 188 | + --from-literal=MSSQL_SA_PASSWORD=<password> |
| 189 | +``` |
| 190 | + |
| 191 | +### Step 3: Create the ConfigMap for `mssql.conf` |
| 192 | + |
| 193 | +In this step, replace `aadclientid` with the client ID, and `aadprimarytenant` with the tenant ID of the registered application in Microsoft Entra ID. You can get these details from the Azure portal. |
| 194 | + |
| 195 | +:::image type="content" source="media/container-kubernetes-microsoft-entra-deployment/azure-portal-keys.png" alt-text="Screenshot showing the keys in the Azure portal."::: |
| 196 | + |
| 197 | +1. Create a ConfigMap file named `mssql-conf.yaml`: |
| 198 | + |
| 199 | + ```yaml |
| 200 | + apiVersion: v1 |
| 201 | + kind: ConfigMap |
| 202 | + metadata: |
| 203 | + name: mssql-conf |
| 204 | + data: |
| 205 | + mssql.conf: | |
| 206 | + [EULA] |
| 207 | + accepteula = Y |
| 208 | + |
| 209 | + [sqlagent] |
| 210 | + enabled = false |
| 211 | + |
| 212 | + [licensing] |
| 213 | + azurebilling = false |
| 214 | + |
| 215 | + [network] |
| 216 | + aadcertificatefilepath = /var/opt/mssql/mssql-entra-id.pfx |
| 217 | + aadclientid = <client-id> |
| 218 | + aadprimarytenant = <tenant-id> |
| 219 | + ``` |
| 220 | + |
| 221 | +1. Apply the ConfigMap: |
| 222 | + |
| 223 | + ```bash |
| 224 | + kubectl apply -f mssql-conf.yaml |
| 225 | + ``` |
| 226 | + |
| 227 | +### Step 4: Deploy SQL Server |
| 228 | + |
| 229 | +In this step, you deploy [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)] and enable Microsoft Entra ID authentication. You must mount the ConfigMap and Secret into the [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] container, and use a supported [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] Linux image (for example, `mcr.microsoft.com/mssql/server:2025-latest`). |
| 230 | + |
| 231 | +Make sure that the certificate file path in `mssql.conf` matches the mounted path, and the container runs with the required filesystem permissions. |
| 232 | + |
| 233 | +1. Create a file called `mssql-deployment.yaml` with the following contents: |
| 234 | + |
| 235 | + ```yaml |
| 236 | + apiVersion: apps/v1 |
| 237 | + kind: Deployment |
| 238 | + metadata: |
| 239 | + name: mssql-2025 |
| 240 | + labels: |
| 241 | + app: mssql-2025 |
| 242 | + spec: |
| 243 | + replicas: 1 |
| 244 | + selector: |
| 245 | + matchLabels: |
| 246 | + app: mssql-2025 |
| 247 | + template: |
| 248 | + metadata: |
| 249 | + labels: |
| 250 | + app: mssql-2025 |
| 251 | + spec: |
| 252 | + securityContext: |
| 253 | + fsGroup: 10001 |
| 254 | + containers: |
| 255 | + - name: mssql |
| 256 | + image: mcr.microsoft.com/mssql/server:2025-latest |
| 257 | + imagePullPolicy: IfNotPresent |
| 258 | + ports: |
| 259 | + - name: tds |
| 260 | + containerPort: 1433 |
| 261 | + env: |
| 262 | + - name: ACCEPT_EULA |
| 263 | + value: "Y" |
| 264 | + - name: MSSQL_SA_PASSWORD |
| 265 | + valueFrom: |
| 266 | + secretKeyRef: |
| 267 | + name: mssql |
| 268 | + key: MSSQL_SA_PASSWORD |
| 269 | + - name: MSSQL_PID |
| 270 | + value: "Developer" |
| 271 | + volumeMounts: |
| 272 | + - name: mssql-conf |
| 273 | + mountPath: /var/opt/mssql/mssql.conf |
| 274 | + subPath: mssql.conf |
| 275 | + readOnly: true |
| 276 | + - name: mssql-entra-cert |
| 277 | + mountPath: /var/opt/mssql/mssql-entra-id.pfx |
| 278 | + subPath: mssql-entra-id |
| 279 | + readOnly: true |
| 280 | + volumes: |
| 281 | + - name: mssql-conf |
| 282 | + configMap: |
| 283 | + name: mssql-conf |
| 284 | + items: |
| 285 | + - key: mssql.conf |
| 286 | + path: mssql.conf |
| 287 | + - name: mssql-entra-cert |
| 288 | + secret: |
| 289 | + secretName: mssql-entra-cert |
| 290 | + items: |
| 291 | + - key: mssql-entra-id |
| 292 | + path: mssql-entra-id.pfx |
| 293 | + ``` |
| 294 | +
|
| 295 | +1. Apply the deployment: |
| 296 | +
|
| 297 | + ```bash |
| 298 | + kubectl apply -f mssql-deployment.yaml |
| 299 | + ``` |
| 300 | + |
| 301 | +### Step 5: Create a service |
| 302 | + |
| 303 | +In this step, you create a load balancer service to connect to [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)]. |
| 304 | + |
| 305 | +1. Create the service file named `mssql-service.yaml`. |
| 306 | + |
| 307 | + ```yaml |
| 308 | + apiVersion: v1 |
| 309 | + kind: Service |
| 310 | + metadata: |
| 311 | + name: mssql |
| 312 | + labels: |
| 313 | + app: mssql-2025 |
| 314 | + spec: |
| 315 | + type: LoadBalancer |
| 316 | + selector: |
| 317 | + app: mssql-2025 |
| 318 | + ports: |
| 319 | + - name: tds |
| 320 | + port: 1433 |
| 321 | + targetPort: 1433 |
| 322 | + ``` |
| 323 | +
|
| 324 | +1. Apply the service: |
| 325 | +
|
| 326 | + ```bash |
| 327 | + kubectl apply -f mssql-service.yaml |
| 328 | + ``` |
| 329 | + |
| 330 | +Continue to the step to [create the Microsoft Entra](#create-microsoft-entra-logins) logins. |
| 331 | + |
| 332 | +## Create Microsoft Entra logins |
| 333 | + |
| 334 | +1. Connect to the [!INCLUDE [ssnoversion-md](../../includes/ssnoversion-md.md)] container using SQL Server Management Studio (SSMS), with the `sa` account and password you configured previously. |
| 335 | + |
| 336 | +1. Create your Microsoft Entra-based login: |
| 337 | + |
| 338 | + ```sql |
| 339 | + CREATE LOGIN [user@contoso.com] |
| 340 | + FROM EXTERNAL PROVIDER; |
| 341 | + ``` |
| 342 | + |
| 343 | +1. Optionally, add the Microsoft Entra account to the **sysadmin** fixed server role, so that you can disable the `sa` account. For more information, see [Disable the SA account as a best practice](#disable-the-sa-account-as-a-best-practice) in the next section. |
| 344 | + |
| 345 | + ```sql |
| 346 | + EXECUTE sp_addsrvrolemember |
| 347 | + @loginame = 'user@contoso.com', |
| 348 | + @rolename = 'sysadmin'; |
| 349 | + ``` |
| 350 | + |
| 351 | +You can now authenticate using Microsoft Entra ID with password, integrated authentication, or multifactor authentication (MFA). |
| 352 | + |
| 353 | +### Disable the SA account as a best practice |
| 354 | + |
| 355 | +> [!IMPORTANT] |
| 356 | +> You need these credentials for later steps. Be sure to write down the user ID and password that you enter here. |
| 357 | +
|
| 358 | +[!INCLUDE [connect-with-sa](../includes/connect-with-sa.md)] |
| 359 | + |
| 360 | +## Related content |
| 361 | + |
| 362 | +- [Tutorial: Configure Active Directory authentication with SQL Server on Linux containers](../sql-server-linux-containers-ad-auth-adutil-tutorial.md) |
| 363 | +- [Configure SQL Server settings with environment variables on Linux](../sql-server-linux-configure-environment-variables.md) |
| 364 | +- [Tutorial: Set up Microsoft Entra authentication for SQL Server with app registration](../../relational-databases/security/authentication-access/azure-ad-authentication-sql-server-setup-tutorial.md) |
0 commit comments