After module 3.2, the Kladde's infrastructure is in the repository as Bicep, part of it just as azd generated it in lesson 3.2.5:
sql.bicep with a managed identity as Entra administrator, web-identity.bicep, the deployment script web-roles-sql.bicep
for the database user, and in container-apps.bicep a registry without an admin user, with an identity of its own for the pull. You took
these files over but didn't build them yourself. In this lesson, you understand what happens in them, and you rebuild them to the Kladde's
rules: one identity per app, which also pulls its image, the group Kladde-Operations as the SQL server's administrator instead of an
identity that only a script uses, and roles whose names stay the same on every deployment. If your SQL server still has an administrator
with a password, from an exercise perhaps, that password disappears in the process; azd keeps it as a parameter in plain text under
.azure/<environment>/ (lesson 3.2.6). At the end of the lesson, the Kladde signs in to Azure SQL without a password, and a SQL sign-in
with a name and password is rejected.
One secret from K2 remains in this module: the client secret that the sign-in with Entra ID uses to identify itself (K2, lesson 2.9.5). It disappears only in lesson 3.10.4, when the app identifies itself there with its managed identity. Until then, it's never in the repository and never in a parameter file.
Work on a branch feature/no-keys throughout the module. At the end of the module, you have someone from your circle, a public learning
community, or yourself with a checklist review the pull request for it, "Kladde without keys".
Who is signing in?
When you sign in to Azure, you're a user in an Entra tenant. When a program signs in, it also needs an identity in the tenant. This identity is called a service principal. Roles in Azure always go to a security principal, so a user, a group or a service principal (lesson 3.1.4).
You already know a service principal. For the sign-in with Entra ID, you created an app registration in K2 (lesson 2.6.2). A service principal belongs to it, and the app identified itself with a client secret that was in the user secrets. A secret like that has three weaknesses:
- It expires, and then the app stops, usually on a Friday evening.
- It sits somewhere in plain text, and every copy is a possible leak: in the vault, in the pipeline, on a laptop.
- Whoever knows it is the app. Afterward, nobody can tell whether the app or an attacker with the copied secret did the accessing.
A managed identity is a service principal whose credentials Azure manages itself. Nobody sees them, nobody copies them, nobody has to
renew them. The app asks an endpoint in its environment for a token, and Azure issues it only if the request really comes from the
resource the identity is assigned to. In Container Apps, the environment variables IDENTITY_ENDPOINT and IDENTITY_HEADER point to this
endpoint. With the token, the app then signs in to the service, such as Azure SQL or Key Vault, and the service uses Azure RBAC or its own
permissions to check what it may do.
That works only on resources in Azure that support managed identities: Container Apps, App Service, Functions, virtual machines and more. On your own machine, there's no managed identity. There, the app signs in with your own sign-in, more on that in a moment.