Managed Identities - Simply Explained
Managing passwords, connection strings, client secrets, and certificates has always been one of the biggest challenges when building secure cloud applications. Every application that connects to Azure Storage, Azure Key Vault, Azure SQL Database, or other Azure services traditionally required credentials that had to be stored, protected, rotated, and monitored. Over time, this creates secret sprawl, increases security risks, and adds operational complexity. In this episode of Microsoft Knowledge Nuggets, we explain Azure Managed Identities in simple terms and show why Microsoft considers them the future of authentication for Azure workloads. You'll discover how Managed Identities completely eliminate the need to store secrets while making your applications more secure, easier to manage, and ready for modern cloud architectures.
HOW MANAGED IDENTITIES WORK AND WHY THEY MATTER
Instead of storing passwords or client secrets inside your application, Azure automatically creates a trusted identity in Microsoft Entra ID for your workload. Whenever your application needs access to Azure Storage, Key Vault, Cosmos DB, Service Bus, SQL Database, or another Azure service, it simply requests a temporary access token through the Azure Instance Metadata Service (IMDS). Azure validates the workload's identity, issues a short-lived OAuth token, and handles all certificate rotation behind the scenes. Your application never stores, generates, or even sees a password, dramatically reducing the attack surface while simplifying authentication for developers and administrators alike.
SYSTEM-ASSIGNED VS USER-ASSIGNED MANAGED IDENTITIES
One of the most important concepts covered in this episode is understanding the difference between System-Assigned and User-Assigned Managed Identities. You'll learn when a System-Assigned Identity is the ideal choice for a single Azure resource such as an App Service, Azure Function, or Virtual Machine, and when a User-Assigned Identity provides greater flexibility by allowing multiple Azure resources to share the same identity and permissions. We also discuss lifecycle management, regional considerations, migration scenarios, and practical recommendations that help you choose the right identity model for production workloads.
REAL-WORLD IMPLEMENTATION, SECURITY BENEFITS, AND BEST PRACTICES
Beyond the theory, this episode walks through a complete real-world deployment from local development to production. You'll see how DefaultAzureCredential automatically selects the correct authentication method, how Azure RBAC replaces connection strings with permission-based access, and how Managed Identities integrate seamlessly with Azure Storage, Azure Key Vault, Azure SQL, Azure Service Bus, Event Hubs, and many other Microsoft services. We also compare traditional service principals with Managed Identities, explain when Managed Identities cannot be used, and explore workload identity federation for hybrid and multi-cloud environments. By the end of the episode, you'll understand why passwordless authentication has become Microsoft's recommended security model for modern Azure applications and why every new Azure project should start with Managed Identities instead of secrets.
Become a supporter of this podcast: https://www.spreaker.com/podcast/m365-fm-modern-work-security-and-productivity-with-microsoft-365--6704921/support.
🚀 Want to be part of m365.fm?
Then stop just listening… and start showing up.
👉 Connect with me on LinkedIn and let’s make something happen:
- 🎙️ Be a podcast guest and share your story
- 🎧 Host your own episode (yes, seriously)
- 💡 Pitch topics the community actually wants to hear
- 🌍 Build your personal brand in the Microsoft 365 space
This isn’t just a podcast — it’s a platform for people who take action.
🔥 Most people wait. The best ones don’t.
👉 Connect with me on LinkedIn and send me a message:
"I want in"
Let’s build something awesome 👊
00:00:00,000 --> 00:00:02,260
Have you ever opened a config file and thought,
2
00:00:02,260 --> 00:00:04,460
"I really hope nobody finds this connection string"
3
00:00:04,460 --> 00:00:06,380
or maybe you've been the person who accidentally pushed
4
00:00:06,380 --> 00:00:08,900
a secret to GitHub and spent the next hour rotating keys
5
00:00:08,900 --> 00:00:10,340
before anyone noticed?
6
00:00:10,340 --> 00:00:12,380
If you've worked with Azure for any length of time,
7
00:00:12,380 --> 00:00:13,980
you've dealt with the credential problem.
8
00:00:13,980 --> 00:00:16,060
Service principles with client secrets,
9
00:00:16,060 --> 00:00:18,660
certificates that expire at the worst possible moment,
10
00:00:18,660 --> 00:00:21,500
connection strings spread across repos and deployment scripts.
11
00:00:21,500 --> 00:00:23,020
It's a mess.
12
00:00:23,020 --> 00:00:23,860
But here's the thing,
13
00:00:23,860 --> 00:00:25,820
what if your app didn't need secrets at all?
14
00:00:25,820 --> 00:00:27,660
What if you could give it its own identity
15
00:00:27,660 --> 00:00:29,140
just like you give a person one
16
00:00:29,140 --> 00:00:30,620
and let Azure handle the rest?
17
00:00:30,620 --> 00:00:32,820
Think of it like a digital ID card for your app
18
00:00:32,820 --> 00:00:35,380
that ID card shows Azure who the app is
19
00:00:35,380 --> 00:00:36,580
and what it's allowed to do.
20
00:00:36,580 --> 00:00:39,220
And that's exactly what managed identities are all about.
21
00:00:39,220 --> 00:00:41,620
In this episode, we're breaking down what they are,
22
00:00:41,620 --> 00:00:43,020
the two types you need to know
23
00:00:43,020 --> 00:00:45,260
and why Microsoft is betting on this approach
24
00:00:45,260 --> 00:00:46,620
for Azure security.
25
00:00:46,620 --> 00:00:48,940
By the end, you'll understand why managed identities
26
00:00:48,940 --> 00:00:52,100
are becoming the standard for any real Azure workload.
27
00:00:52,100 --> 00:00:54,420
The problem, secrets, secrets everywhere.
28
00:00:54,420 --> 00:00:56,460
Let's start with the old way of doing things.
29
00:00:56,460 --> 00:00:58,380
You build an app that needs to talk to Azure storage
30
00:00:58,380 --> 00:01:00,140
so you grab a connection string,
31
00:01:00,140 --> 00:01:01,700
then it needs to read from key vaults
32
00:01:01,700 --> 00:01:02,820
so you get another secret,
33
00:01:02,820 --> 00:01:04,140
then it has to write to a database
34
00:01:04,140 --> 00:01:05,540
which means another credential.
35
00:01:05,540 --> 00:01:06,540
Before you know it,
36
00:01:06,540 --> 00:01:07,860
you're managing a dozen different secrets,
37
00:01:07,860 --> 00:01:09,420
each one a ticking time bomb.
38
00:01:09,420 --> 00:01:11,660
Security people call this secrets brawl.
39
00:01:11,660 --> 00:01:13,580
Those credentials end up in app settings,
40
00:01:13,580 --> 00:01:15,620
environment variables, deployment scripts
41
00:01:15,620 --> 00:01:17,940
and sometimes hard coded and source code.
42
00:01:17,940 --> 00:01:20,820
A quick search on GitHub for accidentally committed secrets
43
00:01:20,820 --> 00:01:23,020
shows this isn't just a hypothetical problem.
44
00:01:23,020 --> 00:01:24,260
It happens every single day.
45
00:01:24,260 --> 00:01:25,620
Then there's the rotation problem.
46
00:01:25,620 --> 00:01:27,260
Rotating secrets every 90 days
47
00:01:27,260 --> 00:01:29,220
is what security best practices recommend.
48
00:01:29,220 --> 00:01:30,540
In theory, that sounds great,
49
00:01:30,540 --> 00:01:32,660
but in practice, nobody does it consistently.
50
00:01:32,660 --> 00:01:33,980
Teams forget, scripts break
51
00:01:33,980 --> 00:01:35,180
and then you have a certificate
52
00:01:35,180 --> 00:01:36,780
that expires at 3 a.m. on a Saturday
53
00:01:36,780 --> 00:01:39,060
taking your entire production environment down.
54
00:01:39,060 --> 00:01:40,620
The human factor makes it worse.
55
00:01:40,620 --> 00:01:42,340
Secrets get shared in emails,
56
00:01:42,340 --> 00:01:43,620
paste it into chat threads
57
00:01:43,620 --> 00:01:46,020
or written on sticky notes attached to monitors.
58
00:01:46,020 --> 00:01:47,180
When someone leaves the company,
59
00:01:47,180 --> 00:01:49,980
nobody remembers to rotate the credentials they had access to.
60
00:01:49,980 --> 00:01:52,580
Now scale that up to a microservices architecture
61
00:01:52,580 --> 00:01:54,700
where every component needs its own identity.
62
00:01:54,700 --> 00:01:56,340
Suddenly, you're not managing a dozen secrets,
63
00:01:56,340 --> 00:01:57,260
but 50.
64
00:01:57,260 --> 00:01:58,420
When something goes wrong,
65
00:01:58,420 --> 00:02:00,420
good luck figuring out which service did what,
66
00:02:00,420 --> 00:02:02,060
because audit logs become useless
67
00:02:02,060 --> 00:02:04,220
when multiple services share the same credential.
68
00:02:04,220 --> 00:02:05,500
You see an action happened,
69
00:02:05,500 --> 00:02:08,260
but you have no idea which service actually performed it.
70
00:02:08,260 --> 00:02:11,300
So Microsoft looked at this mess and asked a simple question,
71
00:02:11,300 --> 00:02:13,940
what if we just eliminated the secret entirely?
72
00:02:13,940 --> 00:02:15,900
The solution managed identity.
73
00:02:15,900 --> 00:02:17,100
So here's the idea.
74
00:02:17,100 --> 00:02:18,700
Instead of handing your app a secret,
75
00:02:18,700 --> 00:02:19,860
it has to keep safe.
76
00:02:19,860 --> 00:02:21,540
You give it an identity.
77
00:02:21,540 --> 00:02:23,500
A real identity inside Microsoft EntraID,
78
00:02:23,500 --> 00:02:24,740
just like a user account,
79
00:02:24,740 --> 00:02:27,220
but built for a workload as your creates it,
80
00:02:27,220 --> 00:02:28,300
ties it to your resource
81
00:02:28,300 --> 00:02:31,020
and handles all the credential management behind the scenes.
82
00:02:31,020 --> 00:02:32,460
You never see a password,
83
00:02:32,460 --> 00:02:33,620
you never generate a key,
84
00:02:33,620 --> 00:02:36,300
you never install a certificate, it just works.
85
00:02:36,300 --> 00:02:37,540
Now here's what's interesting.
86
00:02:37,540 --> 00:02:40,620
Under the hood, a managed identity is still a service principle.
87
00:02:40,620 --> 00:02:42,100
The same kind of object that exists
88
00:02:42,100 --> 00:02:44,660
when you register an app in EntraID.
89
00:02:44,660 --> 00:02:47,420
The difference is that you don't manage the credential.
90
00:02:47,420 --> 00:02:48,260
Azure does.
91
00:02:48,260 --> 00:02:49,420
It creates the identity,
92
00:02:49,420 --> 00:02:52,460
rotates the certificate automatically every 45 days or so,
93
00:02:52,460 --> 00:02:54,620
and if you're using a system assigned identity,
94
00:02:54,620 --> 00:02:57,140
it cleans everything up when the resource is deleted.
95
00:02:57,140 --> 00:02:58,580
No orphaned accounts,
96
00:02:58,580 --> 00:03:00,940
no expired secrets causing outages,
97
00:03:00,940 --> 00:03:03,580
no manual rotation scripts that nobody remembers to run.
98
00:03:03,580 --> 00:03:04,940
So how does it actually work?
99
00:03:04,940 --> 00:03:06,420
The magic happens through something called
100
00:03:06,420 --> 00:03:09,260
the Instance Metadata Service or IMDS.
101
00:03:09,260 --> 00:03:11,340
Every Azure resource has an internal endpoint
102
00:03:11,340 --> 00:03:12,820
at a specific IP address,
103
00:03:12,820 --> 00:03:16,580
169.254, 169.254.
104
00:03:16,580 --> 00:03:18,340
When your code needs to authenticate,
105
00:03:18,340 --> 00:03:20,580
it sends a request to this endpoint saying,
106
00:03:20,580 --> 00:03:23,020
I need a token for Azure storage.
107
00:03:23,020 --> 00:03:24,940
The Azure fabric checks that this resource
108
00:03:24,940 --> 00:03:27,140
actually has a managed identity enabled,
109
00:03:27,140 --> 00:03:29,860
and if it does, IMDS returns and access token,
110
00:03:29,860 --> 00:03:32,980
your code takes that token and uses it to call the service it needs.
111
00:03:32,980 --> 00:03:34,140
Think about what that means.
112
00:03:34,140 --> 00:03:35,500
Your code never sees a secret.
113
00:03:35,500 --> 00:03:36,460
It doesn't store one.
114
00:03:36,460 --> 00:03:38,260
It doesn't read one from a config file.
115
00:03:38,260 --> 00:03:40,060
It just asks for a token and gets one.
116
00:03:40,060 --> 00:03:42,180
The Azure platform itself acts as the proof
117
00:03:42,180 --> 00:03:44,140
that your app is who it says it is.
118
00:03:44,140 --> 00:03:47,060
This changes the entire mindset of building on Azure.
119
00:03:47,060 --> 00:03:48,060
The old way was,
120
00:03:48,060 --> 00:03:49,820
I need my app to talk to storage,
121
00:03:49,820 --> 00:03:51,340
so I need a connection string.
122
00:03:51,340 --> 00:03:52,340
The new way is,
123
00:03:52,340 --> 00:03:53,820
I need my app to talk to storage.
124
00:03:53,820 --> 00:03:55,980
Can I use a managed identity?
125
00:03:55,980 --> 00:03:58,100
And in almost every case, the answer is yes.
126
00:03:58,100 --> 00:03:59,260
Azure storage supports it,
127
00:03:59,260 --> 00:04:00,460
Key Vault supports it,
128
00:04:00,460 --> 00:04:02,260
SQL database, service bus,
129
00:04:02,260 --> 00:04:04,140
event hubs, Cosmos DB,
130
00:04:04,140 --> 00:04:05,380
the list keeps growing.
131
00:04:05,380 --> 00:04:07,340
When you're building a new Azure workload,
132
00:04:07,340 --> 00:04:09,300
managed identity should be your first thought,
133
00:04:09,300 --> 00:04:10,180
not an after thought.
134
00:04:10,180 --> 00:04:12,140
No more storing secrets in app settings,
135
00:04:12,140 --> 00:04:14,660
no more environment variables with connection strings,
136
00:04:14,660 --> 00:04:17,700
no more putting credentials in Key Vault just for authentication.
137
00:04:17,700 --> 00:04:20,460
You grant permissions directly to the identity using our back
138
00:04:20,460 --> 00:04:22,220
and the platform handles the rest.
139
00:04:22,220 --> 00:04:24,820
System assigned versus user assigned.
140
00:04:24,820 --> 00:04:27,220
Now let's talk about the two flavors of managed identities
141
00:04:27,220 --> 00:04:29,180
because this is where people get confused.
142
00:04:29,180 --> 00:04:30,220
They're not the same thing
143
00:04:30,220 --> 00:04:32,860
and picking the wrong one can cause headaches later.
144
00:04:32,860 --> 00:04:35,540
The core difference comes down to one word, life cycle.
145
00:04:35,540 --> 00:04:37,220
Who owns the identity's lifespan?
146
00:04:37,220 --> 00:04:39,780
Who decides when it's created and when it's destroyed?
147
00:04:39,780 --> 00:04:41,660
System assigned is the simpler of the two.
148
00:04:41,660 --> 00:04:43,140
You enable it on a resource,
149
00:04:43,140 --> 00:04:45,900
a virtual machine, an app service, a single function,
150
00:04:45,900 --> 00:04:47,460
and Azure creates an identity
151
00:04:47,460 --> 00:04:49,140
that is tied directly to that resource.
152
00:04:49,140 --> 00:04:51,340
They share a life when the resource is born,
153
00:04:51,340 --> 00:04:52,380
the identity is born.
154
00:04:52,380 --> 00:04:53,460
When you delete the resource,
155
00:04:53,460 --> 00:04:57,220
the identity is deleted too, one to one relationship.
156
00:04:57,220 --> 00:04:59,940
The beauty of System assigned is that there's almost no management
157
00:04:59,940 --> 00:05:00,700
overhead.
158
00:05:00,700 --> 00:05:01,940
You flip a switch in the portal
159
00:05:01,940 --> 00:05:04,060
or add a single line in your bicep template,
160
00:05:04,060 --> 00:05:04,900
and it's done.
161
00:05:04,900 --> 00:05:06,340
No separate resource to create,
162
00:05:06,340 --> 00:05:07,620
no cleanup to worry about.
163
00:05:07,620 --> 00:05:09,460
If you have a single web app that needs to read
164
00:05:09,460 --> 00:05:11,940
from its own storage account, this is your answer.
165
00:05:11,940 --> 00:05:13,820
Enable it, grant the role, move on,
166
00:05:13,820 --> 00:05:16,100
but there's a catch because the identity is tied
167
00:05:16,100 --> 00:05:17,260
to that specific resource.
168
00:05:17,260 --> 00:05:19,980
If you delete the resource, the identity disappears.
169
00:05:19,980 --> 00:05:21,260
That's fine if you're done with it.
170
00:05:21,260 --> 00:05:22,980
But what if you're migrating workloads?
171
00:05:22,980 --> 00:05:24,460
What if you need to rebuild a VM
172
00:05:24,460 --> 00:05:26,180
and want to keep the same identity?
173
00:05:26,180 --> 00:05:28,100
With System assigned, you'd have to re-enable it
174
00:05:28,100 --> 00:05:29,340
and re-ground permissions.
175
00:05:29,340 --> 00:05:31,180
Not a disaster, but an extra step.
176
00:05:31,180 --> 00:05:33,140
User assigned solves that problem.
177
00:05:33,140 --> 00:05:35,100
Here you create the identity as a standalone
178
00:05:35,100 --> 00:05:36,300
Azure resource first.
179
00:05:36,300 --> 00:05:39,340
It exists independently with its own life cycle.
180
00:05:39,340 --> 00:05:41,500
Then you attach it to one or more resources,
181
00:05:41,500 --> 00:05:44,180
virtual machines, app services, whatever you need,
182
00:05:44,180 --> 00:05:45,820
one identity, many resources.
183
00:05:45,820 --> 00:05:47,420
This is a many to one relationship.
184
00:05:47,420 --> 00:05:49,020
The identity lives on its own.
185
00:05:49,020 --> 00:05:51,060
You can delete all the resources that use it
186
00:05:51,060 --> 00:05:52,420
and the identity stays.
187
00:05:52,420 --> 00:05:55,260
You can attach the same identity to five different services
188
00:05:55,260 --> 00:05:57,060
and they all share the same permissions.
189
00:05:57,060 --> 00:06:00,300
That's incredibly useful when you have a shared development cluster
190
00:06:00,300 --> 00:06:03,740
where multiple services all need access to the same key vault.
191
00:06:03,740 --> 00:06:05,620
Instead of granting permissions five times
192
00:06:05,620 --> 00:06:07,180
to five different identities,
193
00:06:07,180 --> 00:06:09,780
you grant it once to a user assigned identity
194
00:06:09,780 --> 00:06:10,860
and attach it everywhere.
195
00:06:10,860 --> 00:06:11,940
So when do you pick which?
196
00:06:11,940 --> 00:06:13,380
Here's a simple framework.
197
00:06:13,380 --> 00:06:15,980
Use System assigned when you have a single resource
198
00:06:15,980 --> 00:06:17,540
that needs its own identity
199
00:06:17,540 --> 00:06:19,780
and you want zero management overhead.
200
00:06:19,780 --> 00:06:22,140
A web app that talks to its own database.
201
00:06:22,140 --> 00:06:24,620
A function that writes to its own storage account.
202
00:06:24,620 --> 00:06:26,700
A VM that needs to pull secrets from key vault,
203
00:06:26,700 --> 00:06:28,340
enable it, grant access done.
204
00:06:28,340 --> 00:06:30,540
Use user assigned when you need the same identity
205
00:06:30,540 --> 00:06:32,020
across multiple resources.
206
00:06:32,020 --> 00:06:34,300
When you want the identity to outlive the resources
207
00:06:34,300 --> 00:06:36,460
it's attached to, when you need to control
208
00:06:36,460 --> 00:06:37,980
the life cycle separately,
209
00:06:37,980 --> 00:06:39,700
maybe you want to pre-create identities
210
00:06:39,700 --> 00:06:41,420
in a central management subscription
211
00:06:41,420 --> 00:06:43,340
and let application teams attach them.
212
00:06:43,340 --> 00:06:45,340
User assigned gives you that flexibility.
213
00:06:45,340 --> 00:06:47,380
One more thing, user assigned identities
214
00:06:47,380 --> 00:06:48,780
are regional resources.
215
00:06:48,780 --> 00:06:50,740
You create them in a specific region
216
00:06:50,740 --> 00:06:52,500
but the service principle behind them
217
00:06:52,500 --> 00:06:54,260
lives in enter ID globally.
218
00:06:54,260 --> 00:06:56,620
So you can attach a user assigned identity created
219
00:06:56,620 --> 00:06:58,740
in East, US to a resource in West Europe.
220
00:06:58,740 --> 00:07:01,620
The identity works anywhere as you are runs.
221
00:07:01,620 --> 00:07:03,500
How they actually work under the hood.
222
00:07:03,500 --> 00:07:05,060
So what actually happens when your code
223
00:07:05,060 --> 00:07:06,660
uses a managed identity?
224
00:07:06,660 --> 00:07:07,860
Let's walk through the flow.
225
00:07:07,860 --> 00:07:10,100
Your code needs to talk to Azure storage.
226
00:07:10,100 --> 00:07:11,540
Instead of reading a connection string
227
00:07:11,540 --> 00:07:14,220
from a config file, it calls the identity endpoint.
228
00:07:14,220 --> 00:07:16,060
If you're using the Azure SDKs,
229
00:07:16,060 --> 00:07:18,820
this happens automatically through default Azure credential.
230
00:07:18,820 --> 00:07:20,340
You don't write any special code.
231
00:07:20,340 --> 00:07:21,940
You just create a blob service client
232
00:07:21,940 --> 00:07:23,380
without passing credentials
233
00:07:23,380 --> 00:07:25,900
and the SDK handles the rest.
234
00:07:25,900 --> 00:07:28,140
That request hits the instance metadata service
235
00:07:28,140 --> 00:07:31,540
at 169.254, 169.254.
236
00:07:31,540 --> 00:07:32,940
Think of it like an internal phone number
237
00:07:32,940 --> 00:07:34,380
that every Azure resource has.
238
00:07:34,380 --> 00:07:35,940
You can't reach it from your laptop
239
00:07:35,940 --> 00:07:37,820
that only exists inside the Azure fabric.
240
00:07:37,820 --> 00:07:40,380
IMDS then checks with the Azure control plane.
241
00:07:40,380 --> 00:07:42,500
Does this resource have a managed identity enabled?
242
00:07:42,500 --> 00:07:43,820
If not, you get an error.
243
00:07:43,820 --> 00:07:46,260
If it does, the platform confirms the identity.
244
00:07:46,260 --> 00:07:47,980
Next, IMDS returns an access token.
245
00:07:47,980 --> 00:07:50,140
It's a standard OAuth 2.0 token
246
00:07:50,140 --> 00:07:52,020
like any other token from EntraID.
247
00:07:52,020 --> 00:07:53,900
It includes the identity's client ID,
248
00:07:53,900 --> 00:07:55,940
the target resource and a timestamp.
249
00:07:55,940 --> 00:07:58,900
The token is short-lived, typically 60 to 90 minutes.
250
00:07:58,900 --> 00:08:01,860
Your code takes that token and calls Azure storage.
251
00:08:01,860 --> 00:08:04,780
The storage service validates the token against EntraID
252
00:08:04,780 --> 00:08:05,940
and checks the ABIAC permissions
253
00:08:05,940 --> 00:08:07,780
you assigned to the managed identity.
254
00:08:07,780 --> 00:08:09,780
If the identity has storage blob data reader
255
00:08:09,780 --> 00:08:12,140
on that storage account, the request goes through.
256
00:08:12,140 --> 00:08:13,420
If not, you get a 403.
257
00:08:13,420 --> 00:08:16,540
Here's the thing, at no point did your code handle the secret.
258
00:08:16,540 --> 00:08:19,660
The platform itself proved the resources identity.
259
00:08:19,660 --> 00:08:21,740
The Azure fabric knows what resources running,
260
00:08:21,740 --> 00:08:24,660
where it's running and that it has a managed identity.
261
00:08:24,660 --> 00:08:25,940
It's not checking a password.
262
00:08:25,940 --> 00:08:27,580
It's checking the resources, existence,
263
00:08:27,580 --> 00:08:29,180
and configuration inside Azure
264
00:08:29,180 --> 00:08:31,620
compared that to the old service principle approach.
265
00:08:31,620 --> 00:08:33,380
You needed three things, the tenant ID,
266
00:08:33,380 --> 00:08:36,260
the client ID, and a client's secret or certificate.
267
00:08:36,260 --> 00:08:38,300
Your code has to read those values from somewhere.
268
00:08:38,300 --> 00:08:40,460
Environment variables, key vault, a config file,
269
00:08:40,460 --> 00:08:42,580
every one of those is a potential leak point.
270
00:08:42,580 --> 00:08:44,300
Everyone requires manual rotation.
271
00:08:44,300 --> 00:08:46,340
Everyone is something an attacker could steal.
272
00:08:46,340 --> 00:08:49,420
With managed identities, your code doesn't specify any of that.
273
00:08:49,420 --> 00:08:51,940
Default as your credential automatically detects.
274
00:08:51,940 --> 00:08:53,740
It's running inside an Azure resource
275
00:08:53,740 --> 00:08:55,340
with a managed identity and uses it.
276
00:08:55,340 --> 00:08:57,420
If you run the same code locally on your laptop,
277
00:08:57,420 --> 00:08:59,100
default as your credential falls back
278
00:08:59,100 --> 00:09:00,660
to your personal developer credentials.
279
00:09:00,660 --> 00:09:03,300
You don't change the code, you don't change the configuration.
280
00:09:03,300 --> 00:09:05,700
The SDK handles the environment detection for you.
281
00:09:05,700 --> 00:09:07,660
The tokens refresh automatically.
282
00:09:07,660 --> 00:09:09,300
Your code doesn't worry about expiration.
283
00:09:09,300 --> 00:09:12,060
The SDK caches the token and requests a new one
284
00:09:12,060 --> 00:09:13,500
before the old one expires.
285
00:09:13,500 --> 00:09:14,700
This all happens in the background.
286
00:09:14,700 --> 00:09:16,900
You just call the service and it works.
287
00:09:16,900 --> 00:09:18,020
One thing to be aware of,
288
00:09:18,020 --> 00:09:20,380
permission changes don't take effect instantly.
289
00:09:20,380 --> 00:09:23,060
Because tokens are cached for up to 24 hours on the back end,
290
00:09:23,060 --> 00:09:25,820
if you grant a new R-back role to a managed identity,
291
00:09:25,820 --> 00:09:28,380
it might take a while before the identity can use it.
292
00:09:28,380 --> 00:09:29,540
This is by design.
293
00:09:29,540 --> 00:09:32,300
It reduces load on the authentication infrastructure,
294
00:09:32,300 --> 00:09:34,620
but it means you can't expect instant propagation.
295
00:09:34,620 --> 00:09:35,900
If you need immediate access,
296
00:09:35,900 --> 00:09:37,380
you might need to restart the service
297
00:09:37,380 --> 00:09:39,580
or wait for the cache to clear.
298
00:09:39,580 --> 00:09:42,020
Real-world scenario from dev to production.
299
00:09:42,020 --> 00:09:43,260
Let's make this concrete.
300
00:09:43,260 --> 00:09:45,860
Imagine a simple web API that writes to Azure storage
301
00:09:45,860 --> 00:09:47,660
and reads secrets from Key Vault.
302
00:09:47,660 --> 00:09:49,700
We'll follow it from your laptop to production
303
00:09:49,700 --> 00:09:51,220
in development you're running locally.
304
00:09:51,220 --> 00:09:54,180
Visual Studio, VS Code, whatever tool you use.
305
00:09:54,180 --> 00:09:55,620
Default as your credential kicks in
306
00:09:55,620 --> 00:09:57,700
and picks up your personal developer credentials.
307
00:09:57,700 --> 00:10:00,020
The same ones you use to sign into the Azure portal.
308
00:10:00,020 --> 00:10:01,740
You don't need a managed identity here.
309
00:10:01,740 --> 00:10:03,380
You don't need a service principle.
310
00:10:03,380 --> 00:10:05,580
Your own user account handles authentication
311
00:10:05,580 --> 00:10:07,140
while you're building and testing.
312
00:10:07,140 --> 00:10:08,220
Now it's time to deploy.
313
00:10:08,220 --> 00:10:10,380
You push your code to Azure app service.
314
00:10:10,380 --> 00:10:12,340
First thing you do is enable system assigned
315
00:10:12,340 --> 00:10:14,180
managed identity on that app service.
316
00:10:14,180 --> 00:10:17,220
One toggle in the portal or one line in your bicep template.
317
00:10:17,220 --> 00:10:18,460
That's it.
318
00:10:18,460 --> 00:10:20,260
Next, you grant permissions.
319
00:10:20,260 --> 00:10:22,540
Your API needs to write blobs to a storage account
320
00:10:22,540 --> 00:10:24,100
and read secrets from Key Vault.
321
00:10:24,100 --> 00:10:25,540
You assign two R-back roles.
322
00:10:25,540 --> 00:10:28,060
Storage Blob Data contributor on the storage account
323
00:10:28,060 --> 00:10:30,500
and Key Vault secrets user on the Key Vault.
324
00:10:30,500 --> 00:10:32,980
Both assigned to the managed identities principle ID.
325
00:10:32,980 --> 00:10:34,260
Notice what you didn't do.
326
00:10:34,260 --> 00:10:35,980
You didn't generate a connection string.
327
00:10:35,980 --> 00:10:37,340
You didn't create a client secret.
328
00:10:37,340 --> 00:10:38,980
You didn't store anything in app settings.
329
00:10:38,980 --> 00:10:40,460
You didn't put credentials in Key Vault
330
00:10:40,460 --> 00:10:41,780
just to retrieve them later.
331
00:10:41,780 --> 00:10:43,940
You granted permissions directly to the identity
332
00:10:43,940 --> 00:10:45,660
and the platform handles the rest.
333
00:10:45,660 --> 00:10:47,180
The app starts working immediately.
334
00:10:47,180 --> 00:10:48,500
No secret rotation scripts.
335
00:10:48,500 --> 00:10:49,780
No expiry dates to track.
336
00:10:49,780 --> 00:10:51,260
No works on my machine problems
337
00:10:51,260 --> 00:10:52,980
because the authentication method changes
338
00:10:52,980 --> 00:10:54,220
between environments.
339
00:10:54,220 --> 00:10:56,740
Default as your credential handles that transparently.
340
00:10:56,740 --> 00:10:57,980
Now you scale out.
341
00:10:57,980 --> 00:11:00,340
You add more instances to your app service plan.
342
00:11:00,340 --> 00:11:02,340
Every new instance automatically shares
343
00:11:02,340 --> 00:11:04,500
the same system assigned identity.
344
00:11:04,500 --> 00:11:06,420
You don't need to configure anything.
345
00:11:06,420 --> 00:11:08,300
The new instances start serving requests
346
00:11:08,300 --> 00:11:10,220
and authenticating with the same identity
347
00:11:10,220 --> 00:11:11,380
using the same permissions.
348
00:11:11,380 --> 00:11:12,260
It just works.
349
00:11:12,260 --> 00:11:14,540
But then you add a second service, a background processor
350
00:11:14,540 --> 00:11:16,060
that reads from the same storage account
351
00:11:16,060 --> 00:11:17,300
and processes files.
352
00:11:17,300 --> 00:11:20,180
This is where user assigned identities shine.
353
00:11:20,180 --> 00:11:21,660
Instead of enabling system assigned
354
00:11:21,660 --> 00:11:24,100
on the processor and granting the same permissions again,
355
00:11:24,100 --> 00:11:26,100
you create a user assigned identity.
356
00:11:26,100 --> 00:11:29,380
You granted storage Blob Data Reader on the storage account.
357
00:11:29,380 --> 00:11:30,940
Then you attach that same identity
358
00:11:30,940 --> 00:11:33,460
to both the web API and the background processor.
359
00:11:33,460 --> 00:11:35,380
One permission granted to services covered.
360
00:11:35,380 --> 00:11:37,180
Now consider environment isolation.
361
00:11:37,180 --> 00:11:39,780
You want separate identities for dev, test, and prod.
362
00:11:39,780 --> 00:11:42,180
With user assigned identities, you create three,
363
00:11:42,180 --> 00:11:43,380
one per environment.
364
00:11:43,380 --> 00:11:46,300
Each one gets permissions scoped to its own resources.
365
00:11:46,300 --> 00:11:49,180
A token obtained in dev cannot reach production.
366
00:11:49,180 --> 00:11:50,940
Even if someone somehow extracts a token
367
00:11:50,940 --> 00:11:53,140
from your dev environment, it's worthless against
368
00:11:53,140 --> 00:11:53,980
prod resources.
369
00:11:53,980 --> 00:11:56,260
The audience and the permissions simply don't match.
370
00:11:56,260 --> 00:11:57,540
Your deployment pipeline itself
371
00:11:57,540 --> 00:11:59,380
doesn't need to handle secrets either.
372
00:11:59,380 --> 00:12:02,020
The CI/CD runner, whether it's Azure DevOps, GitHub
373
00:12:02,020 --> 00:12:04,340
actions, or something else, can use a managed identity
374
00:12:04,340 --> 00:12:06,300
to deploy resources and assigned permissions.
375
00:12:06,300 --> 00:12:09,380
No service principle secrets stored in pipeline variables.
376
00:12:09,380 --> 00:12:11,580
No certificate files uploaded to the build agent.
377
00:12:11,580 --> 00:12:14,180
The pipeline authenticates using its own identity,
378
00:12:14,180 --> 00:12:15,660
granted through R-Back.
379
00:12:15,660 --> 00:12:17,460
The old world versus the new world.
380
00:12:17,460 --> 00:12:20,020
Let's put this side by side so you can really see the difference.
381
00:12:20,020 --> 00:12:22,260
In the old world, you'd create a service principle,
382
00:12:22,260 --> 00:12:25,500
generate a client secret, and store that secret in Key Vault.
383
00:12:25,500 --> 00:12:27,780
Then you'd write code to retrieve it at runtime.
384
00:12:27,780 --> 00:12:29,140
You'd set up a rotation schedule.
385
00:12:29,140 --> 00:12:32,540
Every 90 days, generate a new secret, update Key Vault,
386
00:12:32,540 --> 00:12:35,300
test that nothing broke, and hope you didn't miss any of the places
387
00:12:35,300 --> 00:12:36,420
that secret was used.
388
00:12:36,420 --> 00:12:38,180
That's a lot of moving parts, and one mistake
389
00:12:38,180 --> 00:12:39,620
could bring everything down.
390
00:12:39,620 --> 00:12:41,580
In the new world, you enable managed identity,
391
00:12:41,580 --> 00:12:43,700
assign an R-Back role, and you're done.
392
00:12:43,700 --> 00:12:44,980
No secret to rotate.
393
00:12:44,980 --> 00:12:46,740
No Key Vault call just for authentication.
394
00:12:46,740 --> 00:12:49,260
It's like having a smart badge that works everywhere automatically.
395
00:12:49,260 --> 00:12:50,180
That's the magic of it.
396
00:12:50,180 --> 00:12:52,060
The old world had a specific failure mode
397
00:12:52,060 --> 00:12:53,940
that kept security teams up at night.
398
00:12:53,940 --> 00:12:55,620
A developer checks in a secret by accident,
399
00:12:55,620 --> 00:12:57,420
and suddenly you have a security incident.
400
00:12:57,420 --> 00:12:59,860
You're rotating the secret, notifying the team, auditing
401
00:12:59,860 --> 00:13:01,340
who might have accessed it.
402
00:13:01,340 --> 00:13:02,420
All hands on deck.
403
00:13:02,420 --> 00:13:05,060
In the new world, there are no secrets to check in.
404
00:13:05,060 --> 00:13:07,420
The credential doesn't exist in your code base or your config
405
00:13:07,420 --> 00:13:08,140
files.
406
00:13:08,140 --> 00:13:10,660
It exists only inside the Azure fabric, managed,
407
00:13:10,660 --> 00:13:12,940
and rotated automatically by the platform.
408
00:13:12,940 --> 00:13:15,700
The old world also had what I call the 3am problem.
409
00:13:15,700 --> 00:13:17,700
A certificate expires on a Saturday night.
410
00:13:17,700 --> 00:13:19,060
Your production environment goes down.
411
00:13:19,060 --> 00:13:22,020
You get paged, you scramble to generate a new certificate,
412
00:13:22,020 --> 00:13:24,740
update the service principle, restart the service.
413
00:13:24,740 --> 00:13:27,020
Meanwhile, your users stare at error pages.
414
00:13:27,020 --> 00:13:29,740
In the new world, Azure rotates the credential for you.
415
00:13:29,740 --> 00:13:31,660
Every 45 days or so, the certificate
416
00:13:31,660 --> 00:13:34,140
behind your managed identity is replaced automatically.
417
00:13:34,140 --> 00:13:35,540
You never even know what happened.
418
00:13:35,540 --> 00:13:37,380
No outage, no 3am phone call.
419
00:13:37,380 --> 00:13:39,060
The security implications go deeper.
420
00:13:39,060 --> 00:13:41,860
Managed identity tokens are tied to the Azure control plane.
421
00:13:41,860 --> 00:13:44,820
They're fishing resistant because there's no user involved.
422
00:13:44,820 --> 00:13:46,980
The token is obtained by the resource itself
423
00:13:46,980 --> 00:13:49,700
through a channel that only exists inside Azure.
424
00:13:49,700 --> 00:13:52,220
If an attacker breaches your app, they can access what
425
00:13:52,220 --> 00:13:54,140
the identity has permission to access,
426
00:13:54,140 --> 00:13:56,780
but they can't steal the credential because there's nothing
427
00:13:56,780 --> 00:13:57,580
to steal.
428
00:13:57,580 --> 00:13:59,060
And governance gets simpler, too.
429
00:13:59,060 --> 00:14:01,780
When you delete a resource with a system assigned identity,
430
00:14:01,780 --> 00:14:03,500
the identity is automatically cleaned up.
431
00:14:03,500 --> 00:14:06,140
No often service principles lingering in enter ID
432
00:14:06,140 --> 00:14:07,780
with permissions you forgot about.
433
00:14:07,780 --> 00:14:09,620
No audit findings asking why an identity
434
00:14:09,620 --> 00:14:11,380
from a decommissioned project still has
435
00:14:11,380 --> 00:14:13,540
contributed access to a production subscription.
436
00:14:13,540 --> 00:14:15,060
The platform handles the cleanup.
437
00:14:15,060 --> 00:14:16,420
That's the kind of simplification
438
00:14:16,420 --> 00:14:19,060
that makes Azure security easier to manage.
439
00:14:19,060 --> 00:14:21,140
When not to use managed identities.
440
00:14:21,140 --> 00:14:22,820
So if managed identities are so much better,
441
00:14:22,820 --> 00:14:24,620
why doesn't everyone use them for everything?
442
00:14:24,620 --> 00:14:26,660
The hard limitation is that managed identities
443
00:14:26,660 --> 00:14:29,580
only work inside Azure that on-premises backup server
444
00:14:29,580 --> 00:14:30,500
in your data center.
445
00:14:30,500 --> 00:14:33,460
It can't use a managed identity because it's not running
446
00:14:33,460 --> 00:14:33,980
on Azure.
447
00:14:33,980 --> 00:14:36,580
There's no IMDS endpoint for it to talk to.
448
00:14:36,580 --> 00:14:38,860
Same for your self-hosted GitHub actions runner.
449
00:14:38,860 --> 00:14:40,420
If it's not an Azure resource, you
450
00:14:40,420 --> 00:14:42,340
need a traditional service principle
451
00:14:42,340 --> 00:14:44,300
with a client secret or certificate.
452
00:14:44,300 --> 00:14:46,060
Multi-cloud setups run into the same wall.
453
00:14:46,060 --> 00:14:48,220
If you have workloads on AWS or GCP that
454
00:14:48,220 --> 00:14:51,060
need to authenticate to Azure, managed identities won't help.
455
00:14:51,060 --> 00:14:52,940
Those services aren't inside Azure's fabric,
456
00:14:52,940 --> 00:14:54,700
so they need service principles.
457
00:14:54,700 --> 00:14:56,900
Third party SaaS tools that need to authenticate
458
00:14:56,900 --> 00:14:59,140
to your Azure resources, same problem.
459
00:14:59,140 --> 00:15:00,780
They're not running on your Azure subscription.
460
00:15:00,780 --> 00:15:02,380
They can't use your managed identities,
461
00:15:02,380 --> 00:15:04,060
but Microsoft is making progress here.
462
00:15:04,060 --> 00:15:06,620
Workload identity federation lets external services
463
00:15:06,620 --> 00:15:08,820
exchange their own identity tokens
464
00:15:08,820 --> 00:15:11,460
from GitHub, Kubernetes, or other identity providers
465
00:15:11,460 --> 00:15:13,300
for intra-ID tokens.
466
00:15:13,300 --> 00:15:15,300
It's not as seamless as a managed identity,
467
00:15:15,300 --> 00:15:17,500
but it's a step toward reducing secrets everywhere,
468
00:15:17,500 --> 00:15:18,740
not just inside Azure.
469
00:15:18,740 --> 00:15:19,740
Here's the rule of thumb.
470
00:15:19,740 --> 00:15:22,940
If your workload runs on Azure, use managed identities.
471
00:15:22,940 --> 00:15:24,700
If it doesn't, use service principles
472
00:15:24,700 --> 00:15:26,660
with key vault and automated rotation.
473
00:15:26,660 --> 00:15:28,940
And keep an eye on workload identity federation.
474
00:15:28,940 --> 00:15:31,980
It's closing the gap for workloads outside Azure.
475
00:15:31,980 --> 00:15:33,220
Actionable takeaways.
476
00:15:33,220 --> 00:15:34,940
So what can you actually do starting today?
477
00:15:34,940 --> 00:15:37,620
Here are a few simple steps that will make a big difference.
478
00:15:37,620 --> 00:15:41,220
First, go through your existing Azure resources, app services,
479
00:15:41,220 --> 00:15:44,980
functions, VMs, anything that supports managed identities.
480
00:15:44,980 --> 00:15:48,460
If you find one without managed identity enabled, turn it on.
481
00:15:48,460 --> 00:15:50,180
It takes seconds and it costs you nothing.
482
00:15:50,180 --> 00:15:51,260
No reason not to do it.
483
00:15:51,260 --> 00:15:53,820
Next, pick one specific service to convert.
484
00:15:53,820 --> 00:15:55,900
Storage or key vault are perfect candidates.
485
00:15:55,900 --> 00:15:57,220
Replace that old connection string
486
00:15:57,220 --> 00:15:59,620
sitting in your app settings with a managed identity
487
00:15:59,620 --> 00:16:01,140
and an R-Backroll assignment.
488
00:16:01,140 --> 00:16:01,900
Run a quick test.
489
00:16:01,900 --> 00:16:04,260
You'll see how much cleaner your configuration looks
490
00:16:04,260 --> 00:16:06,460
when there are no secrets hiding in plain sight.
491
00:16:06,460 --> 00:16:08,460
Finally, for any shared infrastructure
492
00:16:08,460 --> 00:16:10,580
like a development cluster or a set of microservices
493
00:16:10,580 --> 00:16:12,380
that all need the same permissions,
494
00:16:12,380 --> 00:16:14,340
use a user assigned managed identity
495
00:16:14,340 --> 00:16:15,660
instead of duplicating permissions
496
00:16:15,660 --> 00:16:18,100
across multiple system assigned identities.
497
00:16:18,100 --> 00:16:20,060
One identity, one set of R-Backrolls,
498
00:16:20,060 --> 00:16:21,740
and you can attach it everywhere it's needed.
499
00:16:21,740 --> 00:16:22,580
It's that simple.
500
00:16:22,580 --> 00:16:24,020
This isn't just a nice to have anymore.
501
00:16:24,020 --> 00:16:26,100
Microsoft is making mandatory MFA mandatory
502
00:16:26,100 --> 00:16:27,140
for service principles,
503
00:16:27,140 --> 00:16:29,780
but managed identities bypass that requirement completely
504
00:16:29,780 --> 00:16:32,180
because there are no user credentials to protect.
505
00:16:32,180 --> 00:16:33,940
Your future self will thank you when you avoid
506
00:16:33,940 --> 00:16:36,980
that 3am on call alert about an expired certificate.
507
00:16:36,980 --> 00:16:39,460
Managed identities let you give your apps their own identity
508
00:16:39,460 --> 00:16:41,180
without ever touching a secret.
509
00:16:41,180 --> 00:16:43,180
That's the real shift from managing credentials
510
00:16:43,180 --> 00:16:44,580
to managing permissions.
511
00:16:44,580 --> 00:16:46,700
Subscribe for more simply explained breakdowns
512
00:16:46,700 --> 00:16:48,100
and drop a comment letting me know
513
00:16:48,100 --> 00:16:50,220
which as your service you want covered next,
514
00:16:50,220 --> 00:16:52,540
making Microsoft make sense one nugget at a time.