<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Olivier Miossec</title>
    <description>The latest articles on DEV Community by Olivier Miossec (@omiossec).</description>
    <link>https://dev.to/omiossec</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160244%2Ff2d80283-eb50-4e19-a699-1cd6ca166e49.jpg</url>
      <title>DEV Community: Olivier Miossec</title>
      <link>https://dev.to/omiossec</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omiossec"/>
    <language>en</language>
    <item>
      <title>Using Claude Code in a PowerShell Project: An Introduction</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Sat, 14 Mar 2026 18:47:01 +0000</pubDate>
      <link>https://dev.to/omiossec/using-claude-code-in-a-powershell-project-an-introduction-56j9</link>
      <guid>https://dev.to/omiossec/using-claude-code-in-a-powershell-project-an-introduction-56j9</guid>
      <description>&lt;p&gt;Generative and agentic AI have reshaped software development in a few short months. This is more than asking a chatbot for help; it’s a mindset shift and a cultural transformation in how we design, generate and maintain code.&lt;/p&gt;

&lt;p&gt;Claude Code is one of the most advanced agentic tools for code generation, but like any generative system it can produce incorrect or low quality output. See the sloop content on Instagram, AI used carelessly, it can create the same "surface level" results you see on social platforms, attractive but unreliable.&lt;/p&gt;

&lt;p&gt;In this post I’ll show how to use Claude Code in a PowerShell project: we’ll build a module to automate GitHub issue management.&lt;br&gt;
First, a quick intro: Claude Code is part of Anthropic’s ecosystem (alongside Claude.ai, the Claude API and Claude CoWork). Claude Code is designed as an agentic coding assistant rather than a simple chatbot.&lt;br&gt;
You can download it &lt;a href="https://claude.com/product/claude-code" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Code is not a Chatbot, it is an AI Agent; it follow a workflow, gets the context, analyzes, plan the work and creates the code.  In Claude Code, you don’t ask a question, you specify the result you want and the agent executes. &lt;/p&gt;

&lt;p&gt;There is one important notion in Claude Code (and other AI tools), the Context. Context is the agent’s working memory, measured in tokens.  It’s critical to manage. Claude Code sessions typically support large contexts (hundreds of thousands of tokens, depending on your plan). Monitor usage with the /context command; if you approach ~60% capacity, run /compact to reduce context size and avoid degraded behaviours.&lt;/p&gt;

&lt;p&gt;The first best practice with Claude Code, is to keep a CLAUDE.md at the project root: treat it like a brief for the agent. Describe the project goals, constraints, runtime targets and coding conventions. That file becomes the agent’s persistent context, so you manage an agentic collaborator rather than a stateless LLM chat.&lt;/p&gt;

&lt;p&gt;You can generate CLAUDE.md with the /init command: when run against an existing codebase, the agent analyses the repository and drafts the brief based on discovered files and patterns.&lt;/p&gt;

&lt;p&gt;In this tutorial we start from an empty folder; you can author CLAUDE.md manually or ask Claude Code to create it for you. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Create a new CLAUDE.md file in this folder with these instructions, PowerShell module for GitHub Issue Automation, named psGTIssue, the module will use classes, private function and public function, it run with PwSh 7 on Linux, MacOS and Windows. The project structure include, src, tests and build folder, the code should respect the camel case notation for variable and authorized verb for function (get-something), Pester will be used for unit testing" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should have something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# CLAUDE.md — psGTIssue Project Instructions&lt;/span&gt;

&lt;span class="gu"&gt;## Project Overview&lt;/span&gt;

&lt;span class="gs"&gt;**Module name:**&lt;/span&gt; &lt;span class="sb"&gt;`psGTIssue`&lt;/span&gt;
&lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; PowerShell module for GitHub Issue Automation
&lt;span class="gs"&gt;**Runtime:**&lt;/span&gt; PowerShell 7 (pwsh) — cross-platform: Linux, macOS, Windows
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Project Structure&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;psGTIssue/&lt;br&gt;
├── src/&lt;br&gt;
│   ├── Classes/          # PowerShell classes&lt;br&gt;
│   ├── Private/          # Private (internal) functions&lt;br&gt;
│   ├── Public/           # Public (exported) functions&lt;br&gt;
│   └── psGTIssue.psm1    # Module root — dot-sources all classes, private, public&lt;br&gt;
├── tests/&lt;br&gt;
│   ├── Unit/             # Pester unit tests mirroring src/ structure&lt;br&gt;
│   └── Integration/      # Integration tests (optional)&lt;br&gt;
├── build/                # Build output and scripts&lt;br&gt;
│   └── psGTIssue.psd1    # Module manifest (generated or maintained here)&lt;br&gt;
└── CLAUDE.md&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Coding Conventions&lt;/span&gt;

&lt;span class="gu"&gt;### Naming&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Variables:**&lt;/span&gt; camelCase — &lt;span class="sb"&gt;`$issueTitle`&lt;/span&gt;, &lt;span class="sb"&gt;`$repoOwner`&lt;/span&gt;, &lt;span class="sb"&gt;`$pageNumber`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Parameters:**&lt;/span&gt; camelCase — &lt;span class="sb"&gt;`param([string]$issueTitle)`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Classes:**&lt;/span&gt; PascalCase — &lt;span class="sb"&gt;`class GitHubIssue`&lt;/span&gt;, &lt;span class="sb"&gt;`class IssueFilter`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Functions:**&lt;/span&gt; Approved PowerShell verb + PascalCase noun — &lt;span class="sb"&gt;`Get-GtIssue`&lt;/span&gt;, &lt;span class="sb"&gt;`New-GtIssue`&lt;/span&gt;, &lt;span class="sb"&gt;`Set-GtIssue`&lt;/span&gt;, &lt;span class="sb"&gt;`Remove-GtIssue`&lt;/span&gt;, &lt;span class="sb"&gt;`Invoke-GtIssueAction`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Private functions:**&lt;/span&gt; same verb-noun convention, not exported — &lt;span class="sb"&gt;`Get-GtApiHeader`&lt;/span&gt;, &lt;span class="sb"&gt;`ConvertTo-GtIssueObject`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Constants / enum values:**&lt;/span&gt; camelCase

&lt;span class="gu"&gt;### Approved Verbs&lt;/span&gt;

&lt;span class="gh"&gt;Always use verbs from `Get-Verb`. Common ones for this module:
---
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can create the project structure. First, create the project skeleton. Use a prompt such as Create the project structure and Claude will scaffold folders, a .psd1 manifest, a .psm1 module file, a build.ps1 script and Pester test stubs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Create a public function that list all issue for a given repository, param are repository, organization name and a switch all, open, close" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can create a function that list all issue for a repository&lt;/p&gt;

&lt;p&gt;The agent will create several files, a function to call the GitHub API, a function to retrieve all issues in the repository and test files. &lt;/p&gt;

&lt;p&gt;You see that the prompt used are optimised to create a function, the prompt should be optimised to get the result.  If you want a modification, you should be precise on the result you want. &lt;/p&gt;

&lt;p&gt;For example, using a switch for the parameter $State is not a great idead&lt;br&gt;
We can ask Claude to replace the switch parameter in the Get-GtIssueList to a simple validateSet parameter with All, Open, Closed. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"replace the switch parameter in the Get-GtIssueList to a simple validateSet parameter with All, Open, Closed in the&lt;br&gt;
  @psGTIssue\src\Public\Get-GtIssueList.ps1"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can work directly on a file work by using @  here @psGTIssue\src\Public\Get-GtIssueList.ps1 it will cost less in token as Claude will not have to search for the file. &lt;/p&gt;

&lt;p&gt;Now it is time to check the status of the session with /context. The command will show the percentage used by the session. If the number is higher than 60% you should run the command /compact &lt;br&gt;
It is a good practice to name the session (and its context) so you can retrieve it later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/rename buildGitHubIssuePwSh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To restart the session &lt;/p&gt;

&lt;p&gt;&lt;code&gt;claude --resume "buildGitHubIssuePwSh"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Review generated code carefully. Common issues: the agent may prefer Write-Verbose over Write-Debug, and it might scaffold a .psm1 that dynamically dot sources files at runtime. For best practice a static .psm1 that explicitly imports and exports functions and classes is better; this improves readability, testability and module loading behaviours.&lt;/p&gt;

&lt;p&gt;You can encode these conventions in CLAUDE.md, but they’re generic PowerShell best practices you’ll want in every project.&lt;/p&gt;

&lt;p&gt;Claude Code supports skills; reusable instruction sets that tell the agent how to behave in specific contexts. Create a PowerShell module skill to enforce coding conventions, file layout and test patterns across projects.&lt;br&gt;
All you need to do is to create a folder in .claude/skills/ and create the file SKILL.md. &lt;/p&gt;

&lt;p&gt;You can ask Claude for that &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Create the folder ./claude/skills/powershell-module at the root and add the file SKILL.md"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude will create the file for you with some elements&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;  -&lt;/span&gt; Trigger conditions for when the skill applies
&lt;span class="p"&gt;  -&lt;/span&gt; Naming conventions summary
&lt;span class="p"&gt;  -&lt;/span&gt; Function templates (public &amp;amp; private)
&lt;span class="p"&gt;  -&lt;/span&gt; Class template
&lt;span class="p"&gt;  -&lt;/span&gt; Module dot-source order
&lt;span class="p"&gt;  -&lt;/span&gt; API call rules
&lt;span class="p"&gt;  -&lt;/span&gt; Pester test patterns
&lt;span class="p"&gt;  -&lt;/span&gt; File placement checklist

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add an header&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt; 
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;powershell-module&lt;/span&gt; 
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conventions and guidelines for building PowerShell modules&lt;/span&gt;
&lt;span class="na"&gt;argument-hint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[check|fix]"&lt;/span&gt; 
&lt;span class="nn"&gt;---&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And information about write-verbose and write-debug and psm1 generation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### write-verbose?/write-debug?
- Use `Write-Verbose` for informational messages that may be helpful for debugging but are not critical to the user, only visible when the `-Verbose` switch is used. 
- Use `Write-Debug` for detailed debugging information that is typically only relevant when troubleshooting specific issues. This can be enabled with the `-Debug` switch when running the function.
- Avoid using `Write-Host` for regular output; reserve it for special cases where you want to display colored or formatted output directly to the console. For standard output, return objects or use `Write-Output`.

### psm1 file 
- The `.psm1` file should contain all individual functions and class files, and the `Export-ModuleMember` call to specify which public functions are exported. The build script will handle the creation of the `.psm1` manifest file, so you do not need to create that manually.
- All actual code (functions, classes) should live in separate `.ps1` files under the `src/` directory, organized into `Public`, `Private`, and `Classes` subdirectories.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once conventions live in a skill, you can simplify CLAUDE.md and rely on the skill for enforcement. Skills are shareable, store them in a repo so your teams can reuse the same conventions and templates.&lt;/p&gt;

&lt;p&gt;Another way to extend Claude Code is to use sub-agent. Sub-agent is a separate agent that use its own context (it doesn’t impact your session) specialised in one task. The task must be specific and should not be related to any other task in your current session. &lt;/p&gt;

&lt;p&gt;Agents are located inside ./claude/agents folder. &lt;/p&gt;

&lt;p&gt;We can ask Claude code to create the agent &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create the folder ./claude/agents/ at the root and add the file security-check.md&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude will create the markdown file with some security check; you can review them and add your own check. &lt;/p&gt;

&lt;p&gt;You can run the check&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start security check with the sub agent security-check&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude will produce a report in the terminal you can review and then act on it. &lt;/p&gt;

&lt;p&gt;Claude Code is a powerful agentic coding tool; it lets you manage a team of coding agents as if you had human collaborators. That power demands discipline: be precise in your briefs, test outputs, and maintain human oversight. Agents can produce useful code quickly, but they also make mistakes; you must validate, adapt, and own the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core commands and session hygiene
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;/init&lt;/strong&gt; — generate CLAUDE.md from an existing repo.&lt;br&gt;
&lt;strong&gt;/context&lt;/strong&gt; — show token usage (monitor session memory).&lt;br&gt;
&lt;strong&gt;/compact&lt;/strong&gt; — reduce context when usage is high.&lt;br&gt;
&lt;strong&gt;/rename &lt;/strong&gt; — name the session for later resume.&lt;br&gt;
&lt;strong&gt;claude --resume ""&lt;/strong&gt; — resume a named session.&lt;br&gt;
&lt;strong&gt;1st rule of Claude&lt;/strong&gt;: compact when usage approaches 60–80% of context capacity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Project files
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CLAUDE.md&lt;/strong&gt; — project brief (goals, constraints, runtime, conventions).&lt;br&gt;
&lt;strong&gt;.claude/skills/powershell-module/SKILL.md&lt;/strong&gt; — reusable PowerShell conventions and templates.&lt;br&gt;
&lt;strong&gt;.claude/agents/&lt;/strong&gt; — sub‑agents for isolated tasks (security, linting).&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>aiops</category>
      <category>powershell</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Will AI Replace Your Job? A Practical Guide for Devs and Cloud Engineers</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Fri, 06 Mar 2026 18:28:55 +0000</pubDate>
      <link>https://dev.to/omiossec/will-ai-replace-your-job-a-practical-guide-for-devs-and-cloud-engineers-3ehl</link>
      <guid>https://dev.to/omiossec/will-ai-replace-your-job-a-practical-guide-for-devs-and-cloud-engineers-3ehl</guid>
      <description>&lt;p&gt;The hot question today is: Will AI take my job? Headlines about mass layoffs and viral posts claiming an entire team can be replaced with a single prompt make the fear feel immediate. Scrolling LinkedIn or Twitter, you see dramatic claims and quick takes.&lt;/p&gt;

&lt;p&gt;Many of those claims are exaggerated, for now. Companies cut headcount for many reasons: cost, restructuring, strategic shifts, and sometimes, "AI" is just a convenient narrative. Dismissing AI as a simple chatbot hype is also a mistake. The reality is that AI, mostly agentic AI, will change our relationship with work and how enterprises create value.&lt;/p&gt;

&lt;p&gt;Agentic AI is real, and some roles will be replaced, just as roles shifted during the Internet, SaaS, and cloud revolutions. In this post, I’ll try to identify which roles are most at risk, suggest ways to protect and reskill yourself, and show how AI can create new opportunities. Like past technological revolutions, Agentic AI will destroy some roles, like steam trains removed the need for diligence, but it will create others.&lt;/p&gt;

&lt;p&gt;Generative AI is a powerful tool that can process texts based on general knowledge. It excels at producing and transforming text-based artifacts: contracts, job descriptions, support tickets, documentation, and code. Agentic AI goes further by orchestrating workflows and subtasks autonomously. If your role is primarily about following a strict, repeatable process to produce standardized outputs, an agent can often do it faster and cheaper.&lt;/p&gt;

&lt;p&gt;Examples include analysts, consultants, HR processes, and other roles where a defined input yields a standardized output. Developers face partial automation too: AI can generate boilerplate code, tests, and scaffolding quickly. Accounting and routine financial reporting are vulnerable. Many managerial tasks, such as synthesizing and distributing information from up and down, can be automated or augmented.&lt;/p&gt;

&lt;p&gt;We already see concrete examples of agentic systems accelerating decision cycles. In high-stakes contexts, automated analysis of multiple data sources can reduce days of work to minutes. Similar acceleration is appearing in HR workflows and financial analysis, where agents aggregate, filter, and summarize large datasets. In the current war in the Middle East, the Pentagon is using agentic AI to analyze multiple data sources to make decisions.&lt;/p&gt;

&lt;p&gt;If your role is primarily execution, producing outputs from well-defined and static processes without having to make any design or judgment, it’s at high risk of automation. Execution can be delegated to agents cheaply. It scales much more than humans can do.  Does that mean you’ll lose your job? Not necessarily.&lt;/p&gt;

&lt;p&gt;Generative AI is powerful but limited: it doesn’t make value judgments, exercise domain judgment, or possess taste. Those human skills, judgment, critical thinking, navigating ambiguity, domain expertise, and taste, become stronger differentiators in an AI-augmented workplace.&lt;/p&gt;

&lt;p&gt;Be proactive: learn how AI works beyond the surface of simple prompts. You don’t need to be an expert or LLM engineer, but you should understand core concepts, how models generate text or images, what tokens and context windows are, and how parameters like temperature affect output. It will help you to have a better vision of what generative AI can do, cannot do, and why hallucinations happen.&lt;/p&gt;

&lt;p&gt;Get hands-on with agentic AI platforms and tooling. Explore multiple ecosystems (Anthropic, OpenAI, GitHub Copilot, and others) and experiment with APIs, MCP, agent orchestration, and observability. Use vendor resources and community tutorials to build practical experience.&lt;/p&gt;

&lt;p&gt;To learn more about the Anthropic ecosystem, you can use these courses published &lt;a href="https://claude.com/resources/courses" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also learn GitHub Copilot CLI, it is for developers, but you can try to learn it with this beginner &lt;a href="https://github.com/github/copilot-cli-for-beginners" rel="noopener noreferrer"&gt;course&lt;/a&gt; (if you want to learn more, this &lt;a href="https://docs.github.com/en/copilot/how-tos/copilot-cli" rel="noopener noreferrer"&gt;page will be useful&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You may also try on local AI tool, where you can use a model on your local device. A good start is to set up Foundry local (&lt;a href="https://learn.microsoft.com/en-us/azure/foundry-local/get-started?view=foundry-classic" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/foundry-local/get-started?view=foundry-classic&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;You can also try any other alternative AI tools, for example, Mistral AI (&lt;a href="https://mistral.ai/products/studio" rel="noopener noreferrer"&gt;https://mistral.ai/products/studio&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Don’t wait for corporate training. Start learning on your own and build demonstrable projects. Early adopters will have an advantage over peers who delay. &lt;/p&gt;

&lt;p&gt;Don’t be desperate, AI will also create new roles. Here are practical examples of emerging job categories where human expertise will remain essential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent governance and compliance, to add policies, audit data access, and permissions for agents. &lt;/li&gt;
&lt;li&gt;AI debt management, to identify, track, and remediate risks from unsupervised agent usage. &lt;/li&gt;
&lt;li&gt;Agent developer/integrator, for designing, building, and maintaining task-specific agents and orchestrations. &lt;/li&gt;
&lt;li&gt;Data discoverability and indexing, to ensure agents can reliably find and use the right data (the “AI SEO” problem). &lt;/li&gt;
&lt;li&gt;AI-assisted code reviewer/verifier, for validating code produced by agents and ensuring security, correctness, and maintainability.&lt;/li&gt;
&lt;li&gt;Token and cost optimization engineer for minimizing inference costs and optimizing model usage patterns.&lt;/li&gt;
&lt;li&gt;AI infrastructure engineer, to deploy and operate compute resources, networking, and observability stacks for agentic workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are predictions,s and I may be wrong. But like past revolutions, agentic AI will eliminate some roles and create new ones, often in places we don’t yet fully anticipate. Things about the Steam train, it revolutionized the world of transportation and the economy. &lt;/p&gt;

&lt;p&gt;AI will reshape work, but it won’t simply “replace” people overnight. Tasks that are repeatable and execution focused are most at risk; judgment, design, domain expertise, and governance remain human strengths. The practical strategy for engineers is clear: learn how agents work, build hands-on experience, and pivot toward roles that require oversight, orchestration, and measurable impact. Those who combine technical fluency with judgment and governance skills will be best positioned in this new tech revolution.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>cloud</category>
    </item>
    <item>
      <title>When AI Agents Meet Wall Street: Why Markets Overreact and what Engineers Should Prepare For</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Sat, 28 Feb 2026 12:28:00 +0000</pubDate>
      <link>https://dev.to/omiossec/when-ai-agents-meet-wall-street-why-markets-overreact-and-what-engineers-should-prepare-for-145e</link>
      <guid>https://dev.to/omiossec/when-ai-agents-meet-wall-street-why-markets-overreact-and-what-engineers-should-prepare-for-145e</guid>
      <description>&lt;p&gt;An economic bubble occurs when asset prices detach from long term fundamentals and are driven instead by irrational exuberance and social contagion.&lt;/p&gt;

&lt;p&gt;Since 2025 we’ve seen that pattern again: mass layoffs, elevated valuations, and extreme market volatility, all of this are tied to the AI narrative.&lt;/p&gt;

&lt;p&gt;Let’s try to analyse what happens and see if we can define a strategy for us, engineer.&lt;/p&gt;

&lt;p&gt;Last year major tech firms, Meta, Amazon, Microsoft and others, announced mass layoffs totalling roughly 200,000 roles. Publicly, the rationale was the rise of AI: many positions will be automated or restructured around AI capabilities.&lt;/p&gt;

&lt;p&gt;There is some truth in this reason, but this is not the main reason. To get the main reason, take a lot on what these companies are doing with their investments. &lt;/p&gt;

&lt;p&gt;There’s truth in that claim, but it misses the main driver. Look at where these companies are investing infrastructure, chips, datacentres and energy capacity. It is not just about chatbots.&lt;/p&gt;

&lt;p&gt;They’re not just chasing chatbots; they’re preparing for an agentic AI world. Training large models consumes massive energy, while inference, asking something, is far cheaper. The real shift is the infrastructure needed to run persistent, autonomous AI agents at scale.&lt;/p&gt;

&lt;p&gt;Agentic AI is not like Chatbot: agents such as Claude CoWork operate autonomously, executing tasks without continuous human input; managing email, CRM workflows, scheduling, and more. Once created, an agent can remain active and consume resources while completing its tasks.&lt;/p&gt;

&lt;p&gt;The capacity required is colossal: servers, accelerators, datacentre space, networking and power provisioning at scale. &lt;/p&gt;

&lt;p&gt;To build that capacity companies must invest heavily; buying accelerators (e.g., NVIDIA GPUs), networking devices and datacenter capacity, and securing power contracts. That capital commitment helps explain why some firms reallocate headcount toward these investments.&lt;/p&gt;

&lt;p&gt;It is capital reallocation, laying off people to build AI capacity, I can’t say it is fair or normal. But this is very rational.&lt;/p&gt;

&lt;p&gt;What’s less rational is the market’s reaction to agentic AI in 2026. Agents differ from chatbots: the value proposition is task execution, not prompt finesse. An agent combines an LLM, tool access and autonomy, but that doesn’t mean it instantly replaces entire software categories.&lt;/p&gt;

&lt;p&gt;In January Anthropic launched Claude CoWork, an agent that handles non technical tasks locally (initially macOS only): files, email, calendar, and deliver artifacts like spreadsheets and text summaries.&lt;/p&gt;

&lt;p&gt;Claude CoWork wasn’t the first agentic solution, but it was the first to capture broad public attention. Anthropic developed it after customers used Claude Code for non coding tasks; managing email, expense reports and file organization, demonstrating real demand for delegated AI automation.&lt;/p&gt;

&lt;p&gt;Soon after CoWork’s general availability, several SaaS and enterprise software stocks, like Salesforce, SAP or Adobe, saw a large market declines, contributing to a broader sell off in software. The MSCI Software &amp;amp; Services index fell significantly in early 2026.&lt;/p&gt;

&lt;p&gt;The market appears to be pricing a future where AI agents displace some SaaS functionality. That view is optimistic and only partially rational, because agents may complement rather than fully replace many enterprise apps in the near future.&lt;/p&gt;

&lt;p&gt;What’s coming next is surprising. Markets moved into irrational territory. On 20 February Anthropic published a blog post suggesting Claude Code could assist with static code analysis. It is just a concept, not a shipped product or roadmap. Yet cybersecurity stocks, from niche vendors to large firms like Palo Alto and CrowdStrike, tumbled in response.&lt;/p&gt;

&lt;p&gt;On 23 February another Anthropic post suggested agents could assist with modernizing COBOL code, again a concept. Consulting firms and legacy technology vendors saw market pressure as investors extrapolated far beyond the announcement. &lt;/p&gt;

&lt;p&gt;This is the irrational zone: a static analysis capability cannot replace entire cybersecurity teams, runtime scanners, or the complex processes that govern legacy banking systems. The market is reacting to buzzwords without understanding the engineering and operational realities behind the headlines. &lt;/p&gt;

&lt;p&gt;Sound familiar? It echoes the dot com bubble, when a single buzzword in a press release could inflate a stock. The mechanism is the same: narrative driven speculation divorced from technical substance. &lt;/p&gt;

&lt;p&gt;It’s easy to laugh, but boards will react. A sudden market signal can pressure executives to “do AI”, sometimes by reallocating resources toward visible AI projects at the expense of core capabilities like cybersecurity. &lt;/p&gt;

&lt;p&gt;We may be in a feedback loop where irrational market moves trigger irrational corporate responses. As engineers, remember that AI is a tool, a powerful tool, but only a probabilistic predictor that generates text, code or images. It does not make value judgments or replace human decision making. &lt;/p&gt;

&lt;p&gt;Strategy for engineers: learn agentic AI, not just prompt engineering, but how agents are built, orchestrated and monitored. Master relevant tools and workflows (e.g., agent orchestration, observability and safety patterns). AI will also create new roles; those who understand agentic systems will be better positioned. &lt;/p&gt;

&lt;p&gt;And of course, there will be soon some AI tools that could complete the cybersecurity landscape, but it will be a real product, with verifiable, measurable and concrete results.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>careerdevelopment</category>
    </item>
    <item>
      <title>What is wrong with LinkedIn in the age of AI</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Wed, 11 Feb 2026 11:02:06 +0000</pubDate>
      <link>https://dev.to/omiossec/what-is-wrong-with-linkedin-in-the-age-of-ai-1pid</link>
      <guid>https://dev.to/omiossec/what-is-wrong-with-linkedin-in-the-age-of-ai-1pid</guid>
      <description>&lt;p&gt;Like everyone in tech, I utilize LinkedIn to manage my professional network, showcase my work, and maintain visibility to recruiters. LinkedIn is central to professional life and has no real competitor.&lt;/p&gt;

&lt;p&gt;Not long ago, I had a strange experience: a stream of posts about an Azure networking change. Nothing unusual, this kind of post floods my LinkedIn every week, but here, there was a tiny but consequential error. The update stated that the change would occur on 30 September 2025, yet the posts were dated December 2025. Everyone was warning readers to act on a change that, in reality, was scheduled for 31 March&lt;/p&gt;

&lt;p&gt;This is where we are now: a lot of noise on a professional network. That noise is amplified by conformity. People avoid friction and rarely post dissenting views. The result is a chorus of similar takes that can feel caricatural; sometimes the most viral LinkedIn posts end up as jokes on Twitter or Reddit, and some have become famous memes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2lob1t3vte65x2zf8rj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2lob1t3vte65x2zf8rj.jpeg" alt=" " width="640" height="783"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This Mediocrity is only part of the problem on the platform. Much of LinkedIn is declarative and unverified: anyone can claim to be a Rust or Go expert simply by writing it. You can be a brain surgeon if you want; you only need to edit your profile. The platform is full of inflated titles and grandiose claims that often bear little relation to reality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qpu2npm0z0ppbeh39u6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qpu2npm0z0ppbeh39u6.jpeg" alt=" " width="640" height="731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s bad news for job seekers. Recruiters must wade through noise and exaggerated titles before they even reach your profile. By the time they find you, they still don’t know whether your résumé is accurate or just inflated.&lt;/p&gt;

&lt;p&gt;There is a lot of friction before reaching your profile. A potential recruiter will need to navigate through all the noise, do some research, and maybe find you. But at this point, the recruiter will have no idea if your profile is valid or if it is just an inflated one. &lt;/p&gt;

&lt;p&gt;The recruiter needs to navigate to LinkedIn, like you do when trying to find a job. It’s often frustrating. The probability that a recruit will find you is limited.&lt;/p&gt;

&lt;p&gt;LinkedIn’s interface, like any computer interface, is designed for humans to navigate into the complexity of data, to control their behaviours, and authorize access.&lt;/p&gt;

&lt;p&gt;The interface is going to be disrupted by Artificial Intelligence. Agentic AI are systems that can autonomously plan, make decisions, and take actions to achieve goals without human direction, and can now replace some work tasks, including finding profile.&lt;/p&gt;

&lt;p&gt;AI Agents do not have time to lose scrolling a feed on the interface; they work on raw data. When a recruiter instructs an agent to find an Azure architect skilled in Bicep and Terraform, the agent won’t scroll through posts and buzzwords. It will search raw, verifiable artifacts; GitHub and GitLab repositories, blog posts, published articles, … These are concrete and verifiable artifacts to spot the perfect profile. &lt;/p&gt;

&lt;p&gt;In this agentic recruitment world, LinkedIn becomes secondary. It will be useful for correlation, but the primary sources will be your public artifacts: documented side projects, repositories, PRs and issues, and technical blog posts. Those are the things agents can verify and score.&lt;/p&gt;

&lt;p&gt;To facilitate the AI, you should group them on a single page visible from GitHub, Twitter and LinkedIn. A personal brand API that automatically lists your original blog posts, your public repos, your PR, and your contributions. This will be your new AI era visit card. &lt;/p&gt;

&lt;p&gt;LinkedIn still matters for human networking and visibility, but the rise of agentic hiring shifts the signal to verifiable, AI-readable artifacts. Start publishing concrete work and make it easy for agents to find and verify.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>Azure Machine Configuration, Linux, and DSC Configuration</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Tue, 13 Jan 2026 22:03:23 +0000</pubDate>
      <link>https://dev.to/omiossec/azure-machine-configuration-linux-and-dsc-configuration-1i74</link>
      <guid>https://dev.to/omiossec/azure-machine-configuration-linux-and-dsc-configuration-1i74</guid>
      <description>&lt;p&gt;I recently made a post about Azure Machine Configuration and PowerShell DSC, and how to deploy VM configurations as infrastructure as Code, just like the rest of your infrastructure.&lt;/p&gt;

&lt;p&gt;But in this post, I focused mainly on Windows configuration and wrote almost nothing about Linux.&lt;/p&gt;

&lt;p&gt;However, Azure Machine Configuration is also available for Linux VMs, where you can use DSC or Chef InSpec.&lt;/p&gt;

&lt;p&gt;To run DSC configurations, VMs need to have the AzurePolicyForLinux extension and a managed identity.&lt;/p&gt;

&lt;p&gt;But unlike Windows, most Linux VMs don’t come with PowerShell installed. To solve this problem, the AzurePolicyForLinux extension installs PowerShell in a Folder but doesn’t modify the Path of the VM. PowerShell can only be used by the policy. &lt;/p&gt;

&lt;p&gt;The next step is to write a DSC configuration. There are many DSC resources for managing Windows, but to manage a Linux server, you will need a compatible DSC resource. The most advanced is the &lt;a href="https://github.com/azure/nxtools" rel="noopener noreferrer"&gt;NxTools module&lt;/a&gt;. It is the recommended version to use with the Azure Machine configuration. &lt;/p&gt;

&lt;p&gt;The NxTools module is a POSIX wrapper for several Linux commands and includes several DSC resources. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nxFiles, to manage files and folders&lt;/li&gt;
&lt;li&gt;nxGroup, to manage groups and group membership&lt;/li&gt;
&lt;li&gt;nxUser, to manage users&lt;/li&gt;
&lt;li&gt;nxPackages, to manage packages (support only apt)&lt;/li&gt;
&lt;li&gt;nxService, to manage service (only system)&lt;/li&gt;
&lt;li&gt;nxScript, to execute scripts in DSC configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To demonstrate DSC on Linux with Azure Machine Configuration, let's ensure the user devTo is created and added to the group publisher, and a file with specified content is created using a script resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;configuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demoDSCLinux&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;Import-DscResource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ModuleName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'nxtools'&lt;/span&gt;&lt;span class="w"&gt;


        &lt;/span&gt;&lt;span class="n"&gt;nxUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ensureDevToUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;Ensure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'Present'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'DevTo'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Dev To Demo user'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;HomeDirectory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/home/DevTo'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Ensure that DevTo user is present on the system'&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="n"&gt;nxGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ensurePublishersGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="c"&gt;# the group must be present and have root as only member&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;Ensure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'Present'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;GroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'publishers'&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;Members&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="s1"&gt;'DevTo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="n"&gt;nxScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ensurePublisherfilePresent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;GetScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Reason&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Script:Script:FileMissing"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Phrase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"File does not exist"&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/DevTo/publisher.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Script:Script:Success"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Phrase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"File exists"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nx"&gt;Reasons&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="nv"&gt;$Reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;TestScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/DevTo/publisher.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;SetScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/DevTo/publisher.txt"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"File"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two resources create the DevTo user and create the Publishers group, and add the DevTo user. &lt;/p&gt;

&lt;p&gt;The last one ensures that the file "/home/DevTo/publisher.txt" is present on the system using a nxScript resource. The GetScript block of the resource needs to return a Hashtable with a Reason object to work. The reason.phrase will be shown in the Azure Portal in case of noncompliance.&lt;/p&gt;

&lt;p&gt;If you try to compile this configuration on your Windows or macOS machine, you will get an error; you need a Linux VM with PowerShell. &lt;/p&gt;

&lt;p&gt;You can set up a dev VM for that, but you can also use a CI/CD pipeline to compile and package the configuration for Linux. You can also compile and package the DSC configuration in GitHub Actions. &lt;/p&gt;

&lt;p&gt;First, you will need a script for compiling the configuration and creating the Azure Machine Configuration package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check if the host is a Linux system&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$IsLinux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This script must be run on a Linux system."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# install modules &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nxtools&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;install-module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PSDesiredStateConfiguration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-RequiredVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3.0.0-beta1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-AllowPrerelease&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;install-module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GuestConfiguration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-RequiredVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;4.1.0&lt;/span&gt;&lt;span class="w"&gt; 

&lt;/span&gt;&lt;span class="c"&gt;# compile the demo configuration&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;/DSC-Linux/demolinux.dsc.ps1&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;demoDSCLinux&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# rename the MOF file &lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Rename-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\demoDSCLinux\localhost.mof&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NewName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;demoDSCLinux.mof&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; 

&lt;/span&gt;&lt;span class="c"&gt;# create the package for Azure Machine Configuration&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;New-GuestConfigurationPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"demoDSCLinux"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AuditAndSet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Configuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\demoDSCLinux\demoDSCLinux.mof&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line of the script tests if the host is a Linux machine. The configuration can only be created on Linux. &lt;/p&gt;

&lt;p&gt;Then the script imports all the necessary modules, nxtools for the DSC resources, PSDesiredStateConfiguration for DSC, and GuestConfiguration to package the configuration. &lt;/p&gt;

&lt;p&gt;It then compiles the configuration and packages it. The package can then be deployed to a Linux VM with Azure Machine configuration.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>iac</category>
      <category>powershell</category>
      <category>linux</category>
    </item>
    <item>
      <title>Overview of Azure Service Groups (public preview)</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Tue, 02 Dec 2025 20:38:03 +0000</pubDate>
      <link>https://dev.to/omiossec/overview-of-azure-service-groups-public-preview-hoa</link>
      <guid>https://dev.to/omiossec/overview-of-azure-service-groups-public-preview-hoa</guid>
      <description>&lt;p&gt;In an Azure tenant, you use management groups to organize subscriptions. In that hierarchy, you can define access controls and apply policies.&lt;/p&gt;

&lt;p&gt;When resources for a single workload are deployed across multiple subscriptions, management becomes more complex. Azure Service Groups help by allowing you to group resources without moving them.&lt;/p&gt;

&lt;p&gt;A Service Group is a logical container that groups resources across subscriptions and resource groups while leaving each resource in its original subscription. You can manage that collection from within the management group hierarchy.&lt;/p&gt;

&lt;p&gt;An Azure Service Group is a logical container, similar to a resource group, a subscription, or a management group, but completely separate from the last ones. Service Groups organize resources across subscriptions, resource groups, and management groups without moving these resources. It stores metadata used to identify workloads, track state, and manage processes.&lt;/p&gt;

&lt;p&gt;Suppose your networking team manages gateways, load balancers, and other network services that are deployed across several subscriptions. With Azure Service Group, you can create a service group for these networking resources, add the network resources you need, and apply permissions to people who will manage these resources.&lt;/p&gt;

&lt;p&gt;With Azure Service Groups, you can create a service group for those networking resources, add the relevant resources, and assign permissions to the people who manage them. Users assigned the Service Group Reader role can view the service group and its child resources.&lt;/p&gt;

&lt;p&gt;You also get an inventory of resources in the service group, a list of issues affecting those resources, application maps, and availability tests (if Application Insights is linked), and monitoring recommendations and coverage for VMs and AKS.&lt;/p&gt;

&lt;p&gt;Each Service Group requires a unique global name (similar to a storage account; up to 250 characters). Service Groups form a hierarchy: you can create a Service Group at the top level (under the Tenant Root Service Group) or as a child of another Service Group.&lt;/p&gt;

&lt;p&gt;You can create a Service Group and associate resources using the Azure Portal or the Azure REST API. There is no dedicated PowerShell cmdlet or Azure CLI tool for the moment.&lt;/p&gt;

&lt;p&gt;Below is an example that creates a Service Group and associates a resource using Bicep. (Note: you can also use ARM templates or the REST API.)&lt;/p&gt;

&lt;p&gt;Creating a Service Group and associating a resource in Azure Bicep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param serviceGroupId string
param parentServiceGroupId string
param serviceGroupName string 
param storageAccountName string

resource serviceGroup 'Microsoft.Management/serviceGroups@2024-02-01-preview' = {
  scope: tenant()
  name: serviceGroupId
  properties: {
    displayName: serviceGroupName
    parent: {
      resourceId: '/providers/Microsoft.Management/serviceGroups/${parentServiceGroupId}'
    }
  }
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' existing = {
  name: storageAccountName
}

resource rel1 'Microsoft.Relationships/serviceGroupMember@2023-09-01-preview' = {
  scope: storageAccount
  name: 'childResource1'
  properties: {
    targetId: serviceGroup.id
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the service group is created using the Microsoft.Management/serviceGroups at the tenant level. The resource has a name (the ID of the service group) and a display name. It has a parent, either the root service group or another service group.&lt;/p&gt;

&lt;p&gt;For associating a resource, a storage account, to the new service group, the Microsoft.Relationships/serviceGroupMember is used. You need a reference of the resource in the scope property. &lt;/p&gt;

&lt;p&gt;To get this reference, I use the Existing keyword in bicep to access the resource property without deploying it again. &lt;/p&gt;

&lt;p&gt;The scope property in the Microsoft.Relationships/serviceGroupMember don’t take a resourceID in Azure Bicep for the scope property. But ARM template allows it on the same scope property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"storageAccountName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                 
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"storageAccountRG"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                 
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"storageAccountSubID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                 
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"targetServiceGroupResourceID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                 
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"variables"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Relationships/serviceGroupMember"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"apiVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-09-01-preview"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[concat('rel-', parameters('storageAccountName'))]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[resourceId(parameters('storageAccountSubID'), parameters('storageAccountRG'), 'Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="nl"&gt;"targetId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[parameters('targetServiceGroupResourceID')]"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Service Groups are in public preview, so APIs and tooling may change before general availability. Still, it’s worth evaluating the feature now if you manage medium or large Azure tenants.&lt;/p&gt;

</description>
      <category>azure</category>
    </item>
    <item>
      <title>Install and use the Microsoft Learn MCP server in VS Code</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Mon, 10 Nov 2025 20:07:46 +0000</pubDate>
      <link>https://dev.to/omiossec/install-the-microsoft-learn-mcp-server-in-vs-code-265k</link>
      <guid>https://dev.to/omiossec/install-the-microsoft-learn-mcp-server-in-vs-code-265k</guid>
      <description>&lt;p&gt;This short guide shows how to install and use the Microsoft Learn MCP server inside Visual Studio Code so you can query official Microsoft documentation and code samples directly from your editor.&lt;br&gt;
You will need a VS Code installation with the latest updates, Internet and permission to install extensions.&lt;/p&gt;

&lt;p&gt;VS Code allows you to use MCP servers. An MCP server (Model Context Protocol server) is a small service that exposes tools and data to AI agents. Instead of returning only text, it can call real functions such as reading web pages or querying documentation and return structured results that the editor can use.&lt;/p&gt;

&lt;p&gt;As a cloud platform engineer or operator, you often switch between an editor and a browser to look up docs, examples, or snippets. The Microsoft Learn MCP server brings official docs and code samples into VS Code, so answers and examples appear where you work.&lt;/p&gt;

&lt;p&gt;To activate the MS Learn MCP server in VS Code, go to “Extensions” (or CTRL + Shift + x) and then type &lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt; &lt;br&gt;
You will have to enable the “MCP server marketplace” if it is the first time you do that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncmtl5cduncb2i3g2ns0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncmtl5cduncb2i3g2ns0.png" alt=" " width="401" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then search for the Microsoft Learn MCP server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddzin420tq1hhpui4nbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddzin420tq1hhpui4nbw.png" alt=" " width="383" height="862"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiqq5v3jufyotxwymzoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiqq5v3jufyotxwymzoa.png" alt=" " width="800" height="746"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then click on install. You now have access to the service.  &lt;/p&gt;

&lt;p&gt;To start using the MS Learn MCP server, open the AI shell with [Ctrl + Shift + I] in VSCode.&lt;/p&gt;

&lt;p&gt;Make sure you are in “Agent” mode in the chat windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmo6usqusks9vkay1nled.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmo6usqusks9vkay1nled.png" alt=" " width="335" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more context, I open a PowerShell file, then I can type the prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me an example of PowerShell code to create a VNET use microsoft_code_sample_search&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5od3fv0ow2dh2pnklzhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5od3fv0ow2dh2pnklzhg.png" alt=" " width="703" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The chat provides a sample code based on the MCP server. &lt;br&gt;
We can do the same with Azure Bicep.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I add the private subnet option to a subnet resource in Bicep? Use the microsoft_code_sample_search feature, which will provide a sample in Bicep. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you need to know more about the private subnet feature, you can use the MCP tool, microsoft_docs_search, to query Microsoft Doc. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;using microsoft_docs_search, explain the features of private subnets in an Azure VNet&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1uzz0gob6ueupzea8j9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1uzz0gob6ueupzea8j9.png" alt=" " width="688" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is another useful tool in the MCP server, microsoft_docs_fetch, which can take a Microsoft Doc page and put it in a Markdown format.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;microsoft_docs_fetch &lt;a href="https://learn.microsoft.com/en-us/azure/expressroute/resiliency-insights" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/expressroute/resiliency-insights&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezztqksqj0is055d239s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezztqksqj0is055d239s.png" alt=" " width="677" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is very useful when you are working on a documentation or on a script, you can have the Microsoft Documentation inside your editor. &lt;/p&gt;

&lt;p&gt;The MS Learn MCP server is an excellent introduction to the world of AI-assisted programming. It can help you solve a problem, reduce the number of tabs open in your browser, and be more efficient while working with VSCode.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>ai</category>
      <category>vscode</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Azure Bicep: Extension and local deploy</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Sun, 19 Oct 2025 06:28:28 +0000</pubDate>
      <link>https://dev.to/omiossec/azure-bicep-extension-and-local-deploy-45l1</link>
      <guid>https://dev.to/omiossec/azure-bicep-extension-and-local-deploy-45l1</guid>
      <description>&lt;p&gt;Bicep was created with a single goal: to simplify Azure resource deployment. Instead of writing verbose JSON, Bicep gives us a cleaner, more concise way to define infrastructure.&lt;/p&gt;

&lt;p&gt;But here’s the catch: like most Infrastructure as Code (IaC) tools, Bicep traditionally only deploys Azure resources. Modern deployments often require more than that; they need configuration tasks, data plane actions, or external integrations. The result? You end up gluing together multiple scripts in your pipeline, breaking the IaC promise of having a single source of truth.&lt;/p&gt;

&lt;p&gt;This is the purpose of Extension in Bicep. Extension is about doing things beyond the Azure Resource Manager.&lt;/p&gt;

&lt;p&gt;How does it work? When a Bicep template is published, the Azure Resource Manager API determines if a resource coded in the template should be deployed (like a storage account) or if another API should be used (like the Graph API for Entra resource). &lt;/p&gt;

&lt;p&gt;I already talked about the &lt;a href="https://dev.to/omiossec/using-azure-bicep-to-deploy-ms-graph-resources-gh"&gt;Azure Graph API for Bicep extension&lt;/a&gt;. This extension is &lt;a href="https://techcommunity.microsoft.com/blog/azuregovernanceandmanagementblog/announcing-ga-of-bicep-templates-support-for-microsoft-entra-id-resources/4437163" rel="noopener noreferrer"&gt;generally available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For an extension to work, the Azure Resource Manager API needs to be able to contact an external API. This is a huge limitation. Extensions must live inside the Azure ecosystem. This is the case for the Microsoft Graph and the Kubernetes extensions. Anything else was impossible. &lt;/p&gt;

&lt;p&gt;But with the Bicep Local deploy, experimental feature deployment occurs on the local devices without interacting with the Azure Resource Manager API.&lt;br&gt;
Local Deploy is a new experimental feature; you need to update your Bicep CLI (at least v0.30) to use it. &lt;/p&gt;

&lt;p&gt;There are already several extensions available; you can use them to make HTTP calls, manage GitHub or Azure DevOps, create passwords, execute scripts locally, and other things. &lt;/p&gt;

&lt;p&gt;You can get more information on these GitHub pages &lt;a href="https://github.com/maikvandergaag/bicep-extensions?tab=readme-ov-file" rel="noopener noreferrer"&gt;bicep-extensions&lt;/a&gt; and &lt;a href="https://github.com/Azure/bicep/blob/main/docs/experimental/local-deploy.md" rel="noopener noreferrer"&gt;Bicep GitHub Doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also create your own extension (but it is beyond the subject of this post), check &lt;a href="https://github.com/Azure/bicep/blob/main/docs/experimental/local-deploy-dotnet-quickstart.md" rel="noopener noreferrer"&gt;this&lt;/a&gt; and this &lt;a href="https://www.idontlikeai.dev/how-to-easily-developer-your-first-bicep-local-deploy-extension-with-bicep-localdeploy-templates/" rel="noopener noreferrer"&gt;post&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this post, I will use two extensions, [bicep-ext-local}(&lt;a href="https://github.com/anthony-c-martin/bicep-ext-local" rel="noopener noreferrer"&gt;https://github.com/anthony-c-martin/bicep-ext-local&lt;/a&gt;) to run scripts and bicep-ext-PassWordGenerator (&lt;a href="https://github.com/anthony-c-martin/bicep-ext-local" rel="noopener noreferrer"&gt;https://github.com/anthony-c-martin/bicep-ext-local&lt;/a&gt;) to generate random passwords. &lt;/p&gt;

&lt;p&gt;Keep in mind that local extensions run on the device where the Bicep code is executed. You need to check if the extension is compatible with your OS (Windows and Linux ARM may not be available).&lt;/p&gt;

&lt;p&gt;To use these extensions and the local deploy feature, the Bicep configuration must be updated. A bicepconfig.json file needs to be created in the same folder (or a parent folder) of the bicep files. You can check the documentation on this &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-config" rel="noopener noreferrer"&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We need to indicate Bicep to use the experimental local deploy feature and which extension to use. But also, as we need to manipulate passwords and want to print them for the demonstration, Bicep will return a warning (outputs-should-not-contain-secrets). The linter should be modified to avoid this warning. &lt;/p&gt;

&lt;p&gt;the bicepconfig.json file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"experimentalFeaturesEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"localDeploy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PassWordGenerator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"br:bicepextsys4opsacr.azurecr.io/extensions/passwordgenerator:0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"local"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"br:bicepextdemo.azurecr.io/extensions/local:0.1.3"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"analyzers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"outputs-should-not-contain-secrets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The BicepConfig file allows to use of the experimental feature, use the two extensions (passwordgenerator and local), and change the linter to not show a warning when a password is used in the output.&lt;/p&gt;

&lt;p&gt;The Bicep code used (main.bicep)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;targetScope = 'local'

extension PassWordGenerator
extension local

resource password 'GeneratedPassword'  = {
  name: 'pass'
  properties: {
    includeLower: true
    includeUpper: false
    includeDigits: true
    includeSpecial: false
    passwordLength: 20
  }
}

resource sayHelloWithPowerShell 'Script' = {
  type: 'powershell'
  script: replace(loadTextContent('./pwshscript.ps1'), '$input', 'dev.to')
}

output sayHelloWithPowerShell string = sayHelloWithPowerShell.stdout
output password string = password.output 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing to notice is the TargetScope statement. The value, local, indicates that local deploy will be used. Without enabling it in the bicepconfig file, it will generate an error. &lt;/p&gt;

&lt;p&gt;As you can only have one TargetScope statement in a deployment, including linked modules, you can only deploy locally. &lt;/p&gt;

&lt;p&gt;The two extension statements import the extension defined in the bicepconfig file.&lt;/p&gt;

&lt;p&gt;Then we have the two resources, the password and the script. &lt;br&gt;
The first one generates a random 20-character string in lowercase, the second one executes a script, pwshscript.ps1, in the same folder. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Write-Host "Hello from Bicep $($input)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you try to deploy the template, like any other template using Azure CLI or Azure PowerShell, you will get an “InvalidTemplateDeployment “error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UnknownExtension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unknown extension 'PassWordGenerator'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/resources/password"&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UnknownExtension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unknown extension 'Local'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/resources/sayHelloWithPowerShell"&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use local deploy, the latest version of Bicep CLI is needed. The command to use is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bicep local-deploy &amp;lt;PathToBicepParamFile&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You need to provide a bicep parameter file and not the path to the bicep template. &lt;br&gt;
In the same directory as the Bicep template, main.bicep, and the PowerShell script pwshscript.ps1, we need a main.bicepparam file. &lt;/p&gt;

&lt;p&gt;A bicepparam file defines values of parameters, but the template doesn’t have any parameters; it only needs to have a using close referencing the main.bicep.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;using 'main.bicep'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;bicep local-deploy&lt;/code&gt; produces this output&lt;/p&gt;

&lt;p&gt;password │ 5gmj6e7qrxktvxsuzakr &lt;br&gt;
sayHelloWithPowerShell │ Hello from Bicep&lt;/p&gt;

&lt;p&gt;Local Deploy is still experimental and limited, but it’s a big step forward. Combined with extensions like Microsoft Graph, it reduces the need for configuring resources or managing data plane and makes Bicep a true central point for both infrastructure and configuration.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
    </item>
    <item>
      <title>Azure Networking: Expanding Subnets with Multiple Prefixes without Downtime.</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Tue, 23 Sep 2025 21:04:21 +0000</pubDate>
      <link>https://dev.to/omiossec/azure-networking-expanding-subnets-with-multiple-prefixes-without-downtime-34lg</link>
      <guid>https://dev.to/omiossec/azure-networking-expanding-subnets-with-multiple-prefixes-without-downtime-34lg</guid>
      <description>&lt;p&gt;In Azure, a subnet has a single address prefix, a part of your Virtual Network (VNet) address space. This works fine until your workloads outgrow the available IPs. Traditionally, the fix meant creating a new subnet and moving resources, often causing downtime. Now, Azure has introduced a multiple-prefix subnet feature that lets you expand capacity without redeploying.&lt;/p&gt;

&lt;p&gt;Sometimes, your subnet prefix is too small and doesn’t fit your needs anymore. In many situations, it is not a problem. &lt;/p&gt;

&lt;p&gt;Think of a subnet as a logical grouping of virtual network interfaces (vNICs) that share the same network policies, like Network Security Groups (NSGs), NAT Gateways, and route tables. Within the same VNet, vNICs can communicate directly, regardless of which subnet they’re in. Adding a new prefix to the VNET and creating a new subnet will be enough to overcome the shortage of IP addresses in the first Subnet. &lt;/p&gt;

&lt;p&gt;But with stateful or large-scale deployments, like Virtual Machine Scale Sets (VMSS), IP exhaustion can be painful. Redeploying VMSS into a new subnet means downtime, scaling delays, and potential customer impact.&lt;/p&gt;

&lt;p&gt;Fortunately, a new feature in Azure Virtual Network allows you to add a new prefix to a subnet. This feature is only available in PowerShell, Azure CLI, ARM Template, and Bicep. &lt;/p&gt;

&lt;p&gt;Let’s take an example: an application needs an Azure SQL Database, a load balancer, and 10 to 15 VMs with the application. To ease the deployment, VMSS with the flexible orchestration mode. &lt;/p&gt;

&lt;p&gt;You create a VNET for the application, with the 192.168.0.0/24 prefix. Within this VNET, two subnets are created, one for the private endpoint of the Database, 192.168.0.0/29, and one for the VMSS and the LB (192.168.0.128/27). The last prefix has enough IP addresses to support scaling operation (27 free IPs).&lt;/p&gt;

&lt;p&gt;Everything works perfectly until the marketing team announces that the application will be presented on social media and TV, so you need to increase the capacity at least sixfold, which means at least 90 VMSS instances or a /25 prefix.&lt;/p&gt;

&lt;p&gt;There are two solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new subnet and move the VMSS. This is the default solution until now, but a downtime is needed.&lt;/li&gt;
&lt;li&gt;Add a prefix to the existing subnet. This is the new feature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A /25 prefix is needed, but to avoid any disturbance while scaling, a /24 is better. A new prefix will be added to the VNET and then to the subnet. &lt;/p&gt;

&lt;p&gt;The multiple-prefix feature is currently supported via PowerShell, Azure CLI, ARM templates, and Bicep. The Azure portal is not supported. Below is a PowerShell example to expand a subnet without downtime.&lt;/p&gt;

&lt;p&gt;The first step is to update the Azure PowerShell module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update-Module-NameAz-Force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, a new /24 prefix needs to be added to the current VNET.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-AzVirtualNetwork&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VnetName&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ResourceGroupName&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddressSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddressPrefixes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"192.168.1.0/24"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-AzVirtualNetwork-VirtualNetwork&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can add the new prefix to the subnet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Get-AzVirtualNetwork&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VnetName&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ResourceGroupName&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-AzVirtualNetworkSubnetConfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="s1"&gt;'APP'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-VirtualNetwork&lt;/span&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="nt"&gt;-AddressPrefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'192.168.0.128/27'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'192.168.1.0/24'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$vnet&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;Set-AzVirtualNetwork&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subnet has been updated. If you take a look at the Azure Portal, you will get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79m2q288gfos4g4bpzoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79m2q288gfos4g4bpzoj.png" alt=" " width="800" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that Azure reserves the first three available IP addresses of each prefix for internal use.&lt;/p&gt;

&lt;p&gt;However, you will have no option to manage this from the portal. &lt;/p&gt;

&lt;p&gt;But you can also manage multiple prefixes in a subnet using Bicep and ARM templates. You will need to use at least the 2018-08-01 API version to use the property called addressPrefixes. This property uses an array of strings as a value. &lt;/p&gt;

&lt;p&gt;In ARM/Bicep, the addressPrefixes property accepts an array of CIDR blocks. This is what enables multiple prefixes. You can still use addressPrefix for single values, but mixing the two in the same resource definition isn’t allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param location string = resourceGroup().location


@description('VNet name')
param vnetName string = 'vnet2'

@description('Vnet Address space')
param vnetAddressPrefix string = '10.0.0.0/8'

@description('First Subnet Prefix')
param subnetPrefix1 string  = '10.0.0.0/24'

@description('First Subnet Prefix')
param subnetPrefix2 string  = '10.0.1.0/24'

@description('Subnet1 Name')
param subnet1Name string  = 'sub1'

resource vnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        vnetAddressPrefix
      ]
    }

  }
}

resource subnet1 'Microsoft.Network/virtualNetworks/subnets@2024-07-01' =  {
  parent: vnet
  name: subnet1Name
  properties: {
    addressPrefixes: [
        subnetPrefix1
        subnetPrefix2
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Restrictions for Multiple-Prefix Subnets&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No subnet delegation (except VPN/ExpressRoute gateways)&lt;/li&gt;
&lt;li&gt;No VNet injection for container services&lt;/li&gt;
&lt;li&gt;Primarily supports IaaS workloads (VM, VMSS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practice&lt;/strong&gt;: Plan for growth by using addressPrefixes from the start in Bicep/ARM Template. Even if you only need one prefix today, defining it as an array future-proofs your network configuration.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>network</category>
    </item>
    <item>
      <title>Breaking change in Azure Network</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Tue, 15 Jul 2025 04:45:12 +0000</pubDate>
      <link>https://dev.to/omiossec/breaking-change-in-azure-network-4eap</link>
      <guid>https://dev.to/omiossec/breaking-change-in-azure-network-4eap</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/omiossec/about-the-implicit-outbound-connectivity-retirement-in-azure-1d6n" class="crayons-story__hidden-navigation-link"&gt;About the implicit outbound connectivity retirement in Azure on 31/03/2026&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/omiossec" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160244%2Ff2d80283-eb50-4e19-a699-1cd6ca166e49.jpg" alt="omiossec profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/omiossec" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Olivier Miossec
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Olivier Miossec
                
              
              &lt;div id="story-author-preview-content-2607268" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/omiossec" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160244%2Ff2d80283-eb50-4e19-a699-1cd6ca166e49.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Olivier Miossec&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/omiossec/about-the-implicit-outbound-connectivity-retirement-in-azure-1d6n" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 19 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/omiossec/about-the-implicit-outbound-connectivity-retirement-in-azure-1d6n" id="article-link-2607268"&gt;
          About the implicit outbound connectivity retirement in Azure on 31/03/2026
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/azure"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;azure&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/networking"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;networking&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/omiossec/about-the-implicit-outbound-connectivity-retirement-in-azure-1d6n#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>azure</category>
      <category>networking</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Tue, 15 Jul 2025 04:40:07 +0000</pubDate>
      <link>https://dev.to/omiossec/-11fb</link>
      <guid>https://dev.to/omiossec/-11fb</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/omiossec/azure-machine-configuration-deploy-dsc-config-to-azure-vms-hji" class="crayons-story__hidden-navigation-link"&gt;Azure Machine Configuration, deploy DSC config to Azure VMs.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/omiossec" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160244%2Ff2d80283-eb50-4e19-a699-1cd6ca166e49.jpg" alt="omiossec profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/omiossec" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Olivier Miossec
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Olivier Miossec
                
              
              &lt;div id="story-author-preview-content-2507323" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/omiossec" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160244%2Ff2d80283-eb50-4e19-a699-1cd6ca166e49.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Olivier Miossec&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/omiossec/azure-machine-configuration-deploy-dsc-config-to-azure-vms-hji" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 20 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/omiossec/azure-machine-configuration-deploy-dsc-config-to-azure-vms-hji" id="article-link-2507323"&gt;
          Azure Machine Configuration, deploy DSC config to Azure VMs.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/azure"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;azure&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/iac"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;iac&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/omiossec/azure-machine-configuration-deploy-dsc-config-to-azure-vms-hji" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/omiossec/azure-machine-configuration-deploy-dsc-config-to-azure-vms-hji#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>azure</category>
      <category>iac</category>
    </item>
    <item>
      <title>Azure RBAC roles, an advanced introduction</title>
      <dc:creator>Olivier Miossec</dc:creator>
      <pubDate>Thu, 10 Jul 2025 18:55:10 +0000</pubDate>
      <link>https://dev.to/omiossec/azure-rbac-an-advanced-introduction-g25</link>
      <guid>https://dev.to/omiossec/azure-rbac-an-advanced-introduction-g25</guid>
      <description>&lt;p&gt;Azure role-based access control (RBAC) roles are essential in any organization to create granular access to resources across subscriptions.&lt;/p&gt;

&lt;p&gt;Azure RBAC lets you define your roles, allowing you to create fine-grained permissions that you can’t find in built-in roles. &lt;br&gt;
A custom role is defined by an ID, a name, an assignable scope (such as subscriptions or management groups), a description, and specific permissions. There are several kinds of permission; the most important is “Actions” (it is mandatory when creating a costume role), there are also “noActions”, “DataActions”, and “noDataActions” properties.&lt;/p&gt;

&lt;p&gt;“Actions” list what you can do on the control plane of resources. Thinks about all actions on a resource like a virtual machine or a storage action that do not include accessing data. DataActions list what you can do on the data plate of resources, think about what is inside an Azure Key Vault, or data in a storage account. &lt;br&gt;
The purpose of noActions and noDataActions is to remove a permission that is listed in the “Actions” or “DataActions” properties. Because permissions are a hierarchy of actions, starting with a resource type and subtype. &lt;br&gt;
For example, this is the list of all actions for virtual machines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/write",
"Microsoft.Compute/virtualMachines/delete",
"Microsoft.Compute/virtualMachines/start/action",                  "Microsoft.Compute/virtualMachines/powerOff/action",
"Microsoft.Compute/virtualMachines/reapply/action",
"Microsoft.Compute/virtualMachines/redeploy/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/retrieveBootDiagnosticsData/action",
"Microsoft.Compute/virtualMachines/deallocate/action",
"Microsoft.Compute/virtualMachines/generalize/action",
"Microsoft.Compute/virtualMachines/capture/action",
"Microsoft.Compute/virtualMachines/runCommand/action",
"Microsoft.Compute/virtualMachines/convertToManagedDisks/action",
"Microsoft.Compute/virtualMachines/performMaintenance/action",
"Microsoft.Compute/virtualMachines/reimage/action",
"Microsoft.Compute/virtualMachines/installPatches/action",
"Microsoft.Compute/virtualMachines/assessPatches/action",
"Microsoft.Compute/virtualMachines/cancelPatchInstallation/action",
"Microsoft.Compute/virtualMachines/simulateEviction/action",
"Microsoft.Compute/virtualMachines/osUpgradeInternal/action",
"Microsoft.Compute/virtualMachines/rollbackOSDisk/action",
"Microsoft.Compute/virtualMachines/deletePreservedOSDisk/action",
"Microsoft.Compute/virtualMachines/upgradeVMAgent/action",
"Microsoft.Compute/virtualMachines/attachDetachDataDisks/action",
"Microsoft.Compute/virtualMachines/patchAssessmentResults/latest/read",
"Microsoft.Compute/virtualMachines/patchAssessmentResults/latest/softwarePatches/read",
"Microsoft.Compute/virtualMachines/patchInstallationResults/read",
"Microsoft.Compute/virtualMachines/patchInstallationResults/softwarePatches/read",
"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/logDefinitions/read",
"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/diagnosticSettings/read",
"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/diagnosticSettings/write",
"Microsoft.Compute/virtualMachines/extensions/read",
"Microsoft.Compute/virtualMachines/extensions/write",
"Microsoft.Compute/virtualMachines/extensions/delete",
"Microsoft.Compute/virtualMachines/instanceView/read",
"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/metricDefinitions/read",
"Microsoft.Compute/virtualMachines/runCommands/read",
"Microsoft.Compute/virtualMachines/runCommands/write",
"Microsoft.Compute/virtualMachines/runCommands/delete",
"Microsoft.Compute/virtualMachines/vmSizes/read"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see that you see the hierarchy (Microsoft.Compute, then virtual machine, then a child resource, and an action or an action). &lt;br&gt;
Because it can be error-prone and boring to write every single permission for virtual machines (about 40 possible actions), you can use a wildcard. &lt;br&gt;
"Microsoft.Compute/virtualMachines/&lt;em&gt;"&lt;br&gt;
You can see here the utility of no action. If you want to give all permissions except one, you can use noAction to remove a permission. For example, if you want to give all actions except "Microsoft.Compute/virtualMachines/runCommands/delete", and "Microsoft.Compute/virtualMachines/extensions/delete", you can add it the the noAction property. &lt;br&gt;
To get all the possible permissions from a resource, you can use PowerShell:&lt;br&gt;
`Get-AzProviderOperation "Microsoft.Compute/virtualMachines/&lt;/em&gt;/*" | select-object OperationName, Operation, Description`&lt;br&gt;
PowerShell can create a custom role by using a JSON file defining the role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Demo Role 01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows all actions on VM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachines/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Management/managementGroups/test-mg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create the role &lt;br&gt;
&lt;code&gt;New-AzRoleDefinition -InputFile "./role1.json"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, if we want to restrict the role to perform delete operations on VM extensions and runCommands we can add these two actions to the noActions parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Demo Role 02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows all actions on VM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachines/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachines/runCommands/delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachines/extensions/delete"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Management/managementGroups/group01"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if a role needs to allow all actions on VMs (Microsoft.Compute/virtualMachines) and VMSSs (Microsoft.Compute/virtualMachineScaleSets), we can add both resources to the "Actions" parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Demo Role 03"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows all actions on VM and VMSS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachines/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/virtualMachineScaleSets/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Management/managementGroups/group01"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use a wildcard on Microsoft.compute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Demo Role 04"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows all actions on MS Compute with wildcard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Management/managementGroups/group01"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow 279 different actions, and that could be a problem. The role created by this JSON file will have every permission possible from the Microsoft.compute service, including actions that may be added in the future. This is the opposite of a fine-grained security policy. It is just like using a medieval axe to perform microsurgery. &lt;br&gt;
By using Microsoft.compute/* alone, I get 279 possible actions. What about using “*/read”? The number is 9840 possible actions! This leaves a place for malicious actions. &lt;br&gt;
But this is the case with some built-in roles, the reader role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"roleName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"View all resources, but does not allow you to make any changes."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"assignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"*/read"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"notActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"dataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"notDataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or User Access Administrator&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"roleName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User Access Administrator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lets you manage user access to Azure resources."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"assignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"*/read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Authorization/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Support/*"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"notActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"dataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"notDataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Several built-in roles are too permissive. Custom roles, with fewer actions, should be used instead. It can be long and boring, but it will limit your attack surface. &lt;/p&gt;

</description>
      <category>azure</category>
    </item>
  </channel>
</rss>
