[{"data":1,"prerenderedAt":12817},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-Azure CLI":397},[4,192,200],{"title":5,"_path":6,"children":7,"icon":191},"Blog","/posts",[8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,77,80,83,86,89,92,95,98,101,104,107,110,113,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,188],{"title":9,"_path":10},"Testing your API with REST Client","/posts/testing-your-api-with-rest-client",{"title":12,"_path":13},"HTML templating in Xamarin","/posts/html-templating-in-xamarin",{"title":15,"_path":16},"Goodbye Azure Portal, Welcome Azure CLI","/posts/welcome-azure-cli",{"title":18,"_path":19},"Coming across Gitpod","/posts/gitpod",{"title":21,"_path":22},"Handle token retrieval while querying an API","/posts/delegating-handler",{"title":24,"_path":25},"Clean up your local git branches.","/posts/cleaning-git-branches",{"title":27,"_path":28},"Automate configuration of Teams Tab SSO with PowerShell.","/posts/teams-sso-powershell",{"title":30,"_path":31},"How to do a technology watch? - Part 1","/posts/technology-watch-part1",{"title":33,"_path":34},"How to do a technology watch? - Part 2","/posts/technology-watch-part2",{"title":36,"_path":37},"You almost no longer need Key Vault references for Azure Functions.","/posts/azure-functions-custom-configuration",{"title":39,"_path":40},"How to do a technology watch? - Part 3","/posts/technology-watch-part3",{"title":42,"_path":43},"Forget DevOps, the future is already here!","/posts/devops-future",{"title":45,"_path":46},"Week 9, 2021 - Tips I learned this week","/posts/w09-2021-tips-learned-this-week",{"title":48,"_path":49},"Week 12, 2021 - Tips I learned this week","/posts/w12-2021-tips-learned-this-week",{"title":51,"_path":52},"Week 14, 2021 - Tips I learned this week","/posts/w14-2021-tips-learned-this-week",{"title":54,"_path":55},"Once upon a time in .NET","/posts/once-upon-a-time-in-dotnet",{"title":57,"_path":58},"Install your applications with winget","/posts/winget-import",{"title":60,"_path":61},"Customize your applications when installing them with winget","/posts/winget-override",{"title":63,"_path":64},"Week 22, 2021 - Tips I learned this week","/posts/w22-2021-tips-learned-this-week",{"title":66,"_path":67},"How to connect to an Azure SQL Database from C# using Azure AD","/posts/sqlclient-active-directory-authent",{"title":69,"_path":70},"Producing packages for Windows Package Manager","/posts/wingetcreate",{"title":72,"_path":73},"4 tips about GitHub Actions environment variables and contexts","/posts/github-actions-var-and-context",{"title":75,"_path":76},"AzureWebJobsStorage, the secret you don't need in your Function App.","/posts/azure-functions-without-azurewebjobsstorage",{"title":78,"_path":79},"ASP.NET Core - Lost in configuration","/posts/lost-in-configuration",{"title":81,"_path":82},"Week 39, 2021 - Tips I learned this week","/posts/w39-2021-tips-learned-this-week",{"title":84,"_path":85},"Week 41, 2021 - Tips I learned this week","/posts/w41-2021-tips-learned-this-week",{"title":87,"_path":88},"Migrating and open-sourcing my blog","/posts/migrating-blog",{"title":90,"_path":91},"Week 45, 2021 - Tips I learned this week","/posts/w45-2021-tips-learned-this-week",{"title":93,"_path":94},"Organize your GitHub stars with Astral","/posts/astral",{"title":96,"_path":97},"Pulumi with an Azure Blob Storage backend","/posts/pulumi-azure-backend",{"title":99,"_path":100},"IaC Hot Reload with Pulumi Watch","/posts/pulumi-watch",{"title":102,"_path":103},"Week 2, 2022 - Tips I learned this week","/posts/w02-2022-tips-learned-this-week",{"title":105,"_path":106},"Week 3, 2022 - Tips I learned this week","/posts/w03-2022-tips-learned-this-week",{"title":108,"_path":109},"Week 5, 2022 - Tips I learned this week","/posts/w05-2022-tips-learned-this-week",{"title":111,"_path":112},"How to provision an Azure SQL Database with Active Directory authentication","/posts/sqldatabase-active-directory-authent",{"title":114,"_path":115},"Why will I choose Pulumi over Terraform for my next project?","/posts/pulumi-vs-terraform",{"title":117,"_path":118},"Week 19, 2022 - Tips I learned this week","/posts/w19-2022-tips-learned-this-week",{"title":120,"_path":121},"Week 20, 2022 - Tips I learned this week","/posts/w20-2022-tips-learned-this-week",{"title":123,"_path":124},"Keeping secrets secure when using API Clients","/posts/http-clients-secrets",{"title":126,"_path":127},"What made me want to be a developer?","/posts/be-a-developer",{"title":129,"_path":130},"What can we do when stuck with a programming problem?","/posts/get-unstuck",{"title":132,"_path":133},"How did I automate the setup of my developer Windows laptop?","/posts/automate-developer-machine",{"title":135,"_path":136},"Discussion about API clients","/posts/http-clients",{"title":138,"_path":139},"Week 46, 2022 - Tips I learned this week","/posts/w46-2022-tips-learned-this-week",{"title":141,"_path":142},"When Pulumi met Nuke: a .NET love story","/posts/when-pulumi-met-nuke",{"title":144,"_path":145},"A year of learning and sharing - Dev Retro 2022","/posts/2022-retro",{"title":147,"_path":148},"Perform Dynamic Execution of an npm Package","/posts/pnpm-dlx",{"title":150,"_path":151},"Manage multiple Node.js versions","/posts/pnpm-env",{"title":153,"_path":154},"Introducing the Vue.js CI/CD series","/posts/vuecicd-introduction",{"title":156,"_path":157},"Execute commands using your project dependencies","/posts/pnpm-exec",{"title":159,"_path":160},"Vue.js CI/CD: Continuous Integration","/posts/vuecicd-ci",{"title":162,"_path":163},"Who is using pnpm?","/posts/pnpm-who-is-using",{"title":165,"_path":166},"Create an Azure-Ready GitHub Repository using Pulumi","/posts/azure-ready-github-repository",{"title":168,"_path":169},"Deploying to Azure from Azure DevOps without secrets","/posts/ado-workload-identity-federation",{"title":171,"_path":172},"Effortlessly Configure GitHub Repositories for Azure Deployment via OIDC","/posts/scripting-azure-ready-github-repository",{"title":174,"_path":175},"Playing with the .NET 8 Web API template","/posts/playing-with-dotnet8",{"title":177,"_path":178},"Another year of sharing and learning - Dev Retro 2023","/posts/2023-retro",{"title":180,"_path":181},"Week 4, 2024 - Tips I learned this week","/posts/w04-2024-tips-learned-this-week",{"title":183,"_path":184},"Using dependency injection with Azure .NET SDK","/posts/azure-sdk-di",{"title":186,"_path":187},"Having Fun With IT Event Calendars","/posts/it-event-calendars",{"title":189,"_path":190},"Call your Azure AD B2C protected API with authenticated HTTP requests from your JetBrains IDE","/posts/http-clients-oauth2","i-heroicons-newspaper",{"title":193,"_path":194,"children":195,"icon":199},"Goodies","/goodies",[196],{"title":197,"_path":198},"My Git Cheat Sheet","/goodies/gitcheatsheet","i-heroicons-gift-solid",{"title":201,"_path":202,"icon":203},"About","/about","i-heroicons-user-circle-solid",[205,207,209,211,214,217,220,223,226,229,231,234,237,240,242,244,247,250,253,255,258,261,264,267,270,273,276,279,282,285,287,289,292,294,297,300,303,305,308,310,313,316,319,322,325,327,329,332,335,338,341,344,347,350,353,356,359,361,363,366,369,372,375,377,380,383,385,388,391,394],[206,206],"tooling",[208,208],"vscode",[210,210],"rest",[212,213],"http","HTTP",[215,216],"razor","Razor",[218,219],"xamarin","Xamarin",[221,222],"templating","Templating",[224,225],"azure-cli","Azure CLI",[227,228],"azure","Azure",[230,230],"shell",[232,233],"github","GitHub",[235,236],"asp-net-core","ASP.NET Core",[238,239],"net",".NET",[241,241],"git",[243,243],"nushell",[245,246],"microsoft-teams","Microsoft Teams",[248,249],"powershell","PowerShell",[251,252],"azure-active-directory","Azure Active Directory",[254,254],"learning",[256,257],"azure-functions","Azure Functions",[259,260],"azure-key-vault","Azure Key Vault",[262,263],"configuration","Configuration",[265,266],"devops","DevOps",[268,269],"it","IT",[271,272],"tips-learned-this-week","tips learned this week",[274,275],"windows-terminal","Windows Terminal",[277,278],"azure-pipelines","Azure Pipelines",[280,281],"application-insights","Application Insights",[283,284],"azure-iot","Azure IoT",[286,286],"records",[288,288],"refit",[290,291],"development-box-setup","development box setup",[293,293],"winget",[295,296],"package-manager","package manager",[298,299],"azure-sql-database","Azure SQL Database",[301,302],"azure-sdk","Azure SDK",[304,304],"wingetcreate",[306,307],"github-actions","GitHub Actions",[309,309],"jq",[311,312],"pulumi","Pulumi",[314,315],"iac","IaC",[317,318],"azure-storage","Azure Storage",[320,321],"azure-signalr","Azure SignalR",[323,324],"visio","Visio",[326,326],"csharp",[328,328],"jest",[330,331],"statiq","Statiq",[333,334],"open-source","open source",[336,337],"visual-studio","Visual Studio",[339,340],"vue-js","Vue.js",[342,343],"azure-devops","Azure DevOps",[345,346],"vite","Vite",[348,349],"code-analysis","Code analysis",[351,352],"diagram","Diagram",[354,355],"terraform","Terraform",[357,358],"typescript","TypeScript",[360,360],"thoughts",[362,362],"pnpm",[364,365],"nuke","Nuke",[367,368],"pipelines","Pipelines",[370,371],"cicd","CI/CD",[373,374],"openid-connect","OpenID Connect",[376,376],"security",[378,379],"github-cli","GitHub CLI",[381,382],"microsoft-entra-id","Microsoft Entra ID",[384,384],"advent",[386,387],"finops","FinOps",[389,390],"anglesharp","AngleSharp",[392,393],"oauth2","OAuth2",[395,396],"azure-ad-b2c","Azure AD B2C",[398,3731,4754,4999,7564,9977,10332],{"_path":172,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":171,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":408,"body":409,"_type":3726,"_id":3727,"_source":3728,"_file":3729,"_extension":3730},"posts",false,"","What if we could script the creation and configuration of a GitHub Repository so that it is ready to provision or deploy Azure resources from a GitHub Actions pipeline? We will do that in this article using the Azure CLI and GitHub CLI.","Scripting your Azure-Ready GitHub Repository using Azure and GitHub CLI","2023-10-23T00:00:00.000Z",{"src":406},"/images/azureOIDC_2.webp",{"label":266},[228,225,233,379,307,374,382],{"type":410,"children":411,"toc":3715},"root",[412,419,426,431,436,807,823,828,840,859,865,872,886,899,911,917,930,935,1006,1011,1101,1126,1131,1198,1229,1235,1240,1356,1388,1393,1565,1570,1703,1708,1923,1948,1961,2081,2086,2143,2149,2154,2174,2256,2261,2366,2375,2381,3655,3661,3674,3679,3699,3704,3709],{"type":413,"tag":414,"props":415,"children":416},"element","p",{},[417],{"type":418,"value":402},"text",{"type":413,"tag":420,"props":421,"children":423},"h2",{"id":422},"the-objective",[424],{"type":418,"value":425},"The Objective",{"type":413,"tag":414,"props":427,"children":428},{},[429],{"type":418,"value":430},"The goal is to go from nothing to running a GitHub Actions workflow that authenticates to Azure using Open ID Connect (so without secret credentials) in a newly created GitHub repository.",{"type":413,"tag":414,"props":432,"children":433},{},[434],{"type":418,"value":435},"The workflow we plan to run is as follows:",{"type":413,"tag":437,"props":438,"children":442},"pre",{"className":439,"code":440,"language":441,"meta":401,"style":401},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: Run Azure Login with OIDC\non:\n  workflow_dispatch:\n\npermissions:\n  id-token: write\n  contents: read\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Az CLI login'\n        uses: azure/login@v1\n        with:\n          client-id: ${{ secrets.AZURE_CLIENT_ID }}\n          tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n\n      - name: 'Run az commands'\n        run: |\n          az account show\n          az group list\n","yaml",[443],{"type":413,"tag":444,"props":445,"children":446},"code",{"__ignoreMap":401},[447,471,486,499,509,522,540,558,571,584,602,615,648,666,679,697,715,733,741,770,789,798],{"type":413,"tag":448,"props":449,"children":452},"span",{"class":450,"line":451},"line",1,[453,459,465],{"type":413,"tag":448,"props":454,"children":456},{"style":455},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[457],{"type":418,"value":458},"name",{"type":413,"tag":448,"props":460,"children":462},{"style":461},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[463],{"type":418,"value":464},":",{"type":413,"tag":448,"props":466,"children":468},{"style":467},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[469],{"type":418,"value":470}," Run Azure Login with OIDC\n",{"type":413,"tag":448,"props":472,"children":474},{"class":450,"line":473},2,[475,481],{"type":413,"tag":448,"props":476,"children":478},{"style":477},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[479],{"type":418,"value":480},"on",{"type":413,"tag":448,"props":482,"children":483},{"style":461},[484],{"type":418,"value":485},":\n",{"type":413,"tag":448,"props":487,"children":489},{"class":450,"line":488},3,[490,495],{"type":413,"tag":448,"props":491,"children":492},{"style":455},[493],{"type":418,"value":494},"  workflow_dispatch",{"type":413,"tag":448,"props":496,"children":497},{"style":461},[498],{"type":418,"value":485},{"type":413,"tag":448,"props":500,"children":502},{"class":450,"line":501},4,[503],{"type":413,"tag":448,"props":504,"children":506},{"emptyLinePlaceholder":505},true,[507],{"type":418,"value":508},"\n",{"type":413,"tag":448,"props":510,"children":512},{"class":450,"line":511},5,[513,518],{"type":413,"tag":448,"props":514,"children":515},{"style":455},[516],{"type":418,"value":517},"permissions",{"type":413,"tag":448,"props":519,"children":520},{"style":461},[521],{"type":418,"value":485},{"type":413,"tag":448,"props":523,"children":525},{"class":450,"line":524},6,[526,531,535],{"type":413,"tag":448,"props":527,"children":528},{"style":455},[529],{"type":418,"value":530},"  id-token",{"type":413,"tag":448,"props":532,"children":533},{"style":461},[534],{"type":418,"value":464},{"type":413,"tag":448,"props":536,"children":537},{"style":467},[538],{"type":418,"value":539}," write\n",{"type":413,"tag":448,"props":541,"children":543},{"class":450,"line":542},7,[544,549,553],{"type":413,"tag":448,"props":545,"children":546},{"style":455},[547],{"type":418,"value":548},"  contents",{"type":413,"tag":448,"props":550,"children":551},{"style":461},[552],{"type":418,"value":464},{"type":413,"tag":448,"props":554,"children":555},{"style":467},[556],{"type":418,"value":557}," read\n",{"type":413,"tag":448,"props":559,"children":561},{"class":450,"line":560},8,[562,567],{"type":413,"tag":448,"props":563,"children":564},{"style":455},[565],{"type":418,"value":566},"jobs",{"type":413,"tag":448,"props":568,"children":569},{"style":461},[570],{"type":418,"value":485},{"type":413,"tag":448,"props":572,"children":574},{"class":450,"line":573},9,[575,580],{"type":413,"tag":448,"props":576,"children":577},{"style":455},[578],{"type":418,"value":579},"  build-and-deploy",{"type":413,"tag":448,"props":581,"children":582},{"style":461},[583],{"type":418,"value":485},{"type":413,"tag":448,"props":585,"children":587},{"class":450,"line":586},10,[588,593,597],{"type":413,"tag":448,"props":589,"children":590},{"style":455},[591],{"type":418,"value":592},"    runs-on",{"type":413,"tag":448,"props":594,"children":595},{"style":461},[596],{"type":418,"value":464},{"type":413,"tag":448,"props":598,"children":599},{"style":467},[600],{"type":418,"value":601}," ubuntu-latest\n",{"type":413,"tag":448,"props":603,"children":605},{"class":450,"line":604},11,[606,611],{"type":413,"tag":448,"props":607,"children":608},{"style":455},[609],{"type":418,"value":610},"    steps",{"type":413,"tag":448,"props":612,"children":613},{"style":461},[614],{"type":418,"value":485},{"type":413,"tag":448,"props":616,"children":618},{"class":450,"line":617},12,[619,624,629,633,638,643],{"type":413,"tag":448,"props":620,"children":621},{"style":461},[622],{"type":418,"value":623},"      -",{"type":413,"tag":448,"props":625,"children":626},{"style":455},[627],{"type":418,"value":628}," name",{"type":413,"tag":448,"props":630,"children":631},{"style":461},[632],{"type":418,"value":464},{"type":413,"tag":448,"props":634,"children":635},{"style":461},[636],{"type":418,"value":637}," '",{"type":413,"tag":448,"props":639,"children":640},{"style":467},[641],{"type":418,"value":642},"Az CLI login",{"type":413,"tag":448,"props":644,"children":645},{"style":461},[646],{"type":418,"value":647},"'\n",{"type":413,"tag":448,"props":649,"children":651},{"class":450,"line":650},13,[652,657,661],{"type":413,"tag":448,"props":653,"children":654},{"style":455},[655],{"type":418,"value":656},"        uses",{"type":413,"tag":448,"props":658,"children":659},{"style":461},[660],{"type":418,"value":464},{"type":413,"tag":448,"props":662,"children":663},{"style":467},[664],{"type":418,"value":665}," azure/login@v1\n",{"type":413,"tag":448,"props":667,"children":669},{"class":450,"line":668},14,[670,675],{"type":413,"tag":448,"props":671,"children":672},{"style":455},[673],{"type":418,"value":674},"        with",{"type":413,"tag":448,"props":676,"children":677},{"style":461},[678],{"type":418,"value":485},{"type":413,"tag":448,"props":680,"children":682},{"class":450,"line":681},15,[683,688,692],{"type":413,"tag":448,"props":684,"children":685},{"style":455},[686],{"type":418,"value":687},"          client-id",{"type":413,"tag":448,"props":689,"children":690},{"style":461},[691],{"type":418,"value":464},{"type":413,"tag":448,"props":693,"children":694},{"style":467},[695],{"type":418,"value":696}," ${{ secrets.AZURE_CLIENT_ID }}\n",{"type":413,"tag":448,"props":698,"children":700},{"class":450,"line":699},16,[701,706,710],{"type":413,"tag":448,"props":702,"children":703},{"style":455},[704],{"type":418,"value":705},"          tenant-id",{"type":413,"tag":448,"props":707,"children":708},{"style":461},[709],{"type":418,"value":464},{"type":413,"tag":448,"props":711,"children":712},{"style":467},[713],{"type":418,"value":714}," ${{ secrets.AZURE_TENANT_ID }}\n",{"type":413,"tag":448,"props":716,"children":718},{"class":450,"line":717},17,[719,724,728],{"type":413,"tag":448,"props":720,"children":721},{"style":455},[722],{"type":418,"value":723},"          subscription-id",{"type":413,"tag":448,"props":725,"children":726},{"style":461},[727],{"type":418,"value":464},{"type":413,"tag":448,"props":729,"children":730},{"style":467},[731],{"type":418,"value":732}," ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n",{"type":413,"tag":448,"props":734,"children":736},{"class":450,"line":735},18,[737],{"type":413,"tag":448,"props":738,"children":739},{"emptyLinePlaceholder":505},[740],{"type":418,"value":508},{"type":413,"tag":448,"props":742,"children":744},{"class":450,"line":743},19,[745,749,753,757,761,766],{"type":413,"tag":448,"props":746,"children":747},{"style":461},[748],{"type":418,"value":623},{"type":413,"tag":448,"props":750,"children":751},{"style":455},[752],{"type":418,"value":628},{"type":413,"tag":448,"props":754,"children":755},{"style":461},[756],{"type":418,"value":464},{"type":413,"tag":448,"props":758,"children":759},{"style":461},[760],{"type":418,"value":637},{"type":413,"tag":448,"props":762,"children":763},{"style":467},[764],{"type":418,"value":765},"Run az commands",{"type":413,"tag":448,"props":767,"children":768},{"style":461},[769],{"type":418,"value":647},{"type":413,"tag":448,"props":771,"children":773},{"class":450,"line":772},20,[774,779,783],{"type":413,"tag":448,"props":775,"children":776},{"style":455},[777],{"type":418,"value":778},"        run",{"type":413,"tag":448,"props":780,"children":781},{"style":461},[782],{"type":418,"value":464},{"type":413,"tag":448,"props":784,"children":786},{"style":785},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[787],{"type":418,"value":788}," |\n",{"type":413,"tag":448,"props":790,"children":792},{"class":450,"line":791},21,[793],{"type":413,"tag":448,"props":794,"children":795},{"style":467},[796],{"type":418,"value":797},"          az account show\n",{"type":413,"tag":448,"props":799,"children":801},{"class":450,"line":800},22,[802],{"type":413,"tag":448,"props":803,"children":804},{"style":467},[805],{"type":418,"value":806},"          az group list\n",{"type":413,"tag":414,"props":808,"children":809},{},[810,812,821],{"type":418,"value":811},"This workflow is an example coming from ",{"type":413,"tag":813,"props":814,"children":818},"a",{"href":815,"rel":816},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure",[817],"nofollow",[819],{"type":418,"value":820},"the GitHub documentation",{"type":418,"value":822}," showing how to configure GitHub Actions workflow to access Azure resources protected by Microsoft Entra.",{"type":413,"tag":414,"props":824,"children":825},{},[826],{"type":418,"value":827},"To run this workflow we will need to automate the configuration of these resources:",{"type":413,"tag":414,"props":829,"children":830},{},[831],{"type":413,"tag":832,"props":833,"children":839},"img",{"alt":834,"className":835,"src":838},"A diagram showing the interactions between Azure and GitHub.",[836,837],"rounded-lg","mx-auto","/posts/images/scripting_azurereadygithub_azure_1.webp",[],{"type":413,"tag":841,"props":842,"children":844},"callout",{"icon":843},"i-heroicons-chat-bubble-left-20-solid",[845],{"type":413,"tag":414,"props":846,"children":847},{},[848,850,857],{"type":418,"value":849},"Looks familiar? That's the same diagram from my article about ",{"type":413,"tag":813,"props":851,"children":854},{"href":852,"rel":853},"https://www.techwatching.dev/posts/azure-ready-github-repository",[817],[855],{"type":418,"value":856},"creating an Azure-Ready GitHub Repository using Pulumi",{"type":418,"value":858},". The purpose was the same but using Pulumi instead of CLI tools. If you prefer a declarative Infrastructure as Code approach using programming languages over CLI tools, you should definitively read it 😉",{"type":413,"tag":420,"props":860,"children":862},{"id":861},"the-script",[863],{"type":418,"value":864},"The Script",{"type":413,"tag":866,"props":867,"children":869},"h3",{"id":868},"a-word-about-the-tools-used",[870],{"type":418,"value":871},"A word about the tools used",{"type":413,"tag":414,"props":873,"children":874},{},[875,877,884],{"type":418,"value":876},"I will be using ",{"type":413,"tag":813,"props":878,"children":881},{"href":879,"rel":880},"https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3",[817],[882],{"type":418,"value":883},"PowerShell which is cross-platform",{"type":418,"value":885},". However, if you prefer using a different shell, you will simply need to adjust some syntax (such as the environment variable declarations) to ensure compatibility.",{"type":413,"tag":414,"props":887,"children":888},{},[889,891,897],{"type":418,"value":890},"To create and configure the Microsoft Entra ID resources, we will need the ",{"type":413,"tag":813,"props":892,"children":895},{"href":893,"rel":894},"https://learn.microsoft.com/en-us/cli/azure/install-azure-cli",[817],[896],{"type":418,"value":225},{"type":418,"value":898},".",{"type":413,"tag":414,"props":900,"children":901},{},[902,904,910],{"type":418,"value":903},"To create and configure the GitHub repository, we will need the ",{"type":413,"tag":813,"props":905,"children":908},{"href":906,"rel":907},"https://cli.github.com/",[817],[909],{"type":418,"value":379},{"type":418,"value":898},{"type":413,"tag":866,"props":912,"children":914},{"id":913},"create-the-repository-on-github",[915],{"type":418,"value":916},"Create the repository on GitHub",{"type":413,"tag":414,"props":918,"children":919},{},[920,922,928],{"type":418,"value":921},"Let's assume we are already in a new directory with the YAML workflow file ",{"type":413,"tag":444,"props":923,"children":925},{"className":924},[],[926],{"type":418,"value":927},".github\\workflows\\main.yml",{"type":418,"value":929}," in it.",{"type":413,"tag":414,"props":931,"children":932},{},[933],{"type":418,"value":934},"First, we can initialize the git repository.",{"type":413,"tag":437,"props":936,"children":940},{"className":937,"code":938,"language":939,"meta":401,"style":401},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git init\ngit add .\ngit commit -m \"Intialize repository with the GitHub Actions workflow file\"\n","bash",[941],{"type":413,"tag":444,"props":942,"children":943},{"__ignoreMap":401},[944,957,974],{"type":413,"tag":448,"props":945,"children":946},{"class":450,"line":451},[947,952],{"type":413,"tag":448,"props":948,"children":950},{"style":949},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[951],{"type":418,"value":241},{"type":413,"tag":448,"props":953,"children":954},{"style":467},[955],{"type":418,"value":956}," init\n",{"type":413,"tag":448,"props":958,"children":959},{"class":450,"line":473},[960,964,969],{"type":413,"tag":448,"props":961,"children":962},{"style":949},[963],{"type":418,"value":241},{"type":413,"tag":448,"props":965,"children":966},{"style":467},[967],{"type":418,"value":968}," add",{"type":413,"tag":448,"props":970,"children":971},{"style":467},[972],{"type":418,"value":973}," .\n",{"type":413,"tag":448,"props":975,"children":976},{"class":450,"line":488},[977,981,986,991,996,1001],{"type":413,"tag":448,"props":978,"children":979},{"style":949},[980],{"type":418,"value":241},{"type":413,"tag":448,"props":982,"children":983},{"style":467},[984],{"type":418,"value":985}," commit",{"type":413,"tag":448,"props":987,"children":988},{"style":467},[989],{"type":418,"value":990}," -m",{"type":413,"tag":448,"props":992,"children":993},{"style":461},[994],{"type":418,"value":995}," \"",{"type":413,"tag":448,"props":997,"children":998},{"style":467},[999],{"type":418,"value":1000},"Intialize repository with the GitHub Actions workflow file",{"type":413,"tag":448,"props":1002,"children":1003},{"style":461},[1004],{"type":418,"value":1005},"\"\n",{"type":413,"tag":414,"props":1007,"children":1008},{},[1009],{"type":418,"value":1010},"Second, we can create the GitHub repository and push the git repository we just initialized in it.",{"type":413,"tag":437,"props":1012,"children":1015},{"className":1013,"code":1014,"language":248,"meta":401,"style":401},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","$repositoryName = \"MyAzureReadyRepository\"\ngh repo create $repositoryName --private --source=. --push\n",[1016],{"type":413,"tag":444,"props":1017,"children":1018},{"__ignoreMap":401},[1019,1051],{"type":413,"tag":448,"props":1020,"children":1021},{"class":450,"line":451},[1022,1027,1033,1038,1042,1047],{"type":413,"tag":448,"props":1023,"children":1024},{"style":461},[1025],{"type":418,"value":1026},"$",{"type":413,"tag":448,"props":1028,"children":1030},{"style":1029},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1031],{"type":418,"value":1032},"repositoryName ",{"type":413,"tag":448,"props":1034,"children":1035},{"style":461},[1036],{"type":418,"value":1037},"=",{"type":413,"tag":448,"props":1039,"children":1040},{"style":461},[1041],{"type":418,"value":995},{"type":413,"tag":448,"props":1043,"children":1044},{"style":467},[1045],{"type":418,"value":1046},"MyAzureReadyRepository",{"type":413,"tag":448,"props":1048,"children":1049},{"style":461},[1050],{"type":418,"value":1005},{"type":413,"tag":448,"props":1052,"children":1053},{"class":450,"line":473},[1054,1059,1063,1067,1072,1077,1081,1086,1091,1096],{"type":413,"tag":448,"props":1055,"children":1056},{"style":1029},[1057],{"type":418,"value":1058},"gh repo create ",{"type":413,"tag":448,"props":1060,"children":1061},{"style":461},[1062],{"type":418,"value":1026},{"type":413,"tag":448,"props":1064,"children":1065},{"style":1029},[1066],{"type":418,"value":1032},{"type":413,"tag":448,"props":1068,"children":1069},{"style":461},[1070],{"type":418,"value":1071},"--",{"type":413,"tag":448,"props":1073,"children":1074},{"style":1029},[1075],{"type":418,"value":1076},"private ",{"type":413,"tag":448,"props":1078,"children":1079},{"style":461},[1080],{"type":418,"value":1071},{"type":413,"tag":448,"props":1082,"children":1083},{"style":1029},[1084],{"type":418,"value":1085},"source",{"type":413,"tag":448,"props":1087,"children":1088},{"style":461},[1089],{"type":418,"value":1090},"=.",{"type":413,"tag":448,"props":1092,"children":1093},{"style":461},[1094],{"type":418,"value":1095}," --",{"type":413,"tag":448,"props":1097,"children":1098},{"style":1029},[1099],{"type":418,"value":1100},"push\n",{"type":413,"tag":841,"props":1102,"children":1104},{"icon":1103},"i-heroicons-light-bulb",[1105],{"type":413,"tag":414,"props":1106,"children":1107},{},[1108,1110,1116,1118,1124],{"type":418,"value":1109},"You can use the ",{"type":413,"tag":444,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":418,"value":1115},"--public",{"type":418,"value":1117}," flag instead of the ",{"type":413,"tag":444,"props":1119,"children":1121},{"className":1120},[],[1122],{"type":418,"value":1123},"--private",{"type":418,"value":1125}," one if you want your GitHub repository to be public.",{"type":413,"tag":414,"props":1127,"children":1128},{},[1129],{"type":418,"value":1130},"The repository's full name (containing the organization name) can be retrieved like this:",{"type":413,"tag":437,"props":1132,"children":1134},{"className":1013,"code":1133,"language":248,"meta":401,"style":401},"$repositoryFullName=$(gh repo view --json nameWithOwner -q \".nameWithOwner\")\n",[1135],{"type":413,"tag":444,"props":1136,"children":1137},{"__ignoreMap":401},[1138],{"type":413,"tag":448,"props":1139,"children":1140},{"class":450,"line":451},[1141,1145,1150,1155,1160,1164,1169,1174,1179,1184,1189,1193],{"type":413,"tag":448,"props":1142,"children":1143},{"style":461},[1144],{"type":418,"value":1026},{"type":413,"tag":448,"props":1146,"children":1147},{"style":1029},[1148],{"type":418,"value":1149},"repositoryFullName",{"type":413,"tag":448,"props":1151,"children":1152},{"style":461},[1153],{"type":418,"value":1154},"=$(",{"type":413,"tag":448,"props":1156,"children":1157},{"style":1029},[1158],{"type":418,"value":1159},"gh repo view ",{"type":413,"tag":448,"props":1161,"children":1162},{"style":461},[1163],{"type":418,"value":1071},{"type":413,"tag":448,"props":1165,"children":1166},{"style":1029},[1167],{"type":418,"value":1168},"json nameWithOwner ",{"type":413,"tag":448,"props":1170,"children":1171},{"style":461},[1172],{"type":418,"value":1173},"-",{"type":413,"tag":448,"props":1175,"children":1176},{"style":1029},[1177],{"type":418,"value":1178},"q ",{"type":413,"tag":448,"props":1180,"children":1181},{"style":461},[1182],{"type":418,"value":1183},"\"",{"type":413,"tag":448,"props":1185,"children":1186},{"style":467},[1187],{"type":418,"value":1188},".nameWithOwner",{"type":413,"tag":448,"props":1190,"children":1191},{"style":461},[1192],{"type":418,"value":1183},{"type":413,"tag":448,"props":1194,"children":1195},{"style":461},[1196],{"type":418,"value":1197},")\n",{"type":413,"tag":841,"props":1199,"children":1200},{"icon":1103},[1201],{"type":413,"tag":414,"props":1202,"children":1203},{},[1204,1206,1212,1214,1220,1222],{"type":418,"value":1205},"Passing the ",{"type":413,"tag":444,"props":1207,"children":1209},{"className":1208},[],[1210],{"type":418,"value":1211},"--json",{"type":418,"value":1213}," flag converts the output format to JSON which, combined with the ",{"type":413,"tag":444,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":418,"value":1219},"--q",{"type":418,"value":1221}," flag can be handy for filtering or formatting a command output. More on that ",{"type":413,"tag":813,"props":1223,"children":1226},{"href":1224,"rel":1225},"https://cli.github.com/manual/gh_help_formatting",[817],[1227],{"type":418,"value":1228},"in the documentation",{"type":413,"tag":866,"props":1230,"children":1232},{"id":1231},"create-the-microsoft-entra-id-resources",[1233],{"type":418,"value":1234},"Create the Microsoft Entra ID resources",{"type":413,"tag":414,"props":1236,"children":1237},{},[1238],{"type":418,"value":1239},"Later, we will need the subscription and the tenant identifiers. Let's retrieve them now and take this opportunity to check that we are logged in on the correct tenant with the correct subscription selected.",{"type":413,"tag":437,"props":1241,"children":1243},{"className":1013,"code":1242,"language":248,"meta":401,"style":401},"$subscriptionId=$(az account show --query \"id\" -o tsv)\n$tenantId=$(az account show --query \"tenantId\" -o tsv)\n",[1244],{"type":413,"tag":444,"props":1245,"children":1246},{"__ignoreMap":401},[1247,1304],{"type":413,"tag":448,"props":1248,"children":1249},{"class":450,"line":451},[1250,1254,1259,1263,1268,1272,1277,1281,1286,1290,1295,1300],{"type":413,"tag":448,"props":1251,"children":1252},{"style":461},[1253],{"type":418,"value":1026},{"type":413,"tag":448,"props":1255,"children":1256},{"style":1029},[1257],{"type":418,"value":1258},"subscriptionId",{"type":413,"tag":448,"props":1260,"children":1261},{"style":461},[1262],{"type":418,"value":1154},{"type":413,"tag":448,"props":1264,"children":1265},{"style":1029},[1266],{"type":418,"value":1267},"az account show ",{"type":413,"tag":448,"props":1269,"children":1270},{"style":461},[1271],{"type":418,"value":1071},{"type":413,"tag":448,"props":1273,"children":1274},{"style":1029},[1275],{"type":418,"value":1276},"query ",{"type":413,"tag":448,"props":1278,"children":1279},{"style":461},[1280],{"type":418,"value":1183},{"type":413,"tag":448,"props":1282,"children":1283},{"style":467},[1284],{"type":418,"value":1285},"id",{"type":413,"tag":448,"props":1287,"children":1288},{"style":461},[1289],{"type":418,"value":1183},{"type":413,"tag":448,"props":1291,"children":1292},{"style":461},[1293],{"type":418,"value":1294}," -",{"type":413,"tag":448,"props":1296,"children":1297},{"style":1029},[1298],{"type":418,"value":1299},"o tsv",{"type":413,"tag":448,"props":1301,"children":1302},{"style":461},[1303],{"type":418,"value":1197},{"type":413,"tag":448,"props":1305,"children":1306},{"class":450,"line":473},[1307,1311,1316,1320,1324,1328,1332,1336,1340,1344,1348,1352],{"type":413,"tag":448,"props":1308,"children":1309},{"style":461},[1310],{"type":418,"value":1026},{"type":413,"tag":448,"props":1312,"children":1313},{"style":1029},[1314],{"type":418,"value":1315},"tenantId",{"type":413,"tag":448,"props":1317,"children":1318},{"style":461},[1319],{"type":418,"value":1154},{"type":413,"tag":448,"props":1321,"children":1322},{"style":1029},[1323],{"type":418,"value":1267},{"type":413,"tag":448,"props":1325,"children":1326},{"style":461},[1327],{"type":418,"value":1071},{"type":413,"tag":448,"props":1329,"children":1330},{"style":1029},[1331],{"type":418,"value":1276},{"type":413,"tag":448,"props":1333,"children":1334},{"style":461},[1335],{"type":418,"value":1183},{"type":413,"tag":448,"props":1337,"children":1338},{"style":467},[1339],{"type":418,"value":1315},{"type":413,"tag":448,"props":1341,"children":1342},{"style":461},[1343],{"type":418,"value":1183},{"type":413,"tag":448,"props":1345,"children":1346},{"style":461},[1347],{"type":418,"value":1294},{"type":413,"tag":448,"props":1349,"children":1350},{"style":1029},[1351],{"type":418,"value":1299},{"type":413,"tag":448,"props":1353,"children":1354},{"style":461},[1355],{"type":418,"value":1197},{"type":413,"tag":841,"props":1357,"children":1358},{"icon":843},[1359],{"type":413,"tag":414,"props":1360,"children":1361},{},[1362,1364,1370,1372,1378,1380,1387],{"type":418,"value":1363},"Similar to the GitHub CLI, the Azure CLI has a ",{"type":413,"tag":444,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":418,"value":1369},"--query",{"type":418,"value":1371}," flag to filter a command output. There are also different output formats. The ",{"type":413,"tag":444,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":418,"value":1377},"tsv",{"type":418,"value":1379}," (tab-separated values) one is useful for capturing a value in an environment variable. If you are not very familiar with the Azure CLI, you can check my article on the topic ",{"type":413,"tag":813,"props":1381,"children":1384},{"href":1382,"rel":1383},"https://www.techwatching.dev/posts/welcome-azure-cli",[817],[1385],{"type":418,"value":1386},"here",{"type":418,"value":898},{"type":413,"tag":414,"props":1389,"children":1390},{},[1391],{"type":418,"value":1392},"To create the app registration and its associated service principal, we can execute the following commands:",{"type":413,"tag":437,"props":1394,"children":1396},{"className":1013,"code":1395,"language":248,"meta":401,"style":401},"$appId=$(az ad app create --display-name \"GitHub Action OIDC for ${repositoryFullName}\" --query \"appId\" -o tsv)\n$servicePrincipalId=$(az ad sp create --id $appId --query \"id\" -o tsv)\n",[1397],{"type":413,"tag":444,"props":1398,"children":1399},{"__ignoreMap":401},[1400,1494],{"type":413,"tag":448,"props":1401,"children":1402},{"class":450,"line":451},[1403,1407,1412,1416,1421,1425,1430,1434,1439,1443,1448,1453,1457,1462,1466,1470,1474,1478,1482,1486,1490],{"type":413,"tag":448,"props":1404,"children":1405},{"style":461},[1406],{"type":418,"value":1026},{"type":413,"tag":448,"props":1408,"children":1409},{"style":1029},[1410],{"type":418,"value":1411},"appId",{"type":413,"tag":448,"props":1413,"children":1414},{"style":461},[1415],{"type":418,"value":1154},{"type":413,"tag":448,"props":1417,"children":1418},{"style":1029},[1419],{"type":418,"value":1420},"az ad app create ",{"type":413,"tag":448,"props":1422,"children":1423},{"style":461},[1424],{"type":418,"value":1071},{"type":413,"tag":448,"props":1426,"children":1427},{"style":1029},[1428],{"type":418,"value":1429},"display",{"type":413,"tag":448,"props":1431,"children":1432},{"style":461},[1433],{"type":418,"value":1173},{"type":413,"tag":448,"props":1435,"children":1436},{"style":1029},[1437],{"type":418,"value":1438},"name ",{"type":413,"tag":448,"props":1440,"children":1441},{"style":461},[1442],{"type":418,"value":1183},{"type":413,"tag":448,"props":1444,"children":1445},{"style":467},[1446],{"type":418,"value":1447},"GitHub Action OIDC for ",{"type":413,"tag":448,"props":1449,"children":1450},{"style":461},[1451],{"type":418,"value":1452},"${",{"type":413,"tag":448,"props":1454,"children":1455},{"style":1029},[1456],{"type":418,"value":1149},{"type":413,"tag":448,"props":1458,"children":1459},{"style":461},[1460],{"type":418,"value":1461},"}\"",{"type":413,"tag":448,"props":1463,"children":1464},{"style":461},[1465],{"type":418,"value":1095},{"type":413,"tag":448,"props":1467,"children":1468},{"style":1029},[1469],{"type":418,"value":1276},{"type":413,"tag":448,"props":1471,"children":1472},{"style":461},[1473],{"type":418,"value":1183},{"type":413,"tag":448,"props":1475,"children":1476},{"style":467},[1477],{"type":418,"value":1411},{"type":413,"tag":448,"props":1479,"children":1480},{"style":461},[1481],{"type":418,"value":1183},{"type":413,"tag":448,"props":1483,"children":1484},{"style":461},[1485],{"type":418,"value":1294},{"type":413,"tag":448,"props":1487,"children":1488},{"style":1029},[1489],{"type":418,"value":1299},{"type":413,"tag":448,"props":1491,"children":1492},{"style":461},[1493],{"type":418,"value":1197},{"type":413,"tag":448,"props":1495,"children":1496},{"class":450,"line":473},[1497,1501,1506,1510,1515,1519,1524,1528,1533,1537,1541,1545,1549,1553,1557,1561],{"type":413,"tag":448,"props":1498,"children":1499},{"style":461},[1500],{"type":418,"value":1026},{"type":413,"tag":448,"props":1502,"children":1503},{"style":1029},[1504],{"type":418,"value":1505},"servicePrincipalId",{"type":413,"tag":448,"props":1507,"children":1508},{"style":461},[1509],{"type":418,"value":1154},{"type":413,"tag":448,"props":1511,"children":1512},{"style":1029},[1513],{"type":418,"value":1514},"az ad sp create ",{"type":413,"tag":448,"props":1516,"children":1517},{"style":461},[1518],{"type":418,"value":1071},{"type":413,"tag":448,"props":1520,"children":1521},{"style":1029},[1522],{"type":418,"value":1523},"id ",{"type":413,"tag":448,"props":1525,"children":1526},{"style":461},[1527],{"type":418,"value":1026},{"type":413,"tag":448,"props":1529,"children":1530},{"style":1029},[1531],{"type":418,"value":1532},"appId ",{"type":413,"tag":448,"props":1534,"children":1535},{"style":461},[1536],{"type":418,"value":1071},{"type":413,"tag":448,"props":1538,"children":1539},{"style":1029},[1540],{"type":418,"value":1276},{"type":413,"tag":448,"props":1542,"children":1543},{"style":461},[1544],{"type":418,"value":1183},{"type":413,"tag":448,"props":1546,"children":1547},{"style":467},[1548],{"type":418,"value":1285},{"type":413,"tag":448,"props":1550,"children":1551},{"style":461},[1552],{"type":418,"value":1183},{"type":413,"tag":448,"props":1554,"children":1555},{"style":461},[1556],{"type":418,"value":1294},{"type":413,"tag":448,"props":1558,"children":1559},{"style":1029},[1560],{"type":418,"value":1299},{"type":413,"tag":448,"props":1562,"children":1563},{"style":461},[1564],{"type":418,"value":1197},{"type":413,"tag":414,"props":1566,"children":1567},{},[1568],{"type":418,"value":1569},"We can now assign the contributor role to the service principal on the subscription.",{"type":413,"tag":437,"props":1571,"children":1573},{"className":1013,"code":1572,"language":248,"meta":401,"style":401},"az role assignment create --role contributor --subscription $subscriptionId --assignee-object-id  $servicePrincipalId --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscriptionId\n",[1574],{"type":413,"tag":444,"props":1575,"children":1576},{"__ignoreMap":401},[1577],{"type":413,"tag":448,"props":1578,"children":1579},{"class":450,"line":451},[1580,1585,1589,1594,1598,1603,1607,1612,1616,1621,1625,1630,1634,1639,1643,1648,1652,1656,1660,1665,1669,1674,1678,1683,1688,1693,1698],{"type":413,"tag":448,"props":1581,"children":1582},{"style":1029},[1583],{"type":418,"value":1584},"az role assignment create ",{"type":413,"tag":448,"props":1586,"children":1587},{"style":461},[1588],{"type":418,"value":1071},{"type":413,"tag":448,"props":1590,"children":1591},{"style":1029},[1592],{"type":418,"value":1593},"role contributor ",{"type":413,"tag":448,"props":1595,"children":1596},{"style":461},[1597],{"type":418,"value":1071},{"type":413,"tag":448,"props":1599,"children":1600},{"style":1029},[1601],{"type":418,"value":1602},"subscription ",{"type":413,"tag":448,"props":1604,"children":1605},{"style":461},[1606],{"type":418,"value":1026},{"type":413,"tag":448,"props":1608,"children":1609},{"style":1029},[1610],{"type":418,"value":1611},"subscriptionId ",{"type":413,"tag":448,"props":1613,"children":1614},{"style":461},[1615],{"type":418,"value":1071},{"type":413,"tag":448,"props":1617,"children":1618},{"style":1029},[1619],{"type":418,"value":1620},"assignee",{"type":413,"tag":448,"props":1622,"children":1623},{"style":461},[1624],{"type":418,"value":1173},{"type":413,"tag":448,"props":1626,"children":1627},{"style":1029},[1628],{"type":418,"value":1629},"object",{"type":413,"tag":448,"props":1631,"children":1632},{"style":461},[1633],{"type":418,"value":1173},{"type":413,"tag":448,"props":1635,"children":1636},{"style":1029},[1637],{"type":418,"value":1638},"id  ",{"type":413,"tag":448,"props":1640,"children":1641},{"style":461},[1642],{"type":418,"value":1026},{"type":413,"tag":448,"props":1644,"children":1645},{"style":1029},[1646],{"type":418,"value":1647},"servicePrincipalId ",{"type":413,"tag":448,"props":1649,"children":1650},{"style":461},[1651],{"type":418,"value":1071},{"type":413,"tag":448,"props":1653,"children":1654},{"style":1029},[1655],{"type":418,"value":1620},{"type":413,"tag":448,"props":1657,"children":1658},{"style":461},[1659],{"type":418,"value":1173},{"type":413,"tag":448,"props":1661,"children":1662},{"style":1029},[1663],{"type":418,"value":1664},"principal",{"type":413,"tag":448,"props":1666,"children":1667},{"style":461},[1668],{"type":418,"value":1173},{"type":413,"tag":448,"props":1670,"children":1671},{"style":1029},[1672],{"type":418,"value":1673},"type ServicePrincipal ",{"type":413,"tag":448,"props":1675,"children":1676},{"style":461},[1677],{"type":418,"value":1071},{"type":413,"tag":448,"props":1679,"children":1680},{"style":1029},[1681],{"type":418,"value":1682},"scope ",{"type":413,"tag":448,"props":1684,"children":1685},{"style":461},[1686],{"type":418,"value":1687},"/",{"type":413,"tag":448,"props":1689,"children":1690},{"style":1029},[1691],{"type":418,"value":1692},"subscriptions",{"type":413,"tag":448,"props":1694,"children":1695},{"style":461},[1696],{"type":418,"value":1697},"/$",{"type":413,"tag":448,"props":1699,"children":1700},{"style":1029},[1701],{"type":418,"value":1702},"subscriptionId\n",{"type":413,"tag":414,"props":1704,"children":1705},{},[1706],{"type":418,"value":1707},"Creating federated credentials is a bit more complex as one of the arguments needs to be an in-line JSON string.",{"type":413,"tag":437,"props":1709,"children":1711},{"className":1013,"code":1710,"language":248,"meta":401,"style":401},"$parametersJson = @{\n    name = \"FederatedIdentityForWorkshop\"\n    issuer = \"https://token.actions.githubusercontent.com\"\n    subject = \"repo:${repositoryFullName}:ref:refs/heads/main\"\n    description = \"Deployments for ${repositoryFullName}\"\n    audiences = @(\n        \"api://AzureADTokenExchange\"\n    )\n}\n",[1712],{"type":413,"tag":444,"props":1713,"children":1714},{"__ignoreMap":401},[1715,1742,1767,1792,1835,1869,1890,1907,1915],{"type":413,"tag":448,"props":1716,"children":1717},{"class":450,"line":451},[1718,1722,1727,1731,1737],{"type":413,"tag":448,"props":1719,"children":1720},{"style":461},[1721],{"type":418,"value":1026},{"type":413,"tag":448,"props":1723,"children":1724},{"style":1029},[1725],{"type":418,"value":1726},"parametersJson ",{"type":413,"tag":448,"props":1728,"children":1729},{"style":461},[1730],{"type":418,"value":1037},{"type":413,"tag":448,"props":1732,"children":1734},{"style":1733},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1735],{"type":418,"value":1736}," @",{"type":413,"tag":448,"props":1738,"children":1739},{"style":461},[1740],{"type":418,"value":1741},"{\n",{"type":413,"tag":448,"props":1743,"children":1744},{"class":450,"line":473},[1745,1750,1754,1758,1763],{"type":413,"tag":448,"props":1746,"children":1747},{"style":1029},[1748],{"type":418,"value":1749},"    name ",{"type":413,"tag":448,"props":1751,"children":1752},{"style":461},[1753],{"type":418,"value":1037},{"type":413,"tag":448,"props":1755,"children":1756},{"style":461},[1757],{"type":418,"value":995},{"type":413,"tag":448,"props":1759,"children":1760},{"style":467},[1761],{"type":418,"value":1762},"FederatedIdentityForWorkshop",{"type":413,"tag":448,"props":1764,"children":1765},{"style":461},[1766],{"type":418,"value":1005},{"type":413,"tag":448,"props":1768,"children":1769},{"class":450,"line":488},[1770,1775,1779,1783,1788],{"type":413,"tag":448,"props":1771,"children":1772},{"style":1029},[1773],{"type":418,"value":1774},"    issuer ",{"type":413,"tag":448,"props":1776,"children":1777},{"style":461},[1778],{"type":418,"value":1037},{"type":413,"tag":448,"props":1780,"children":1781},{"style":461},[1782],{"type":418,"value":995},{"type":413,"tag":448,"props":1784,"children":1785},{"style":467},[1786],{"type":418,"value":1787},"https://token.actions.githubusercontent.com",{"type":413,"tag":448,"props":1789,"children":1790},{"style":461},[1791],{"type":418,"value":1005},{"type":413,"tag":448,"props":1793,"children":1794},{"class":450,"line":501},[1795,1800,1804,1808,1813,1817,1821,1826,1831],{"type":413,"tag":448,"props":1796,"children":1797},{"style":1029},[1798],{"type":418,"value":1799},"    subject ",{"type":413,"tag":448,"props":1801,"children":1802},{"style":461},[1803],{"type":418,"value":1037},{"type":413,"tag":448,"props":1805,"children":1806},{"style":461},[1807],{"type":418,"value":995},{"type":413,"tag":448,"props":1809,"children":1810},{"style":467},[1811],{"type":418,"value":1812},"repo:",{"type":413,"tag":448,"props":1814,"children":1815},{"style":461},[1816],{"type":418,"value":1452},{"type":413,"tag":448,"props":1818,"children":1819},{"style":1029},[1820],{"type":418,"value":1149},{"type":413,"tag":448,"props":1822,"children":1823},{"style":461},[1824],{"type":418,"value":1825},"}",{"type":413,"tag":448,"props":1827,"children":1828},{"style":467},[1829],{"type":418,"value":1830},":ref:refs/heads/main",{"type":413,"tag":448,"props":1832,"children":1833},{"style":461},[1834],{"type":418,"value":1005},{"type":413,"tag":448,"props":1836,"children":1837},{"class":450,"line":511},[1838,1843,1847,1851,1856,1860,1864],{"type":413,"tag":448,"props":1839,"children":1840},{"style":1029},[1841],{"type":418,"value":1842},"    description ",{"type":413,"tag":448,"props":1844,"children":1845},{"style":461},[1846],{"type":418,"value":1037},{"type":413,"tag":448,"props":1848,"children":1849},{"style":461},[1850],{"type":418,"value":995},{"type":413,"tag":448,"props":1852,"children":1853},{"style":467},[1854],{"type":418,"value":1855},"Deployments for ",{"type":413,"tag":448,"props":1857,"children":1858},{"style":461},[1859],{"type":418,"value":1452},{"type":413,"tag":448,"props":1861,"children":1862},{"style":1029},[1863],{"type":418,"value":1149},{"type":413,"tag":448,"props":1865,"children":1866},{"style":461},[1867],{"type":418,"value":1868},"}\"\n",{"type":413,"tag":448,"props":1870,"children":1871},{"class":450,"line":524},[1872,1877,1881,1885],{"type":413,"tag":448,"props":1873,"children":1874},{"style":1029},[1875],{"type":418,"value":1876},"    audiences ",{"type":413,"tag":448,"props":1878,"children":1879},{"style":461},[1880],{"type":418,"value":1037},{"type":413,"tag":448,"props":1882,"children":1883},{"style":1733},[1884],{"type":418,"value":1736},{"type":413,"tag":448,"props":1886,"children":1887},{"style":461},[1888],{"type":418,"value":1889},"(\n",{"type":413,"tag":448,"props":1891,"children":1892},{"class":450,"line":542},[1893,1898,1903],{"type":413,"tag":448,"props":1894,"children":1895},{"style":461},[1896],{"type":418,"value":1897},"        \"",{"type":413,"tag":448,"props":1899,"children":1900},{"style":467},[1901],{"type":418,"value":1902},"api://AzureADTokenExchange",{"type":413,"tag":448,"props":1904,"children":1905},{"style":461},[1906],{"type":418,"value":1005},{"type":413,"tag":448,"props":1908,"children":1909},{"class":450,"line":560},[1910],{"type":413,"tag":448,"props":1911,"children":1912},{"style":461},[1913],{"type":418,"value":1914},"    )\n",{"type":413,"tag":448,"props":1916,"children":1917},{"class":450,"line":573},[1918],{"type":413,"tag":448,"props":1919,"children":1920},{"style":461},[1921],{"type":418,"value":1922},"}\n",{"type":413,"tag":841,"props":1924,"children":1925},{"icon":1103},[1926],{"type":413,"tag":414,"props":1927,"children":1928},{},[1929,1931,1937,1939,1946],{"type":418,"value":1930},"The ",{"type":413,"tag":444,"props":1932,"children":1934},{"className":1933},[],[1935],{"type":418,"value":1936},"subject",{"type":418,"value":1938}," property here specifies that the GitHub Actions workflow from the created repository is only authorized to authenticate to Azure when it runs on the main branch. Of course, there are other possible configurations, such as those involving pull requests or environments. Consult the ",{"type":413,"tag":813,"props":1940,"children":1943},{"href":1941,"rel":1942},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims",[817],[1944],{"type":418,"value":1945},"documentation",{"type":418,"value":1947}," to learn more about these options.",{"type":413,"tag":414,"props":1949,"children":1950},{},[1951,1953,1960],{"type":418,"value":1952},"To make this JSON string an inline string with escaped quotes that works for the Azure CLI, we have to transform the string using a command I found in this ",{"type":413,"tag":813,"props":1954,"children":1957},{"href":1955,"rel":1956},"https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b",[817],[1958],{"type":418,"value":1959},"blog article",{"type":418,"value":898},{"type":413,"tag":437,"props":1962,"children":1964},{"className":1013,"code":1963,"language":248,"meta":401,"style":401},"$parameters = $($parametersJson | ConvertTo-Json -Depth 100 -Compress).Replace(\"`\"\", \"\\`\"\")\n",[1965],{"type":413,"tag":444,"props":1966,"children":1967},{"__ignoreMap":401},[1968],{"type":413,"tag":448,"props":1969,"children":1970},{"class":450,"line":451},[1971,1975,1980,1984,1989,1993,1998,2004,2008,2013,2018,2022,2027,2032,2037,2042,2046,2051,2055,2060,2064,2069,2073,2077],{"type":413,"tag":448,"props":1972,"children":1973},{"style":461},[1974],{"type":418,"value":1026},{"type":413,"tag":448,"props":1976,"children":1977},{"style":1029},[1978],{"type":418,"value":1979},"parameters ",{"type":413,"tag":448,"props":1981,"children":1982},{"style":461},[1983],{"type":418,"value":1037},{"type":413,"tag":448,"props":1985,"children":1986},{"style":461},[1987],{"type":418,"value":1988}," $($",{"type":413,"tag":448,"props":1990,"children":1991},{"style":1029},[1992],{"type":418,"value":1726},{"type":413,"tag":448,"props":1994,"children":1995},{"style":461},[1996],{"type":418,"value":1997},"|",{"type":413,"tag":448,"props":1999,"children":2001},{"style":2000},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[2002],{"type":418,"value":2003}," ConvertTo-Json",{"type":413,"tag":448,"props":2005,"children":2006},{"style":461},[2007],{"type":418,"value":1294},{"type":413,"tag":448,"props":2009,"children":2010},{"style":1029},[2011],{"type":418,"value":2012},"Depth ",{"type":413,"tag":448,"props":2014,"children":2015},{"style":1733},[2016],{"type":418,"value":2017},"100",{"type":413,"tag":448,"props":2019,"children":2020},{"style":461},[2021],{"type":418,"value":1294},{"type":413,"tag":448,"props":2023,"children":2024},{"style":1029},[2025],{"type":418,"value":2026},"Compress",{"type":413,"tag":448,"props":2028,"children":2029},{"style":461},[2030],{"type":418,"value":2031},")",{"type":413,"tag":448,"props":2033,"children":2034},{"style":1029},[2035],{"type":418,"value":2036},".Replace",{"type":413,"tag":448,"props":2038,"children":2039},{"style":461},[2040],{"type":418,"value":2041},"(",{"type":413,"tag":448,"props":2043,"children":2044},{"style":461},[2045],{"type":418,"value":1183},{"type":413,"tag":448,"props":2047,"children":2048},{"style":1029},[2049],{"type":418,"value":2050},"`\"",{"type":413,"tag":448,"props":2052,"children":2053},{"style":461},[2054],{"type":418,"value":1183},{"type":413,"tag":448,"props":2056,"children":2057},{"style":461},[2058],{"type":418,"value":2059},",",{"type":413,"tag":448,"props":2061,"children":2062},{"style":461},[2063],{"type":418,"value":995},{"type":413,"tag":448,"props":2065,"children":2066},{"style":467},[2067],{"type":418,"value":2068},"\\",{"type":413,"tag":448,"props":2070,"children":2071},{"style":1029},[2072],{"type":418,"value":2050},{"type":413,"tag":448,"props":2074,"children":2075},{"style":461},[2076],{"type":418,"value":1183},{"type":413,"tag":448,"props":2078,"children":2079},{"style":461},[2080],{"type":418,"value":1197},{"type":413,"tag":414,"props":2082,"children":2083},{},[2084],{"type":418,"value":2085},"And finally, we can create the federated credentials.",{"type":413,"tag":437,"props":2087,"children":2089},{"className":1013,"code":2088,"language":248,"meta":401,"style":401},"az ad app federated-credential create --id $appId --parameters $parameters\n",[2090],{"type":413,"tag":444,"props":2091,"children":2092},{"__ignoreMap":401},[2093],{"type":413,"tag":448,"props":2094,"children":2095},{"class":450,"line":451},[2096,2101,2105,2110,2114,2118,2122,2126,2130,2134,2138],{"type":413,"tag":448,"props":2097,"children":2098},{"style":1029},[2099],{"type":418,"value":2100},"az ad app federated",{"type":413,"tag":448,"props":2102,"children":2103},{"style":461},[2104],{"type":418,"value":1173},{"type":413,"tag":448,"props":2106,"children":2107},{"style":1029},[2108],{"type":418,"value":2109},"credential create ",{"type":413,"tag":448,"props":2111,"children":2112},{"style":461},[2113],{"type":418,"value":1071},{"type":413,"tag":448,"props":2115,"children":2116},{"style":1029},[2117],{"type":418,"value":1523},{"type":413,"tag":448,"props":2119,"children":2120},{"style":461},[2121],{"type":418,"value":1026},{"type":413,"tag":448,"props":2123,"children":2124},{"style":1029},[2125],{"type":418,"value":1532},{"type":413,"tag":448,"props":2127,"children":2128},{"style":461},[2129],{"type":418,"value":1071},{"type":413,"tag":448,"props":2131,"children":2132},{"style":1029},[2133],{"type":418,"value":1979},{"type":413,"tag":448,"props":2135,"children":2136},{"style":461},[2137],{"type":418,"value":1026},{"type":413,"tag":448,"props":2139,"children":2140},{"style":1029},[2141],{"type":418,"value":2142},"parameters\n",{"type":413,"tag":866,"props":2144,"children":2146},{"id":2145},"configure-the-github-actions-and-run-the-workflow",[2147],{"type":418,"value":2148},"Configure the GitHub Actions and run the workflow",{"type":413,"tag":414,"props":2150,"children":2151},{},[2152],{"type":418,"value":2153},"For the OIDC authentication to function properly, we need to set 3 GitHub Actions Secrets (could also be GitHub Actions variables as there are not really secrets):",{"type":413,"tag":2155,"props":2156,"children":2157},"ol",{},[2158,2164,2169],{"type":413,"tag":2159,"props":2160,"children":2161},"li",{},[2162],{"type":418,"value":2163},"The identifier of the Azure tenant",{"type":413,"tag":2159,"props":2165,"children":2166},{},[2167],{"type":418,"value":2168},"The identifier of the Azure subscription",{"type":413,"tag":2159,"props":2170,"children":2171},{},[2172],{"type":418,"value":2173},"The application identifier of the app registration",{"type":413,"tag":437,"props":2175,"children":2177},{"className":1013,"code":2176,"language":248,"meta":401,"style":401},"gh secret set AZURE_TENANT_ID --body $tenantId\ngh secret set AZURE_SUBSCRIPTION_ID --body $subscriptionId\ngh secret set AZURE_CLIENT_ID --body $appId\n",[2178],{"type":413,"tag":444,"props":2179,"children":2180},{"__ignoreMap":401},[2181,2207,2231],{"type":413,"tag":448,"props":2182,"children":2183},{"class":450,"line":451},[2184,2189,2193,2198,2202],{"type":413,"tag":448,"props":2185,"children":2186},{"style":1029},[2187],{"type":418,"value":2188},"gh secret set AZURE_TENANT_ID ",{"type":413,"tag":448,"props":2190,"children":2191},{"style":461},[2192],{"type":418,"value":1071},{"type":413,"tag":448,"props":2194,"children":2195},{"style":1029},[2196],{"type":418,"value":2197},"body ",{"type":413,"tag":448,"props":2199,"children":2200},{"style":461},[2201],{"type":418,"value":1026},{"type":413,"tag":448,"props":2203,"children":2204},{"style":1029},[2205],{"type":418,"value":2206},"tenantId\n",{"type":413,"tag":448,"props":2208,"children":2209},{"class":450,"line":473},[2210,2215,2219,2223,2227],{"type":413,"tag":448,"props":2211,"children":2212},{"style":1029},[2213],{"type":418,"value":2214},"gh secret set AZURE_SUBSCRIPTION_ID ",{"type":413,"tag":448,"props":2216,"children":2217},{"style":461},[2218],{"type":418,"value":1071},{"type":413,"tag":448,"props":2220,"children":2221},{"style":1029},[2222],{"type":418,"value":2197},{"type":413,"tag":448,"props":2224,"children":2225},{"style":461},[2226],{"type":418,"value":1026},{"type":413,"tag":448,"props":2228,"children":2229},{"style":1029},[2230],{"type":418,"value":1702},{"type":413,"tag":448,"props":2232,"children":2233},{"class":450,"line":488},[2234,2239,2243,2247,2251],{"type":413,"tag":448,"props":2235,"children":2236},{"style":1029},[2237],{"type":418,"value":2238},"gh secret set AZURE_CLIENT_ID ",{"type":413,"tag":448,"props":2240,"children":2241},{"style":461},[2242],{"type":418,"value":1071},{"type":413,"tag":448,"props":2244,"children":2245},{"style":1029},[2246],{"type":418,"value":2197},{"type":413,"tag":448,"props":2248,"children":2249},{"style":461},[2250],{"type":418,"value":1026},{"type":413,"tag":448,"props":2252,"children":2253},{"style":1029},[2254],{"type":418,"value":2255},"appId\n",{"type":413,"tag":414,"props":2257,"children":2258},{},[2259],{"type":418,"value":2260},"We can directly run the workflow from the GitHub CLI, and watch the run until it is completed.",{"type":413,"tag":437,"props":2262,"children":2264},{"className":1013,"code":2263,"language":248,"meta":401,"style":401},"gh workflow run main.yml\n$runId=$(gh run list --workflow=main.yml --json databaseId -q \".[0].databaseId\")\ngh run watch $runId\n",[2265],{"type":413,"tag":444,"props":2266,"children":2267},{"__ignoreMap":401},[2268,2276,2349],{"type":413,"tag":448,"props":2269,"children":2270},{"class":450,"line":451},[2271],{"type":413,"tag":448,"props":2272,"children":2273},{"style":1029},[2274],{"type":418,"value":2275},"gh workflow run main.yml\n",{"type":413,"tag":448,"props":2277,"children":2278},{"class":450,"line":473},[2279,2283,2288,2292,2297,2301,2306,2310,2315,2319,2324,2328,2332,2336,2341,2345],{"type":413,"tag":448,"props":2280,"children":2281},{"style":461},[2282],{"type":418,"value":1026},{"type":413,"tag":448,"props":2284,"children":2285},{"style":1029},[2286],{"type":418,"value":2287},"runId",{"type":413,"tag":448,"props":2289,"children":2290},{"style":461},[2291],{"type":418,"value":1154},{"type":413,"tag":448,"props":2293,"children":2294},{"style":1029},[2295],{"type":418,"value":2296},"gh run list ",{"type":413,"tag":448,"props":2298,"children":2299},{"style":461},[2300],{"type":418,"value":1071},{"type":413,"tag":448,"props":2302,"children":2303},{"style":1029},[2304],{"type":418,"value":2305},"workflow",{"type":413,"tag":448,"props":2307,"children":2308},{"style":461},[2309],{"type":418,"value":1037},{"type":413,"tag":448,"props":2311,"children":2312},{"style":1029},[2313],{"type":418,"value":2314},"main.yml ",{"type":413,"tag":448,"props":2316,"children":2317},{"style":461},[2318],{"type":418,"value":1071},{"type":413,"tag":448,"props":2320,"children":2321},{"style":1029},[2322],{"type":418,"value":2323},"json databaseId ",{"type":413,"tag":448,"props":2325,"children":2326},{"style":461},[2327],{"type":418,"value":1173},{"type":413,"tag":448,"props":2329,"children":2330},{"style":1029},[2331],{"type":418,"value":1178},{"type":413,"tag":448,"props":2333,"children":2334},{"style":461},[2335],{"type":418,"value":1183},{"type":413,"tag":448,"props":2337,"children":2338},{"style":467},[2339],{"type":418,"value":2340},".[0].databaseId",{"type":413,"tag":448,"props":2342,"children":2343},{"style":461},[2344],{"type":418,"value":1183},{"type":413,"tag":448,"props":2346,"children":2347},{"style":461},[2348],{"type":418,"value":1197},{"type":413,"tag":448,"props":2350,"children":2351},{"class":450,"line":488},[2352,2357,2361],{"type":413,"tag":448,"props":2353,"children":2354},{"style":1029},[2355],{"type":418,"value":2356},"gh run watch ",{"type":413,"tag":448,"props":2358,"children":2359},{"style":461},[2360],{"type":418,"value":1026},{"type":413,"tag":448,"props":2362,"children":2363},{"style":1029},[2364],{"type":418,"value":2365},"runId\n",{"type":413,"tag":414,"props":2367,"children":2368},{},[2369],{"type":413,"tag":832,"props":2370,"children":2374},{"alt":2371,"className":2372,"src":2373},"Screenshot of the GitHub Actions workfow run",[836,837],"/posts/images/scripting_azurereadygithub_github_1.webp",[],{"type":413,"tag":420,"props":2376,"children":2378},{"id":2377},"full-script",[2379],{"type":418,"value":2380},"Full script",{"type":413,"tag":437,"props":2382,"children":2384},{"className":1013,"code":2383,"language":248,"meta":401,"style":401},"# Initialize git repository with current code\n# You should have added the main.yml workflow file in the `.github\\workflows` directory \ngit init\ngit add .\ngit commit -m \"Intialize repository with the GitHub Actions workflow file\"\n\n# Create a new remote private GitHub repository\n$repositoryName = \"MyAzureReadyRepository\"\ngh repo create $repositoryName --private --source=. --push\n\n# Retrieve the repository full name (org/repo)\n$repositoryFullName=$(gh repo view --json nameWithOwner -q \".nameWithOwner\") \n\n# Retrieve the current subscription and current tenant identifiers \n$subscriptionId=$(az account show --query \"id\" -o tsv)\n$tenantId=$(az account show --query \"tenantId\" -o tsv)\n\n# Create an App Registration and its associated service principal\n$appId=$(az ad app create --display-name \"GitHub Action OIDC for ${repositoryFullName}\" --query \"appId\" -o tsv)\n$servicePrincipalId=$(az ad sp create --id $appId --query \"id\" -o tsv)\n\n# Assign the contributor role to the service principal on the subscription\naz role assignment create --role contributor --subscription $subscriptionId --assignee-object-id  $servicePrincipalId --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscriptionId\n\n# Prepare parameters for federated credentials\n$parametersJson = @{\n    name = \"FederatedIdentityForWorkshop\"\n    issuer = \"https://token.actions.githubusercontent.com\"\n    subject = \"repo:${repositoryFullName}:ref:refs/heads/main\"\n    description = \"Deployments for ${repositoryFullName}\"\n    audiences = @(\n        \"api://AzureADTokenExchange\"\n    )\n}\n\n# Change parameters to single line string with escaped quotes to make it work with Azure CLI\n# https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b\n$parameters = $($parametersJson | ConvertTo-Json -Depth 100 -Compress).Replace(\"`\"\", \"\\`\"\")\n\n# Create federated credentials\naz ad app federated-credential create --id $appId --parameters $parameters\n\n# Create GitHub secrets needed for the GitHub Actions\ngh secret set AZURE_TENANT_ID --body $tenantId\ngh secret set AZURE_SUBSCRIPTION_ID --body $subscriptionId\ngh secret set AZURE_CLIENT_ID --body $appId\n\n# Run workflow\ngh workflow run main.yml\n$runId=$(gh run list --workflow=main.yml --json databaseId -q \".[0].databaseId\")\ngh run watch $runId\n\n# Open the repostory in the browser\ngh repo view -w\n",[2385],{"type":413,"tag":444,"props":2386,"children":2387},{"__ignoreMap":401},[2388,2397,2405,2413,2421,2450,2457,2465,2492,2535,2542,2550,2606,2613,2621,2672,2723,2730,2738,2825,2892,2899,2907,3019,3027,3036,3060,3084,3108,3148,3180,3200,3216,3224,3232,3240,3249,3258,3358,3366,3375,3423,3431,3440,3464,3488,3512,3520,3529,3537,3605,3621,3629,3638],{"type":413,"tag":448,"props":2389,"children":2390},{"class":450,"line":451},[2391],{"type":413,"tag":448,"props":2392,"children":2394},{"style":2393},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[2395],{"type":418,"value":2396},"# Initialize git repository with current code\n",{"type":413,"tag":448,"props":2398,"children":2399},{"class":450,"line":473},[2400],{"type":413,"tag":448,"props":2401,"children":2402},{"style":2393},[2403],{"type":418,"value":2404},"# You should have added the main.yml workflow file in the `.github\\workflows` directory \n",{"type":413,"tag":448,"props":2406,"children":2407},{"class":450,"line":488},[2408],{"type":413,"tag":448,"props":2409,"children":2410},{"style":1029},[2411],{"type":418,"value":2412},"git init\n",{"type":413,"tag":448,"props":2414,"children":2415},{"class":450,"line":501},[2416],{"type":413,"tag":448,"props":2417,"children":2418},{"style":1029},[2419],{"type":418,"value":2420},"git add .\n",{"type":413,"tag":448,"props":2422,"children":2423},{"class":450,"line":511},[2424,2429,2433,2438,2442,2446],{"type":413,"tag":448,"props":2425,"children":2426},{"style":1029},[2427],{"type":418,"value":2428},"git commit ",{"type":413,"tag":448,"props":2430,"children":2431},{"style":461},[2432],{"type":418,"value":1173},{"type":413,"tag":448,"props":2434,"children":2435},{"style":1029},[2436],{"type":418,"value":2437},"m ",{"type":413,"tag":448,"props":2439,"children":2440},{"style":461},[2441],{"type":418,"value":1183},{"type":413,"tag":448,"props":2443,"children":2444},{"style":467},[2445],{"type":418,"value":1000},{"type":413,"tag":448,"props":2447,"children":2448},{"style":461},[2449],{"type":418,"value":1005},{"type":413,"tag":448,"props":2451,"children":2452},{"class":450,"line":524},[2453],{"type":413,"tag":448,"props":2454,"children":2455},{"emptyLinePlaceholder":505},[2456],{"type":418,"value":508},{"type":413,"tag":448,"props":2458,"children":2459},{"class":450,"line":542},[2460],{"type":413,"tag":448,"props":2461,"children":2462},{"style":2393},[2463],{"type":418,"value":2464},"# Create a new remote private GitHub repository\n",{"type":413,"tag":448,"props":2466,"children":2467},{"class":450,"line":560},[2468,2472,2476,2480,2484,2488],{"type":413,"tag":448,"props":2469,"children":2470},{"style":461},[2471],{"type":418,"value":1026},{"type":413,"tag":448,"props":2473,"children":2474},{"style":1029},[2475],{"type":418,"value":1032},{"type":413,"tag":448,"props":2477,"children":2478},{"style":461},[2479],{"type":418,"value":1037},{"type":413,"tag":448,"props":2481,"children":2482},{"style":461},[2483],{"type":418,"value":995},{"type":413,"tag":448,"props":2485,"children":2486},{"style":467},[2487],{"type":418,"value":1046},{"type":413,"tag":448,"props":2489,"children":2490},{"style":461},[2491],{"type":418,"value":1005},{"type":413,"tag":448,"props":2493,"children":2494},{"class":450,"line":573},[2495,2499,2503,2507,2511,2515,2519,2523,2527,2531],{"type":413,"tag":448,"props":2496,"children":2497},{"style":1029},[2498],{"type":418,"value":1058},{"type":413,"tag":448,"props":2500,"children":2501},{"style":461},[2502],{"type":418,"value":1026},{"type":413,"tag":448,"props":2504,"children":2505},{"style":1029},[2506],{"type":418,"value":1032},{"type":413,"tag":448,"props":2508,"children":2509},{"style":461},[2510],{"type":418,"value":1071},{"type":413,"tag":448,"props":2512,"children":2513},{"style":1029},[2514],{"type":418,"value":1076},{"type":413,"tag":448,"props":2516,"children":2517},{"style":461},[2518],{"type":418,"value":1071},{"type":413,"tag":448,"props":2520,"children":2521},{"style":1029},[2522],{"type":418,"value":1085},{"type":413,"tag":448,"props":2524,"children":2525},{"style":461},[2526],{"type":418,"value":1090},{"type":413,"tag":448,"props":2528,"children":2529},{"style":461},[2530],{"type":418,"value":1095},{"type":413,"tag":448,"props":2532,"children":2533},{"style":1029},[2534],{"type":418,"value":1100},{"type":413,"tag":448,"props":2536,"children":2537},{"class":450,"line":586},[2538],{"type":413,"tag":448,"props":2539,"children":2540},{"emptyLinePlaceholder":505},[2541],{"type":418,"value":508},{"type":413,"tag":448,"props":2543,"children":2544},{"class":450,"line":604},[2545],{"type":413,"tag":448,"props":2546,"children":2547},{"style":2393},[2548],{"type":418,"value":2549},"# Retrieve the repository full name (org/repo)\n",{"type":413,"tag":448,"props":2551,"children":2552},{"class":450,"line":617},[2553,2557,2561,2565,2569,2573,2577,2581,2585,2589,2593,2597,2601],{"type":413,"tag":448,"props":2554,"children":2555},{"style":461},[2556],{"type":418,"value":1026},{"type":413,"tag":448,"props":2558,"children":2559},{"style":1029},[2560],{"type":418,"value":1149},{"type":413,"tag":448,"props":2562,"children":2563},{"style":461},[2564],{"type":418,"value":1154},{"type":413,"tag":448,"props":2566,"children":2567},{"style":1029},[2568],{"type":418,"value":1159},{"type":413,"tag":448,"props":2570,"children":2571},{"style":461},[2572],{"type":418,"value":1071},{"type":413,"tag":448,"props":2574,"children":2575},{"style":1029},[2576],{"type":418,"value":1168},{"type":413,"tag":448,"props":2578,"children":2579},{"style":461},[2580],{"type":418,"value":1173},{"type":413,"tag":448,"props":2582,"children":2583},{"style":1029},[2584],{"type":418,"value":1178},{"type":413,"tag":448,"props":2586,"children":2587},{"style":461},[2588],{"type":418,"value":1183},{"type":413,"tag":448,"props":2590,"children":2591},{"style":467},[2592],{"type":418,"value":1188},{"type":413,"tag":448,"props":2594,"children":2595},{"style":461},[2596],{"type":418,"value":1183},{"type":413,"tag":448,"props":2598,"children":2599},{"style":461},[2600],{"type":418,"value":2031},{"type":413,"tag":448,"props":2602,"children":2603},{"style":1029},[2604],{"type":418,"value":2605}," \n",{"type":413,"tag":448,"props":2607,"children":2608},{"class":450,"line":650},[2609],{"type":413,"tag":448,"props":2610,"children":2611},{"emptyLinePlaceholder":505},[2612],{"type":418,"value":508},{"type":413,"tag":448,"props":2614,"children":2615},{"class":450,"line":668},[2616],{"type":413,"tag":448,"props":2617,"children":2618},{"style":2393},[2619],{"type":418,"value":2620},"# Retrieve the current subscription and current tenant identifiers \n",{"type":413,"tag":448,"props":2622,"children":2623},{"class":450,"line":681},[2624,2628,2632,2636,2640,2644,2648,2652,2656,2660,2664,2668],{"type":413,"tag":448,"props":2625,"children":2626},{"style":461},[2627],{"type":418,"value":1026},{"type":413,"tag":448,"props":2629,"children":2630},{"style":1029},[2631],{"type":418,"value":1258},{"type":413,"tag":448,"props":2633,"children":2634},{"style":461},[2635],{"type":418,"value":1154},{"type":413,"tag":448,"props":2637,"children":2638},{"style":1029},[2639],{"type":418,"value":1267},{"type":413,"tag":448,"props":2641,"children":2642},{"style":461},[2643],{"type":418,"value":1071},{"type":413,"tag":448,"props":2645,"children":2646},{"style":1029},[2647],{"type":418,"value":1276},{"type":413,"tag":448,"props":2649,"children":2650},{"style":461},[2651],{"type":418,"value":1183},{"type":413,"tag":448,"props":2653,"children":2654},{"style":467},[2655],{"type":418,"value":1285},{"type":413,"tag":448,"props":2657,"children":2658},{"style":461},[2659],{"type":418,"value":1183},{"type":413,"tag":448,"props":2661,"children":2662},{"style":461},[2663],{"type":418,"value":1294},{"type":413,"tag":448,"props":2665,"children":2666},{"style":1029},[2667],{"type":418,"value":1299},{"type":413,"tag":448,"props":2669,"children":2670},{"style":461},[2671],{"type":418,"value":1197},{"type":413,"tag":448,"props":2673,"children":2674},{"class":450,"line":699},[2675,2679,2683,2687,2691,2695,2699,2703,2707,2711,2715,2719],{"type":413,"tag":448,"props":2676,"children":2677},{"style":461},[2678],{"type":418,"value":1026},{"type":413,"tag":448,"props":2680,"children":2681},{"style":1029},[2682],{"type":418,"value":1315},{"type":413,"tag":448,"props":2684,"children":2685},{"style":461},[2686],{"type":418,"value":1154},{"type":413,"tag":448,"props":2688,"children":2689},{"style":1029},[2690],{"type":418,"value":1267},{"type":413,"tag":448,"props":2692,"children":2693},{"style":461},[2694],{"type":418,"value":1071},{"type":413,"tag":448,"props":2696,"children":2697},{"style":1029},[2698],{"type":418,"value":1276},{"type":413,"tag":448,"props":2700,"children":2701},{"style":461},[2702],{"type":418,"value":1183},{"type":413,"tag":448,"props":2704,"children":2705},{"style":467},[2706],{"type":418,"value":1315},{"type":413,"tag":448,"props":2708,"children":2709},{"style":461},[2710],{"type":418,"value":1183},{"type":413,"tag":448,"props":2712,"children":2713},{"style":461},[2714],{"type":418,"value":1294},{"type":413,"tag":448,"props":2716,"children":2717},{"style":1029},[2718],{"type":418,"value":1299},{"type":413,"tag":448,"props":2720,"children":2721},{"style":461},[2722],{"type":418,"value":1197},{"type":413,"tag":448,"props":2724,"children":2725},{"class":450,"line":717},[2726],{"type":413,"tag":448,"props":2727,"children":2728},{"emptyLinePlaceholder":505},[2729],{"type":418,"value":508},{"type":413,"tag":448,"props":2731,"children":2732},{"class":450,"line":735},[2733],{"type":413,"tag":448,"props":2734,"children":2735},{"style":2393},[2736],{"type":418,"value":2737},"# Create an App Registration and its associated service principal\n",{"type":413,"tag":448,"props":2739,"children":2740},{"class":450,"line":743},[2741,2745,2749,2753,2757,2761,2765,2769,2773,2777,2781,2785,2789,2793,2797,2801,2805,2809,2813,2817,2821],{"type":413,"tag":448,"props":2742,"children":2743},{"style":461},[2744],{"type":418,"value":1026},{"type":413,"tag":448,"props":2746,"children":2747},{"style":1029},[2748],{"type":418,"value":1411},{"type":413,"tag":448,"props":2750,"children":2751},{"style":461},[2752],{"type":418,"value":1154},{"type":413,"tag":448,"props":2754,"children":2755},{"style":1029},[2756],{"type":418,"value":1420},{"type":413,"tag":448,"props":2758,"children":2759},{"style":461},[2760],{"type":418,"value":1071},{"type":413,"tag":448,"props":2762,"children":2763},{"style":1029},[2764],{"type":418,"value":1429},{"type":413,"tag":448,"props":2766,"children":2767},{"style":461},[2768],{"type":418,"value":1173},{"type":413,"tag":448,"props":2770,"children":2771},{"style":1029},[2772],{"type":418,"value":1438},{"type":413,"tag":448,"props":2774,"children":2775},{"style":461},[2776],{"type":418,"value":1183},{"type":413,"tag":448,"props":2778,"children":2779},{"style":467},[2780],{"type":418,"value":1447},{"type":413,"tag":448,"props":2782,"children":2783},{"style":461},[2784],{"type":418,"value":1452},{"type":413,"tag":448,"props":2786,"children":2787},{"style":1029},[2788],{"type":418,"value":1149},{"type":413,"tag":448,"props":2790,"children":2791},{"style":461},[2792],{"type":418,"value":1461},{"type":413,"tag":448,"props":2794,"children":2795},{"style":461},[2796],{"type":418,"value":1095},{"type":413,"tag":448,"props":2798,"children":2799},{"style":1029},[2800],{"type":418,"value":1276},{"type":413,"tag":448,"props":2802,"children":2803},{"style":461},[2804],{"type":418,"value":1183},{"type":413,"tag":448,"props":2806,"children":2807},{"style":467},[2808],{"type":418,"value":1411},{"type":413,"tag":448,"props":2810,"children":2811},{"style":461},[2812],{"type":418,"value":1183},{"type":413,"tag":448,"props":2814,"children":2815},{"style":461},[2816],{"type":418,"value":1294},{"type":413,"tag":448,"props":2818,"children":2819},{"style":1029},[2820],{"type":418,"value":1299},{"type":413,"tag":448,"props":2822,"children":2823},{"style":461},[2824],{"type":418,"value":1197},{"type":413,"tag":448,"props":2826,"children":2827},{"class":450,"line":772},[2828,2832,2836,2840,2844,2848,2852,2856,2860,2864,2868,2872,2876,2880,2884,2888],{"type":413,"tag":448,"props":2829,"children":2830},{"style":461},[2831],{"type":418,"value":1026},{"type":413,"tag":448,"props":2833,"children":2834},{"style":1029},[2835],{"type":418,"value":1505},{"type":413,"tag":448,"props":2837,"children":2838},{"style":461},[2839],{"type":418,"value":1154},{"type":413,"tag":448,"props":2841,"children":2842},{"style":1029},[2843],{"type":418,"value":1514},{"type":413,"tag":448,"props":2845,"children":2846},{"style":461},[2847],{"type":418,"value":1071},{"type":413,"tag":448,"props":2849,"children":2850},{"style":1029},[2851],{"type":418,"value":1523},{"type":413,"tag":448,"props":2853,"children":2854},{"style":461},[2855],{"type":418,"value":1026},{"type":413,"tag":448,"props":2857,"children":2858},{"style":1029},[2859],{"type":418,"value":1532},{"type":413,"tag":448,"props":2861,"children":2862},{"style":461},[2863],{"type":418,"value":1071},{"type":413,"tag":448,"props":2865,"children":2866},{"style":1029},[2867],{"type":418,"value":1276},{"type":413,"tag":448,"props":2869,"children":2870},{"style":461},[2871],{"type":418,"value":1183},{"type":413,"tag":448,"props":2873,"children":2874},{"style":467},[2875],{"type":418,"value":1285},{"type":413,"tag":448,"props":2877,"children":2878},{"style":461},[2879],{"type":418,"value":1183},{"type":413,"tag":448,"props":2881,"children":2882},{"style":461},[2883],{"type":418,"value":1294},{"type":413,"tag":448,"props":2885,"children":2886},{"style":1029},[2887],{"type":418,"value":1299},{"type":413,"tag":448,"props":2889,"children":2890},{"style":461},[2891],{"type":418,"value":1197},{"type":413,"tag":448,"props":2893,"children":2894},{"class":450,"line":791},[2895],{"type":413,"tag":448,"props":2896,"children":2897},{"emptyLinePlaceholder":505},[2898],{"type":418,"value":508},{"type":413,"tag":448,"props":2900,"children":2901},{"class":450,"line":800},[2902],{"type":413,"tag":448,"props":2903,"children":2904},{"style":2393},[2905],{"type":418,"value":2906},"# Assign the contributor role to the service principal on the subscription\n",{"type":413,"tag":448,"props":2908,"children":2910},{"class":450,"line":2909},23,[2911,2915,2919,2923,2927,2931,2935,2939,2943,2947,2951,2955,2959,2963,2967,2971,2975,2979,2983,2987,2991,2995,2999,3003,3007,3011,3015],{"type":413,"tag":448,"props":2912,"children":2913},{"style":1029},[2914],{"type":418,"value":1584},{"type":413,"tag":448,"props":2916,"children":2917},{"style":461},[2918],{"type":418,"value":1071},{"type":413,"tag":448,"props":2920,"children":2921},{"style":1029},[2922],{"type":418,"value":1593},{"type":413,"tag":448,"props":2924,"children":2925},{"style":461},[2926],{"type":418,"value":1071},{"type":413,"tag":448,"props":2928,"children":2929},{"style":1029},[2930],{"type":418,"value":1602},{"type":413,"tag":448,"props":2932,"children":2933},{"style":461},[2934],{"type":418,"value":1026},{"type":413,"tag":448,"props":2936,"children":2937},{"style":1029},[2938],{"type":418,"value":1611},{"type":413,"tag":448,"props":2940,"children":2941},{"style":461},[2942],{"type":418,"value":1071},{"type":413,"tag":448,"props":2944,"children":2945},{"style":1029},[2946],{"type":418,"value":1620},{"type":413,"tag":448,"props":2948,"children":2949},{"style":461},[2950],{"type":418,"value":1173},{"type":413,"tag":448,"props":2952,"children":2953},{"style":1029},[2954],{"type":418,"value":1629},{"type":413,"tag":448,"props":2956,"children":2957},{"style":461},[2958],{"type":418,"value":1173},{"type":413,"tag":448,"props":2960,"children":2961},{"style":1029},[2962],{"type":418,"value":1638},{"type":413,"tag":448,"props":2964,"children":2965},{"style":461},[2966],{"type":418,"value":1026},{"type":413,"tag":448,"props":2968,"children":2969},{"style":1029},[2970],{"type":418,"value":1647},{"type":413,"tag":448,"props":2972,"children":2973},{"style":461},[2974],{"type":418,"value":1071},{"type":413,"tag":448,"props":2976,"children":2977},{"style":1029},[2978],{"type":418,"value":1620},{"type":413,"tag":448,"props":2980,"children":2981},{"style":461},[2982],{"type":418,"value":1173},{"type":413,"tag":448,"props":2984,"children":2985},{"style":1029},[2986],{"type":418,"value":1664},{"type":413,"tag":448,"props":2988,"children":2989},{"style":461},[2990],{"type":418,"value":1173},{"type":413,"tag":448,"props":2992,"children":2993},{"style":1029},[2994],{"type":418,"value":1673},{"type":413,"tag":448,"props":2996,"children":2997},{"style":461},[2998],{"type":418,"value":1071},{"type":413,"tag":448,"props":3000,"children":3001},{"style":1029},[3002],{"type":418,"value":1682},{"type":413,"tag":448,"props":3004,"children":3005},{"style":461},[3006],{"type":418,"value":1687},{"type":413,"tag":448,"props":3008,"children":3009},{"style":1029},[3010],{"type":418,"value":1692},{"type":413,"tag":448,"props":3012,"children":3013},{"style":461},[3014],{"type":418,"value":1697},{"type":413,"tag":448,"props":3016,"children":3017},{"style":1029},[3018],{"type":418,"value":1702},{"type":413,"tag":448,"props":3020,"children":3022},{"class":450,"line":3021},24,[3023],{"type":413,"tag":448,"props":3024,"children":3025},{"emptyLinePlaceholder":505},[3026],{"type":418,"value":508},{"type":413,"tag":448,"props":3028,"children":3030},{"class":450,"line":3029},25,[3031],{"type":413,"tag":448,"props":3032,"children":3033},{"style":2393},[3034],{"type":418,"value":3035},"# Prepare parameters for federated credentials\n",{"type":413,"tag":448,"props":3037,"children":3039},{"class":450,"line":3038},26,[3040,3044,3048,3052,3056],{"type":413,"tag":448,"props":3041,"children":3042},{"style":461},[3043],{"type":418,"value":1026},{"type":413,"tag":448,"props":3045,"children":3046},{"style":1029},[3047],{"type":418,"value":1726},{"type":413,"tag":448,"props":3049,"children":3050},{"style":461},[3051],{"type":418,"value":1037},{"type":413,"tag":448,"props":3053,"children":3054},{"style":1733},[3055],{"type":418,"value":1736},{"type":413,"tag":448,"props":3057,"children":3058},{"style":461},[3059],{"type":418,"value":1741},{"type":413,"tag":448,"props":3061,"children":3063},{"class":450,"line":3062},27,[3064,3068,3072,3076,3080],{"type":413,"tag":448,"props":3065,"children":3066},{"style":1029},[3067],{"type":418,"value":1749},{"type":413,"tag":448,"props":3069,"children":3070},{"style":461},[3071],{"type":418,"value":1037},{"type":413,"tag":448,"props":3073,"children":3074},{"style":461},[3075],{"type":418,"value":995},{"type":413,"tag":448,"props":3077,"children":3078},{"style":467},[3079],{"type":418,"value":1762},{"type":413,"tag":448,"props":3081,"children":3082},{"style":461},[3083],{"type":418,"value":1005},{"type":413,"tag":448,"props":3085,"children":3087},{"class":450,"line":3086},28,[3088,3092,3096,3100,3104],{"type":413,"tag":448,"props":3089,"children":3090},{"style":1029},[3091],{"type":418,"value":1774},{"type":413,"tag":448,"props":3093,"children":3094},{"style":461},[3095],{"type":418,"value":1037},{"type":413,"tag":448,"props":3097,"children":3098},{"style":461},[3099],{"type":418,"value":995},{"type":413,"tag":448,"props":3101,"children":3102},{"style":467},[3103],{"type":418,"value":1787},{"type":413,"tag":448,"props":3105,"children":3106},{"style":461},[3107],{"type":418,"value":1005},{"type":413,"tag":448,"props":3109,"children":3111},{"class":450,"line":3110},29,[3112,3116,3120,3124,3128,3132,3136,3140,3144],{"type":413,"tag":448,"props":3113,"children":3114},{"style":1029},[3115],{"type":418,"value":1799},{"type":413,"tag":448,"props":3117,"children":3118},{"style":461},[3119],{"type":418,"value":1037},{"type":413,"tag":448,"props":3121,"children":3122},{"style":461},[3123],{"type":418,"value":995},{"type":413,"tag":448,"props":3125,"children":3126},{"style":467},[3127],{"type":418,"value":1812},{"type":413,"tag":448,"props":3129,"children":3130},{"style":461},[3131],{"type":418,"value":1452},{"type":413,"tag":448,"props":3133,"children":3134},{"style":1029},[3135],{"type":418,"value":1149},{"type":413,"tag":448,"props":3137,"children":3138},{"style":461},[3139],{"type":418,"value":1825},{"type":413,"tag":448,"props":3141,"children":3142},{"style":467},[3143],{"type":418,"value":1830},{"type":413,"tag":448,"props":3145,"children":3146},{"style":461},[3147],{"type":418,"value":1005},{"type":413,"tag":448,"props":3149,"children":3151},{"class":450,"line":3150},30,[3152,3156,3160,3164,3168,3172,3176],{"type":413,"tag":448,"props":3153,"children":3154},{"style":1029},[3155],{"type":418,"value":1842},{"type":413,"tag":448,"props":3157,"children":3158},{"style":461},[3159],{"type":418,"value":1037},{"type":413,"tag":448,"props":3161,"children":3162},{"style":461},[3163],{"type":418,"value":995},{"type":413,"tag":448,"props":3165,"children":3166},{"style":467},[3167],{"type":418,"value":1855},{"type":413,"tag":448,"props":3169,"children":3170},{"style":461},[3171],{"type":418,"value":1452},{"type":413,"tag":448,"props":3173,"children":3174},{"style":1029},[3175],{"type":418,"value":1149},{"type":413,"tag":448,"props":3177,"children":3178},{"style":461},[3179],{"type":418,"value":1868},{"type":413,"tag":448,"props":3181,"children":3183},{"class":450,"line":3182},31,[3184,3188,3192,3196],{"type":413,"tag":448,"props":3185,"children":3186},{"style":1029},[3187],{"type":418,"value":1876},{"type":413,"tag":448,"props":3189,"children":3190},{"style":461},[3191],{"type":418,"value":1037},{"type":413,"tag":448,"props":3193,"children":3194},{"style":1733},[3195],{"type":418,"value":1736},{"type":413,"tag":448,"props":3197,"children":3198},{"style":461},[3199],{"type":418,"value":1889},{"type":413,"tag":448,"props":3201,"children":3203},{"class":450,"line":3202},32,[3204,3208,3212],{"type":413,"tag":448,"props":3205,"children":3206},{"style":461},[3207],{"type":418,"value":1897},{"type":413,"tag":448,"props":3209,"children":3210},{"style":467},[3211],{"type":418,"value":1902},{"type":413,"tag":448,"props":3213,"children":3214},{"style":461},[3215],{"type":418,"value":1005},{"type":413,"tag":448,"props":3217,"children":3219},{"class":450,"line":3218},33,[3220],{"type":413,"tag":448,"props":3221,"children":3222},{"style":461},[3223],{"type":418,"value":1914},{"type":413,"tag":448,"props":3225,"children":3227},{"class":450,"line":3226},34,[3228],{"type":413,"tag":448,"props":3229,"children":3230},{"style":461},[3231],{"type":418,"value":1922},{"type":413,"tag":448,"props":3233,"children":3235},{"class":450,"line":3234},35,[3236],{"type":413,"tag":448,"props":3237,"children":3238},{"emptyLinePlaceholder":505},[3239],{"type":418,"value":508},{"type":413,"tag":448,"props":3241,"children":3243},{"class":450,"line":3242},36,[3244],{"type":413,"tag":448,"props":3245,"children":3246},{"style":2393},[3247],{"type":418,"value":3248},"# Change parameters to single line string with escaped quotes to make it work with Azure CLI\n",{"type":413,"tag":448,"props":3250,"children":3252},{"class":450,"line":3251},37,[3253],{"type":413,"tag":448,"props":3254,"children":3255},{"style":2393},[3256],{"type":418,"value":3257},"# https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b\n",{"type":413,"tag":448,"props":3259,"children":3261},{"class":450,"line":3260},38,[3262,3266,3270,3274,3278,3282,3286,3290,3294,3298,3302,3306,3310,3314,3318,3322,3326,3330,3334,3338,3342,3346,3350,3354],{"type":413,"tag":448,"props":3263,"children":3264},{"style":461},[3265],{"type":418,"value":1026},{"type":413,"tag":448,"props":3267,"children":3268},{"style":1029},[3269],{"type":418,"value":1979},{"type":413,"tag":448,"props":3271,"children":3272},{"style":461},[3273],{"type":418,"value":1037},{"type":413,"tag":448,"props":3275,"children":3276},{"style":461},[3277],{"type":418,"value":1988},{"type":413,"tag":448,"props":3279,"children":3280},{"style":1029},[3281],{"type":418,"value":1726},{"type":413,"tag":448,"props":3283,"children":3284},{"style":461},[3285],{"type":418,"value":1997},{"type":413,"tag":448,"props":3287,"children":3288},{"style":2000},[3289],{"type":418,"value":2003},{"type":413,"tag":448,"props":3291,"children":3292},{"style":461},[3293],{"type":418,"value":1294},{"type":413,"tag":448,"props":3295,"children":3296},{"style":1029},[3297],{"type":418,"value":2012},{"type":413,"tag":448,"props":3299,"children":3300},{"style":1733},[3301],{"type":418,"value":2017},{"type":413,"tag":448,"props":3303,"children":3304},{"style":461},[3305],{"type":418,"value":1294},{"type":413,"tag":448,"props":3307,"children":3308},{"style":1029},[3309],{"type":418,"value":2026},{"type":413,"tag":448,"props":3311,"children":3312},{"style":461},[3313],{"type":418,"value":2031},{"type":413,"tag":448,"props":3315,"children":3316},{"style":1029},[3317],{"type":418,"value":2036},{"type":413,"tag":448,"props":3319,"children":3320},{"style":461},[3321],{"type":418,"value":2041},{"type":413,"tag":448,"props":3323,"children":3324},{"style":461},[3325],{"type":418,"value":1183},{"type":413,"tag":448,"props":3327,"children":3328},{"style":1029},[3329],{"type":418,"value":2050},{"type":413,"tag":448,"props":3331,"children":3332},{"style":461},[3333],{"type":418,"value":1183},{"type":413,"tag":448,"props":3335,"children":3336},{"style":461},[3337],{"type":418,"value":2059},{"type":413,"tag":448,"props":3339,"children":3340},{"style":461},[3341],{"type":418,"value":995},{"type":413,"tag":448,"props":3343,"children":3344},{"style":467},[3345],{"type":418,"value":2068},{"type":413,"tag":448,"props":3347,"children":3348},{"style":1029},[3349],{"type":418,"value":2050},{"type":413,"tag":448,"props":3351,"children":3352},{"style":461},[3353],{"type":418,"value":1183},{"type":413,"tag":448,"props":3355,"children":3356},{"style":461},[3357],{"type":418,"value":1197},{"type":413,"tag":448,"props":3359,"children":3361},{"class":450,"line":3360},39,[3362],{"type":413,"tag":448,"props":3363,"children":3364},{"emptyLinePlaceholder":505},[3365],{"type":418,"value":508},{"type":413,"tag":448,"props":3367,"children":3369},{"class":450,"line":3368},40,[3370],{"type":413,"tag":448,"props":3371,"children":3372},{"style":2393},[3373],{"type":418,"value":3374},"# Create federated credentials\n",{"type":413,"tag":448,"props":3376,"children":3378},{"class":450,"line":3377},41,[3379,3383,3387,3391,3395,3399,3403,3407,3411,3415,3419],{"type":413,"tag":448,"props":3380,"children":3381},{"style":1029},[3382],{"type":418,"value":2100},{"type":413,"tag":448,"props":3384,"children":3385},{"style":461},[3386],{"type":418,"value":1173},{"type":413,"tag":448,"props":3388,"children":3389},{"style":1029},[3390],{"type":418,"value":2109},{"type":413,"tag":448,"props":3392,"children":3393},{"style":461},[3394],{"type":418,"value":1071},{"type":413,"tag":448,"props":3396,"children":3397},{"style":1029},[3398],{"type":418,"value":1523},{"type":413,"tag":448,"props":3400,"children":3401},{"style":461},[3402],{"type":418,"value":1026},{"type":413,"tag":448,"props":3404,"children":3405},{"style":1029},[3406],{"type":418,"value":1532},{"type":413,"tag":448,"props":3408,"children":3409},{"style":461},[3410],{"type":418,"value":1071},{"type":413,"tag":448,"props":3412,"children":3413},{"style":1029},[3414],{"type":418,"value":1979},{"type":413,"tag":448,"props":3416,"children":3417},{"style":461},[3418],{"type":418,"value":1026},{"type":413,"tag":448,"props":3420,"children":3421},{"style":1029},[3422],{"type":418,"value":2142},{"type":413,"tag":448,"props":3424,"children":3426},{"class":450,"line":3425},42,[3427],{"type":413,"tag":448,"props":3428,"children":3429},{"emptyLinePlaceholder":505},[3430],{"type":418,"value":508},{"type":413,"tag":448,"props":3432,"children":3434},{"class":450,"line":3433},43,[3435],{"type":413,"tag":448,"props":3436,"children":3437},{"style":2393},[3438],{"type":418,"value":3439},"# Create GitHub secrets needed for the GitHub Actions\n",{"type":413,"tag":448,"props":3441,"children":3443},{"class":450,"line":3442},44,[3444,3448,3452,3456,3460],{"type":413,"tag":448,"props":3445,"children":3446},{"style":1029},[3447],{"type":418,"value":2188},{"type":413,"tag":448,"props":3449,"children":3450},{"style":461},[3451],{"type":418,"value":1071},{"type":413,"tag":448,"props":3453,"children":3454},{"style":1029},[3455],{"type":418,"value":2197},{"type":413,"tag":448,"props":3457,"children":3458},{"style":461},[3459],{"type":418,"value":1026},{"type":413,"tag":448,"props":3461,"children":3462},{"style":1029},[3463],{"type":418,"value":2206},{"type":413,"tag":448,"props":3465,"children":3467},{"class":450,"line":3466},45,[3468,3472,3476,3480,3484],{"type":413,"tag":448,"props":3469,"children":3470},{"style":1029},[3471],{"type":418,"value":2214},{"type":413,"tag":448,"props":3473,"children":3474},{"style":461},[3475],{"type":418,"value":1071},{"type":413,"tag":448,"props":3477,"children":3478},{"style":1029},[3479],{"type":418,"value":2197},{"type":413,"tag":448,"props":3481,"children":3482},{"style":461},[3483],{"type":418,"value":1026},{"type":413,"tag":448,"props":3485,"children":3486},{"style":1029},[3487],{"type":418,"value":1702},{"type":413,"tag":448,"props":3489,"children":3491},{"class":450,"line":3490},46,[3492,3496,3500,3504,3508],{"type":413,"tag":448,"props":3493,"children":3494},{"style":1029},[3495],{"type":418,"value":2238},{"type":413,"tag":448,"props":3497,"children":3498},{"style":461},[3499],{"type":418,"value":1071},{"type":413,"tag":448,"props":3501,"children":3502},{"style":1029},[3503],{"type":418,"value":2197},{"type":413,"tag":448,"props":3505,"children":3506},{"style":461},[3507],{"type":418,"value":1026},{"type":413,"tag":448,"props":3509,"children":3510},{"style":1029},[3511],{"type":418,"value":2255},{"type":413,"tag":448,"props":3513,"children":3515},{"class":450,"line":3514},47,[3516],{"type":413,"tag":448,"props":3517,"children":3518},{"emptyLinePlaceholder":505},[3519],{"type":418,"value":508},{"type":413,"tag":448,"props":3521,"children":3523},{"class":450,"line":3522},48,[3524],{"type":413,"tag":448,"props":3525,"children":3526},{"style":2393},[3527],{"type":418,"value":3528},"# Run workflow\n",{"type":413,"tag":448,"props":3530,"children":3532},{"class":450,"line":3531},49,[3533],{"type":413,"tag":448,"props":3534,"children":3535},{"style":1029},[3536],{"type":418,"value":2275},{"type":413,"tag":448,"props":3538,"children":3540},{"class":450,"line":3539},50,[3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593,3597,3601],{"type":413,"tag":448,"props":3542,"children":3543},{"style":461},[3544],{"type":418,"value":1026},{"type":413,"tag":448,"props":3546,"children":3547},{"style":1029},[3548],{"type":418,"value":2287},{"type":413,"tag":448,"props":3550,"children":3551},{"style":461},[3552],{"type":418,"value":1154},{"type":413,"tag":448,"props":3554,"children":3555},{"style":1029},[3556],{"type":418,"value":2296},{"type":413,"tag":448,"props":3558,"children":3559},{"style":461},[3560],{"type":418,"value":1071},{"type":413,"tag":448,"props":3562,"children":3563},{"style":1029},[3564],{"type":418,"value":2305},{"type":413,"tag":448,"props":3566,"children":3567},{"style":461},[3568],{"type":418,"value":1037},{"type":413,"tag":448,"props":3570,"children":3571},{"style":1029},[3572],{"type":418,"value":2314},{"type":413,"tag":448,"props":3574,"children":3575},{"style":461},[3576],{"type":418,"value":1071},{"type":413,"tag":448,"props":3578,"children":3579},{"style":1029},[3580],{"type":418,"value":2323},{"type":413,"tag":448,"props":3582,"children":3583},{"style":461},[3584],{"type":418,"value":1173},{"type":413,"tag":448,"props":3586,"children":3587},{"style":1029},[3588],{"type":418,"value":1178},{"type":413,"tag":448,"props":3590,"children":3591},{"style":461},[3592],{"type":418,"value":1183},{"type":413,"tag":448,"props":3594,"children":3595},{"style":467},[3596],{"type":418,"value":2340},{"type":413,"tag":448,"props":3598,"children":3599},{"style":461},[3600],{"type":418,"value":1183},{"type":413,"tag":448,"props":3602,"children":3603},{"style":461},[3604],{"type":418,"value":1197},{"type":413,"tag":448,"props":3606,"children":3608},{"class":450,"line":3607},51,[3609,3613,3617],{"type":413,"tag":448,"props":3610,"children":3611},{"style":1029},[3612],{"type":418,"value":2356},{"type":413,"tag":448,"props":3614,"children":3615},{"style":461},[3616],{"type":418,"value":1026},{"type":413,"tag":448,"props":3618,"children":3619},{"style":1029},[3620],{"type":418,"value":2365},{"type":413,"tag":448,"props":3622,"children":3624},{"class":450,"line":3623},52,[3625],{"type":413,"tag":448,"props":3626,"children":3627},{"emptyLinePlaceholder":505},[3628],{"type":418,"value":508},{"type":413,"tag":448,"props":3630,"children":3632},{"class":450,"line":3631},53,[3633],{"type":413,"tag":448,"props":3634,"children":3635},{"style":2393},[3636],{"type":418,"value":3637},"# Open the repostory in the browser\n",{"type":413,"tag":448,"props":3639,"children":3641},{"class":450,"line":3640},54,[3642,3646,3650],{"type":413,"tag":448,"props":3643,"children":3644},{"style":1029},[3645],{"type":418,"value":1159},{"type":413,"tag":448,"props":3647,"children":3648},{"style":461},[3649],{"type":418,"value":1173},{"type":413,"tag":448,"props":3651,"children":3652},{"style":1029},[3653],{"type":418,"value":3654},"w\n",{"type":413,"tag":420,"props":3656,"children":3658},{"id":3657},"final-thoughts",[3659],{"type":418,"value":3660},"Final Thoughts",{"type":413,"tag":414,"props":3662,"children":3663},{},[3664,3666,3672],{"type":418,"value":3665},"I am very glad to have scripted the creation and configuration of a GitHub repository ready to deploy to Azure. Even if I had already done the ",{"type":413,"tag":813,"props":3667,"children":3669},{"href":852,"rel":3668},[817],[3670],{"type":418,"value":3671},"same using Pulumi",{"type":418,"value":3673},", having a small script can sometimes be more convenient than having a full IaC program. In my case, I needed to automate that for a workshop, so it was easier to give participants a script to execute.",{"type":413,"tag":414,"props":3675,"children":3676},{},[3677],{"type":418,"value":3678},"However, I must admit that developing this script proved to be much more challenging than provisioning the same resources using Pulumi. I didn't expect it to take so much time: browsing the CLI documentation, finding the correct syntax, and understanding the cause of failures. In contrast, using the GitHub and Azure Pulumi providers in my TypeScript code turned out to be a much more enjoyable experience.",{"type":413,"tag":414,"props":3680,"children":3681},{},[3682,3684,3689,3691,3697],{"type":418,"value":3683},"Nevertheless, I was pleased to be introduced to the GitHub CLI, which I hadn't explored extensively until now. While I found it very useful, a few things bothered me. Not all commands can be used with the ",{"type":413,"tag":444,"props":3685,"children":3687},{"className":3686},[],[3688],{"type":418,"value":1211},{"type":418,"value":3690}," and ",{"type":413,"tag":444,"props":3692,"children":3694},{"className":3693},[],[3695],{"type":418,"value":3696},"-q",{"type":418,"value":3698}," parameters, which is not very convenient for scripting. Commands that create things (repo, workflow runs) don't return the identifier of the thing they create. I wish GitHub CLI would be more similar to Azure CLI in these matters. I have no doubt these will be improved over time.",{"type":413,"tag":414,"props":3700,"children":3701},{},[3702],{"type":418,"value":3703},"As for Azure CLI, I am still a big fan, although a bit disappointed to have struggled with the inline JSON string.",{"type":413,"tag":414,"props":3705,"children":3706},{},[3707],{"type":418,"value":3708},"Keep learning, keep sharing.",{"type":413,"tag":3710,"props":3711,"children":3712},"style",{},[3713],{"type":418,"value":3714},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":401,"searchDepth":473,"depth":473,"links":3716},[3717,3718,3724,3725],{"id":422,"depth":473,"text":425},{"id":861,"depth":473,"text":864,"children":3719},[3720,3721,3722,3723],{"id":868,"depth":488,"text":871},{"id":913,"depth":488,"text":916},{"id":1231,"depth":488,"text":1234},{"id":2145,"depth":488,"text":2148},{"id":2377,"depth":473,"text":2380},{"id":3657,"depth":473,"text":3660},"markdown","content:1.posts:55.scripting-azure-ready-github-repository.md","content","1.posts/55.scripting-azure-ready-github-repository.md","md",{"_path":124,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":123,"description":3732,"lead":3733,"date":3734,"image":3735,"badge":3737,"tags":3739,"body":3740,"_type":3726,"_id":4752,"_source":3728,"_file":4753,"_extension":3730},"When using some API Clients (like REST Client or the HTTP Client of JetBrains' IDEs), environment variables are stored in JSON files that can contain secrets. To share these files within a team, developers tend to send them by email or by messaging applications, which is not very convenient nor secure 🔐. I thought it would be a good idea to store these secrets directly in an Azure Key Vault and automate the generation of a JSON file containing the secrets using Azure CLI and Nushell.","Playing with Azure CLI and Nushell to generate a secret environment file to send HTTP requests","2022-08-01T00:00:00.000Z",{"src":3736},"/images/padlock_1.jpg",{"label":3738},"Tooling",[206,213,243,225,260],{"type":410,"children":3741,"toc":4746},[3742,3780,3786,3822,3864,3915,3924,3929,3950,3956,3961,3969,3974,3980,4000,4013,4022,4033,4203,4208,4217,4222,4231,4244,4253,4269,4281,4290,4310,4319,4332,4341,4369,4374,4383,4396,4404,4409,4418,4430,4439,4451,4456,4713,4718,4723,4737,4742],{"type":413,"tag":414,"props":3743,"children":3744},{},[3745,3747,3754,3756,3763,3765,3771,3772,3779],{"type":418,"value":3746},"When using some API Clients (like ",{"type":413,"tag":813,"props":3748,"children":3751},{"href":3749,"rel":3750},"https://marketplace.visualstudio.com/items?itemName=humao.rest-client",[817],[3752],{"type":418,"value":3753},"REST Client",{"type":418,"value":3755}," or the ",{"type":413,"tag":813,"props":3757,"children":3760},{"href":3758,"rel":3759},"https://www.jetbrains.com/help/rider/Http_client_in__product__code_editor.html",[817],[3761],{"type":418,"value":3762},"HTTP Client of JetBrains' IDEs",{"type":418,"value":3764},"), environment variables are stored in JSON files that can contain secrets. To share these files within a team, developers tend to send them by email or by messaging applications, which is not very convenient nor secure 🔐. I thought it would be a good idea to store these secrets directly in an Azure Key Vault and automate the generation of a JSON file containing the secrets using ",{"type":413,"tag":813,"props":3766,"children":3769},{"href":3767,"rel":3768},"https://docs.microsoft.com/en-us/cli/azure/",[817],[3770],{"type":418,"value":225},{"type":418,"value":3690},{"type":413,"tag":813,"props":3773,"children":3776},{"href":3774,"rel":3775},"https://www.nushell.sh/",[817],[3777],{"type":418,"value":3778},"Nushell",{"type":418,"value":898},{"type":413,"tag":420,"props":3781,"children":3783},{"id":3782},"the-problem-keep-secrets-secure-while-making-http-requests",[3784],{"type":418,"value":3785},"The problem: keep secrets secure while making HTTP requests",{"type":413,"tag":414,"props":3787,"children":3788},{},[3789,3791,3797,3799,3804,3806,3812,3814,3820],{"type":418,"value":3790},"If you have read my article \"",{"type":413,"tag":813,"props":3792,"children":3795},{"href":3793,"rel":3794},"https://www.techwatching.dev/posts/testing-your-api-with-rest-client",[817],[3796],{"type":418,"value":9},{"type":418,"value":3798},"\", you know I am a big fan of using the vscode extension ",{"type":413,"tag":444,"props":3800,"children":3802},{"className":3801},[],[3803],{"type":418,"value":3753},{"type":418,"value":3805}," to make HTTP requests instead of using GUI tools like Postman. With REST Client, you write your HTTP requests using the standard RFC 2616 in ",{"type":413,"tag":444,"props":3807,"children":3809},{"className":3808},[],[3810],{"type":418,"value":3811},".http",{"type":418,"value":3813}," or ",{"type":413,"tag":444,"props":3815,"children":3817},{"className":3816},[],[3818],{"type":418,"value":3819},".rest",{"type":418,"value":3821}," files and commit them to your git repository. You can define environments and their associated variables in the workspace settings file of vscode (you can also store them in the user settings file but I don't recommend it as they would apply to every vscode workspace). If you have some secrets among your environment variables (like an API key for instance), you obviously can't commit this settings file (you should never commit secrets to a git repository). So sharing among your developer team the environment variables needed to run the requests can be difficult.",{"type":413,"tag":437,"props":3823,"children":3826},{"className":3824,"code":3825,"language":212,"meta":401,"style":401},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","### Get Luke Skywalker\nGET https://swapi.co/api/people/?search=Luke HTTP/1.1\n",[3827],{"type":413,"tag":444,"props":3828,"children":3829},{"__ignoreMap":401},[3830,3838],{"type":413,"tag":448,"props":3831,"children":3832},{"class":450,"line":451},[3833],{"type":413,"tag":448,"props":3834,"children":3835},{"style":2393},[3836],{"type":418,"value":3837},"### Get Luke Skywalker\n",{"type":413,"tag":448,"props":3839,"children":3840},{"class":450,"line":473},[3841,3846,3851,3855,3859],{"type":413,"tag":448,"props":3842,"children":3843},{"style":785},[3844],{"type":418,"value":3845},"GET",{"type":413,"tag":448,"props":3847,"children":3848},{"style":1029},[3849],{"type":418,"value":3850}," https://swapi.co/api/people/?search=Luke ",{"type":413,"tag":448,"props":3852,"children":3853},{"style":1733},[3854],{"type":418,"value":213},{"type":413,"tag":448,"props":3856,"children":3857},{"style":1029},[3858],{"type":418,"value":1687},{"type":413,"tag":448,"props":3860,"children":3861},{"style":1733},[3862],{"type":418,"value":3863},"1.1\n",{"type":413,"tag":414,"props":3865,"children":3866},{},[3867,3869,3876,3878,3884,3886,3891,3892,3897,3899,3905,3907,3913],{"type":418,"value":3868},"I have been using recently the IDE ",{"type":413,"tag":813,"props":3870,"children":3873},{"href":3871,"rel":3872},"https://www.jetbrains.com/fr-fr/rider/",[817],[3874],{"type":418,"value":3875},"Rider",{"type":418,"value":3877},", which has (like all the other JetBrains' IDEs) an integrated ",{"type":413,"tag":813,"props":3879,"children":3881},{"href":3758,"rel":3880},[817],[3882],{"type":418,"value":3883},"HTTP Client",{"type":418,"value":3885},". It's very similar to REST Client (same syntax for the requests that are written in ",{"type":413,"tag":444,"props":3887,"children":3889},{"className":3888},[],[3890],{"type":418,"value":3811},{"type":418,"value":3813},{"type":413,"tag":444,"props":3893,"children":3895},{"className":3894},[],[3896],{"type":418,"value":3819},{"type":418,"value":3898}," files) with some extra features. With this HTTP Client, environment variables are stored in a public JSON environment file ",{"type":413,"tag":444,"props":3900,"children":3902},{"className":3901},[],[3903],{"type":418,"value":3904},"http-client.env.json",{"type":418,"value":3906}," that can be committed. However, secrets can be stored in a private JSON environment file ",{"type":413,"tag":444,"props":3908,"children":3910},{"className":3909},[],[3911],{"type":418,"value":3912},"http-client.private.env.json",{"type":418,"value":3914}," that will not be committed and whose values will override the values in the public file. It's well thought out, yet we still have the problem of sharing with our team the private file containing the secrets.",{"type":413,"tag":414,"props":3916,"children":3917},{},[3918],{"type":413,"tag":832,"props":3919,"children":3923},{"alt":3920,"className":3921,"src":3922},"HTTP file, HTTP environment file, and HTTP private environment opnened file in Rider.",[836,837],"/posts/images/httpclientssecrets_rider_1.png",[],{"type":413,"tag":414,"props":3925,"children":3926},{},[3927],{"type":418,"value":3928},"When someone joins the team or new environment variables have been added, the developer in the team that has the latest version of the environment file usually share it by sending it by email or private message in Microsoft Teams, or Slack... to those who need it. This is not very convenient and this is not a good practice because you don't want secrets floating around. So what can we do about that?",{"type":413,"tag":841,"props":3930,"children":3931},{"icon":843},[3932],{"type":413,"tag":414,"props":3933,"children":3934},{},[3935,3937,3942,3943,3948],{"type":418,"value":3936},"To be honest, even if sharing secrets like that bothered me a bit, I only decided to think of a solution when a friend pointed out to me that the big challenge with tools like ",{"type":413,"tag":444,"props":3938,"children":3940},{"className":3939},[],[3941],{"type":418,"value":3753},{"type":418,"value":3813},{"type":413,"tag":444,"props":3944,"children":3946},{"className":3945},[],[3947],{"type":418,"value":3883},{"type":418,"value":3949}," from JetBrains was managing secrets.",{"type":413,"tag":420,"props":3951,"children":3953},{"id":3952},"the-solution-use-azure-key-vault-and-scripting",[3954],{"type":418,"value":3955},"The solution: use Azure Key Vault and scripting",{"type":413,"tag":414,"props":3957,"children":3958},{},[3959],{"type":418,"value":3960},"The solution is not complicated. I asked myself: where do I usually store secrets? The answer is \"a vault\". Whether it is Azure Key Vault, AWS Secret Manager, Google Cloud Secret Manager, or HashiCorp Vault it does not matter, secrets have to be stored somewhere safe, and it's precisely the purpose of a vault 🔒. I use Azure Key Vault when developing applications so that's what I am going to use as well for secrets needed for sending HTTP requests. If I want my team to be able to retrieve the secrets I just have to ensure everyone has access to the Key Vault.",{"type":413,"tag":841,"props":3962,"children":3963},{"icon":1103},[3964],{"type":413,"tag":414,"props":3965,"children":3966},{},[3967],{"type":418,"value":3968},"By the way, I like to create an Azure AD Group for my team so that all the permissions given in Azure (for the project the team is working on) are assigned to this group instead of to each developer. When someone joins or leaves the team, we then can simply add him to the group or remove him from it.",{"type":413,"tag":414,"props":3970,"children":3971},{},[3972],{"type":418,"value":3973},"If the secrets are stored in an Azure Key Vault, we can let each developer retrieve the secrets from the vault and put them in their private environment file. But honestly, it's not convenient, especially with many secrets. A better solution is to make a script that automatically retrieves the secrets and generates the JSON file. That way the git repository will contain the HTTP requests, the public environment file, and a script to generate the private environment file so that any new joiner will have everything he needs to get started and run the requests.",{"type":413,"tag":420,"props":3975,"children":3977},{"id":3976},"lets-script-that-with-azure-cli-and-nushell",[3978],{"type":418,"value":3979},"Let's script that with Azure CLI and Nushell!",{"type":413,"tag":414,"props":3981,"children":3982},{},[3983,3985,3990,3992,3998],{"type":418,"value":3984},"I have chosen to script that using Azure CLI and Nushell because these are 2 tools I like and I am confident the resulting script will be concise and not too difficult to write. If you are not familiar with Azure CLI, you can check my article \"",{"type":413,"tag":813,"props":3986,"children":3988},{"href":1382,"rel":3987},[817],[3989],{"type":418,"value":15},{"type":418,"value":3991},"\". If you don't know Nushell you can check its ",{"type":413,"tag":813,"props":3993,"children":3995},{"href":3774,"rel":3994},[817],[3996],{"type":418,"value":3997},"website",{"type":418,"value":3999}," or just continue reading this article to see how nice this shell is.",{"type":413,"tag":414,"props":4001,"children":4002},{},[4003,4005,4011],{"type":418,"value":4004},"I have already created an Azure Key Vault named ",{"type":413,"tag":444,"props":4006,"children":4008},{"className":4007},[],[4009],{"type":418,"value":4010},"httpclient-vault",{"type":418,"value":4012}," and set 3 secrets in it.",{"type":413,"tag":414,"props":4014,"children":4015},{},[4016],{"type":413,"tag":832,"props":4017,"children":4021},{"alt":4018,"className":4019,"src":4020},"The Secrets view of an Azure Key Vault resource in Azure Portal",[836,837],"/posts/images/httpclientssecrets_keyvault_1.png",[],{"type":413,"tag":414,"props":4023,"children":4024},{},[4025,4027,4032],{"type":418,"value":4026},"What I am trying to achieve is to produce the following file ",{"type":413,"tag":444,"props":4028,"children":4030},{"className":4029},[],[4031],{"type":418,"value":3912},{"type":418,"value":464},{"type":413,"tag":437,"props":4034,"children":4038},{"className":4035,"code":4036,"language":4037,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"development\":\n  {\n    \"ApiKey\": \"12345678\",\n    \"Username\": \"admin\",\n    \"UserPassword\": \"Password\"\n  }\n}\n","json",[4039],{"type":413,"tag":444,"props":4040,"children":4041},{"__ignoreMap":401},[4042,4049,4071,4079,4118,4155,4188,4196],{"type":413,"tag":448,"props":4043,"children":4044},{"class":450,"line":451},[4045],{"type":413,"tag":448,"props":4046,"children":4047},{"style":461},[4048],{"type":418,"value":1741},{"type":413,"tag":448,"props":4050,"children":4051},{"class":450,"line":473},[4052,4057,4063,4067],{"type":413,"tag":448,"props":4053,"children":4054},{"style":461},[4055],{"type":418,"value":4056},"  \"",{"type":413,"tag":448,"props":4058,"children":4060},{"style":4059},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[4061],{"type":418,"value":4062},"development",{"type":413,"tag":448,"props":4064,"children":4065},{"style":461},[4066],{"type":418,"value":1183},{"type":413,"tag":448,"props":4068,"children":4069},{"style":461},[4070],{"type":418,"value":485},{"type":413,"tag":448,"props":4072,"children":4073},{"class":450,"line":488},[4074],{"type":413,"tag":448,"props":4075,"children":4076},{"style":461},[4077],{"type":418,"value":4078},"  {\n",{"type":413,"tag":448,"props":4080,"children":4081},{"class":450,"line":501},[4082,4087,4092,4096,4100,4104,4109,4113],{"type":413,"tag":448,"props":4083,"children":4084},{"style":461},[4085],{"type":418,"value":4086},"    \"",{"type":413,"tag":448,"props":4088,"children":4089},{"style":949},[4090],{"type":418,"value":4091},"ApiKey",{"type":413,"tag":448,"props":4093,"children":4094},{"style":461},[4095],{"type":418,"value":1183},{"type":413,"tag":448,"props":4097,"children":4098},{"style":461},[4099],{"type":418,"value":464},{"type":413,"tag":448,"props":4101,"children":4102},{"style":461},[4103],{"type":418,"value":995},{"type":413,"tag":448,"props":4105,"children":4106},{"style":467},[4107],{"type":418,"value":4108},"12345678",{"type":413,"tag":448,"props":4110,"children":4111},{"style":461},[4112],{"type":418,"value":1183},{"type":413,"tag":448,"props":4114,"children":4115},{"style":461},[4116],{"type":418,"value":4117},",\n",{"type":413,"tag":448,"props":4119,"children":4120},{"class":450,"line":511},[4121,4125,4130,4134,4138,4142,4147,4151],{"type":413,"tag":448,"props":4122,"children":4123},{"style":461},[4124],{"type":418,"value":4086},{"type":413,"tag":448,"props":4126,"children":4127},{"style":949},[4128],{"type":418,"value":4129},"Username",{"type":413,"tag":448,"props":4131,"children":4132},{"style":461},[4133],{"type":418,"value":1183},{"type":413,"tag":448,"props":4135,"children":4136},{"style":461},[4137],{"type":418,"value":464},{"type":413,"tag":448,"props":4139,"children":4140},{"style":461},[4141],{"type":418,"value":995},{"type":413,"tag":448,"props":4143,"children":4144},{"style":467},[4145],{"type":418,"value":4146},"admin",{"type":413,"tag":448,"props":4148,"children":4149},{"style":461},[4150],{"type":418,"value":1183},{"type":413,"tag":448,"props":4152,"children":4153},{"style":461},[4154],{"type":418,"value":4117},{"type":413,"tag":448,"props":4156,"children":4157},{"class":450,"line":524},[4158,4162,4167,4171,4175,4179,4184],{"type":413,"tag":448,"props":4159,"children":4160},{"style":461},[4161],{"type":418,"value":4086},{"type":413,"tag":448,"props":4163,"children":4164},{"style":949},[4165],{"type":418,"value":4166},"UserPassword",{"type":413,"tag":448,"props":4168,"children":4169},{"style":461},[4170],{"type":418,"value":1183},{"type":413,"tag":448,"props":4172,"children":4173},{"style":461},[4174],{"type":418,"value":464},{"type":413,"tag":448,"props":4176,"children":4177},{"style":461},[4178],{"type":418,"value":995},{"type":413,"tag":448,"props":4180,"children":4181},{"style":467},[4182],{"type":418,"value":4183},"Password",{"type":413,"tag":448,"props":4185,"children":4186},{"style":461},[4187],{"type":418,"value":1005},{"type":413,"tag":448,"props":4189,"children":4190},{"class":450,"line":542},[4191],{"type":413,"tag":448,"props":4192,"children":4193},{"style":461},[4194],{"type":418,"value":4195},"  }\n",{"type":413,"tag":448,"props":4197,"children":4198},{"class":450,"line":560},[4199],{"type":413,"tag":448,"props":4200,"children":4201},{"style":461},[4202],{"type":418,"value":1922},{"type":413,"tag":414,"props":4204,"children":4205},{},[4206],{"type":418,"value":4207},"First, let's list the secrets in the Key Vault:",{"type":413,"tag":414,"props":4209,"children":4210},{},[4211],{"type":413,"tag":832,"props":4212,"children":4216},{"alt":4213,"className":4214,"src":4215},"An Azure CLI command that lists Key Vault secrets in terminal.",[836,837],"/posts/images/httpclientssecrets_script_1.png",[],{"type":413,"tag":414,"props":4218,"children":4219},{},[4220],{"type":418,"value":4221},"The output of the command is not that easy to read because it's JSON and there are some properties we are not interested in. However, Azure CLI supports different output formats and can be used with JMESPath expressions to query the output of a command like this:",{"type":413,"tag":414,"props":4223,"children":4224},{},[4225],{"type":413,"tag":832,"props":4226,"children":4230},{"alt":4227,"className":4228,"src":4229},"An Azure CLI command using JMESPath that lists Key Vault secrets in terminal.",[836,837],"/posts/images/httpclientssecrets_script_2.png",[],{"type":413,"tag":414,"props":4232,"children":4233},{},[4234,4236,4242],{"type":418,"value":4235},"It's nice but I won't need to use this because I can use Nushell (aka Nu) pipelines where everything is structured data that can be filtered, selected, and sorted. To bring the Azure CLI command output into a Nu pipeline, I can use the ",{"type":413,"tag":444,"props":4237,"children":4239},{"className":4238},[],[4240],{"type":418,"value":4241},"from json",{"type":418,"value":4243}," command.",{"type":413,"tag":414,"props":4245,"children":4246},{},[4247],{"type":413,"tag":832,"props":4248,"children":4252},{"alt":4249,"className":4250,"src":4251},"The output of the \"az keyvault secret list --vault-name httpclient-vault | from json\" command in terminal.",[836,837],"/posts/images/httpclientssecrets_script_3.png",[],{"type":413,"tag":841,"props":4254,"children":4255},{"icon":1103},[4256],{"type":413,"tag":414,"props":4257,"children":4258},{},[4259,4261,4267],{"type":418,"value":4260},"Nu has many ",{"type":413,"tag":444,"props":4262,"children":4264},{"className":4263},[],[4265],{"type":418,"value":4266},"from",{"type":418,"value":4268}," commands to convert data from different formats to structured data/table.",{"type":413,"tag":414,"props":4270,"children":4271},{},[4272,4274,4280],{"type":418,"value":4273},"You probably have noticed that the Azure CLI command we used to list the secrets does not provide their values. To retrieve the secret values we have to call another command for each secret using the id of the secret like this: ",{"type":413,"tag":444,"props":4275,"children":4277},{"className":4276},[],[4278],{"type":418,"value":4279},"az keyvault secret show --id $secretId",{"type":418,"value":898},{"type":413,"tag":414,"props":4282,"children":4283},{},[4284],{"type":413,"tag":832,"props":4285,"children":4289},{"alt":4286,"className":4287,"src":4288},"An Azure CLI command that get a secret from Key Vault in terminal.",[836,837],"/posts/images/httpclientssecrets_script_4.png",[],{"type":413,"tag":414,"props":4291,"children":4292},{},[4293,4295,4300,4302,4308],{"type":418,"value":4294},"Again we can use the ",{"type":413,"tag":444,"props":4296,"children":4298},{"className":4297},[],[4299],{"type":418,"value":4241},{"type":418,"value":4301}," command, and the ",{"type":413,"tag":444,"props":4303,"children":4305},{"className":4304},[],[4306],{"type":418,"value":4307},"get",{"type":418,"value":4309}," command to only retrieve the value of a secret.",{"type":413,"tag":414,"props":4311,"children":4312},{},[4313],{"type":413,"tag":832,"props":4314,"children":4318},{"alt":4315,"className":4316,"src":4317},"The output of the nushell script retrieving a secret value from keyvault.",[836,837],"/posts/images/httpclientssecrets_script_5.png",[],{"type":413,"tag":414,"props":4320,"children":4321},{},[4322,4324,4330],{"type":418,"value":4323},"Now that we know how to retrieve the value of a secret, we can insert a new column ",{"type":413,"tag":444,"props":4325,"children":4327},{"className":4326},[],[4328],{"type":418,"value":4329},"value",{"type":418,"value":4331}," into our table that will be filled with the value of each secret retrieved   using the previous command:",{"type":413,"tag":414,"props":4333,"children":4334},{},[4335],{"type":413,"tag":832,"props":4336,"children":4340},{"alt":4337,"className":4338,"src":4339},"The output of the nushell script retrieving a list of secrets from keyvault.",[836,837],"/posts/images/httpclientssecrets_script_6.png",[],{"type":413,"tag":414,"props":4342,"children":4343},{},[4344,4345,4351,4353,4359,4361,4367],{"type":418,"value":1930},{"type":413,"tag":444,"props":4346,"children":4348},{"className":4347},[],[4349],{"type":418,"value":4350},"{|secret| (az keyvault secret show --id $secret.id | from json | get value)}",{"type":418,"value":4352}," part is a block that is executed for each row. The ",{"type":413,"tag":444,"props":4354,"children":4356},{"className":4355},[],[4357],{"type":418,"value":4358},"secret",{"type":418,"value":4360}," is the parameter of the block which represents the row, with the values of the columns for this row being available as properties of the variable ",{"type":413,"tag":444,"props":4362,"children":4364},{"className":4363},[],[4365],{"type":418,"value":4366},"$secret",{"type":418,"value":4368},". As the command was becoming long for a single line, we wrapped it in parentheses that allow us to write the command on multiple lines.",{"type":413,"tag":414,"props":4370,"children":4371},{},[4372],{"type":418,"value":4373},"As we are only interested in the columns \"name\" and \"value\", we only select them.",{"type":413,"tag":414,"props":4375,"children":4376},{},[4377],{"type":413,"tag":832,"props":4378,"children":4382},{"alt":4379,"className":4380,"src":4381},"The output of the nushell script retrieving Azure Key Vault secrets (name and value).",[836,837],"/posts/images/httpclientssecrets_script_7.png",[],{"type":413,"tag":414,"props":4384,"children":4385},{},[4386,4388,4394],{"type":418,"value":4387},"We have to reorganize the data to make key-value pairs where keys come from the column name and values from the column value. We can use the ",{"type":413,"tag":444,"props":4389,"children":4391},{"className":4390},[],[4392],{"type":418,"value":4393},"transpose",{"type":418,"value":4395}," with the proper flags to do that:",{"type":413,"tag":414,"props":4397,"children":4398},{},[4399],{"type":413,"tag":832,"props":4400,"children":4403},{"alt":4379,"className":4401,"src":4402},[836,837],"/posts/images/httpclientssecrets_script_8.png",[],{"type":413,"tag":414,"props":4405,"children":4406},{},[4407],{"type":418,"value":4408},"Then we wrap the key-value pairs in a JSON object corresponding to the development environment:",{"type":413,"tag":414,"props":4410,"children":4411},{},[4412],{"type":413,"tag":832,"props":4413,"children":4417},{"alt":4414,"className":4415,"src":4416},"The output of the nushell script creating a JSON object from Azure Key Vault secrets.",[836,837],"/posts/images/httpclientssecrets_script_9.png",[],{"type":413,"tag":414,"props":4419,"children":4420},{},[4421,4423,4429],{"type":418,"value":4422},"We can check we get the JSON we want with the ",{"type":413,"tag":444,"props":4424,"children":4426},{"className":4425},[],[4427],{"type":418,"value":4428},"to json",{"type":418,"value":4243},{"type":413,"tag":414,"props":4431,"children":4432},{},[4433],{"type":413,"tag":832,"props":4434,"children":4438},{"alt":4435,"className":4436,"src":4437},"The output of the nushell script creating a JSON string from Azure Key Vault secrets.",[836,837],"/posts/images/httpclientssecrets_script_10.png",[],{"type":413,"tag":414,"props":4440,"children":4441},{},[4442,4444,4449],{"type":418,"value":4443},"And finally, we can save the data in a ",{"type":413,"tag":444,"props":4445,"children":4447},{"className":4446},[],[4448],{"type":418,"value":3912},{"type":418,"value":4450}," file using the save command.",{"type":413,"tag":414,"props":4452,"children":4453},{},[4454],{"type":418,"value":4455},"Here is the final script 🔽:",{"type":413,"tag":437,"props":4457,"children":4460},{"className":4458,"code":4459,"language":243,"meta":401,"style":401},"language-nushell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","(\n  az keyvault secret list --vault-name httpclient-vault |\n  from json |\n  insert value {|secret| (az keyvault secret show --id $secret.id | from json | get value)} |\n  select name value |\n  transpose -rd |\n  { development: $in } |\n  save http-client.private.env.json\n)\n",[4461],{"type":413,"tag":444,"props":4462,"children":4463},{"__ignoreMap":401},[4464,4471,4513,4525,4622,4642,4663,4693,4706],{"type":413,"tag":448,"props":4465,"children":4466},{"class":450,"line":451},[4467],{"type":413,"tag":448,"props":4468,"children":4469},{"style":1029},[4470],{"type":418,"value":1889},{"type":413,"tag":448,"props":4472,"children":4473},{"class":450,"line":473},[4474,4479,4484,4489,4494,4498,4504,4509],{"type":413,"tag":448,"props":4475,"children":4476},{"style":949},[4477],{"type":418,"value":4478},"  az",{"type":413,"tag":448,"props":4480,"children":4481},{"style":467},[4482],{"type":418,"value":4483}," keyvault",{"type":413,"tag":448,"props":4485,"children":4486},{"style":467},[4487],{"type":418,"value":4488}," secret",{"type":413,"tag":448,"props":4490,"children":4491},{"style":467},[4492],{"type":418,"value":4493}," list",{"type":413,"tag":448,"props":4495,"children":4496},{"style":785},[4497],{"type":418,"value":1095},{"type":413,"tag":448,"props":4499,"children":4501},{"style":4500},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[4502],{"type":418,"value":4503},"vault-name",{"type":413,"tag":448,"props":4505,"children":4506},{"style":467},[4507],{"type":418,"value":4508}," httpclient-vault",{"type":413,"tag":448,"props":4510,"children":4511},{"style":785},[4512],{"type":418,"value":788},{"type":413,"tag":448,"props":4514,"children":4515},{"class":450,"line":488},[4516,4521],{"type":413,"tag":448,"props":4517,"children":4518},{"style":1733},[4519],{"type":418,"value":4520},"  from json",{"type":413,"tag":448,"props":4522,"children":4523},{"style":785},[4524],{"type":418,"value":788},{"type":413,"tag":448,"props":4526,"children":4527},{"class":450,"line":501},[4528,4533,4538,4543,4547,4551,4556,4561,4565,4569,4574,4578,4582,4587,4591,4596,4601,4606,4610,4614,4618],{"type":413,"tag":448,"props":4529,"children":4530},{"style":1733},[4531],{"type":418,"value":4532},"  insert",{"type":413,"tag":448,"props":4534,"children":4535},{"style":467},[4536],{"type":418,"value":4537}," value",{"type":413,"tag":448,"props":4539,"children":4540},{"style":461},[4541],{"type":418,"value":4542}," {",{"type":413,"tag":448,"props":4544,"children":4545},{"style":1029},[4546],{"type":418,"value":1997},{"type":413,"tag":448,"props":4548,"children":4549},{"style":4500},[4550],{"type":418,"value":4358},{"type":413,"tag":448,"props":4552,"children":4553},{"style":1029},[4554],{"type":418,"value":4555},"| (",{"type":413,"tag":448,"props":4557,"children":4558},{"style":949},[4559],{"type":418,"value":4560},"az",{"type":413,"tag":448,"props":4562,"children":4563},{"style":467},[4564],{"type":418,"value":4483},{"type":413,"tag":448,"props":4566,"children":4567},{"style":467},[4568],{"type":418,"value":4488},{"type":413,"tag":448,"props":4570,"children":4571},{"style":467},[4572],{"type":418,"value":4573}," show",{"type":413,"tag":448,"props":4575,"children":4576},{"style":785},[4577],{"type":418,"value":1095},{"type":413,"tag":448,"props":4579,"children":4580},{"style":4500},[4581],{"type":418,"value":1285},{"type":413,"tag":448,"props":4583,"children":4584},{"style":1029},[4585],{"type":418,"value":4586}," $secret.id ",{"type":413,"tag":448,"props":4588,"children":4589},{"style":785},[4590],{"type":418,"value":1997},{"type":413,"tag":448,"props":4592,"children":4593},{"style":1733},[4594],{"type":418,"value":4595}," from json",{"type":413,"tag":448,"props":4597,"children":4598},{"style":785},[4599],{"type":418,"value":4600}," |",{"type":413,"tag":448,"props":4602,"children":4603},{"style":1733},[4604],{"type":418,"value":4605}," get",{"type":413,"tag":448,"props":4607,"children":4608},{"style":467},[4609],{"type":418,"value":4537},{"type":413,"tag":448,"props":4611,"children":4612},{"style":1029},[4613],{"type":418,"value":2031},{"type":413,"tag":448,"props":4615,"children":4616},{"style":461},[4617],{"type":418,"value":1825},{"type":413,"tag":448,"props":4619,"children":4620},{"style":785},[4621],{"type":418,"value":788},{"type":413,"tag":448,"props":4623,"children":4624},{"class":450,"line":511},[4625,4630,4634,4638],{"type":413,"tag":448,"props":4626,"children":4627},{"style":1733},[4628],{"type":418,"value":4629},"  select",{"type":413,"tag":448,"props":4631,"children":4632},{"style":467},[4633],{"type":418,"value":628},{"type":413,"tag":448,"props":4635,"children":4636},{"style":467},[4637],{"type":418,"value":4537},{"type":413,"tag":448,"props":4639,"children":4640},{"style":785},[4641],{"type":418,"value":788},{"type":413,"tag":448,"props":4643,"children":4644},{"class":450,"line":524},[4645,4650,4654,4659],{"type":413,"tag":448,"props":4646,"children":4647},{"style":1733},[4648],{"type":418,"value":4649},"  transpose",{"type":413,"tag":448,"props":4651,"children":4652},{"style":785},[4653],{"type":418,"value":1294},{"type":413,"tag":448,"props":4655,"children":4656},{"style":4500},[4657],{"type":418,"value":4658},"rd",{"type":413,"tag":448,"props":4660,"children":4661},{"style":785},[4662],{"type":418,"value":788},{"type":413,"tag":448,"props":4664,"children":4665},{"class":450,"line":542},[4666,4671,4676,4680,4685,4689],{"type":413,"tag":448,"props":4667,"children":4668},{"style":461},[4669],{"type":418,"value":4670},"  {",{"type":413,"tag":448,"props":4672,"children":4673},{"style":1029},[4674],{"type":418,"value":4675}," development",{"type":413,"tag":448,"props":4677,"children":4678},{"style":785},[4679],{"type":418,"value":464},{"type":413,"tag":448,"props":4681,"children":4682},{"style":1029},[4683],{"type":418,"value":4684}," $in ",{"type":413,"tag":448,"props":4686,"children":4687},{"style":461},[4688],{"type":418,"value":1825},{"type":413,"tag":448,"props":4690,"children":4691},{"style":785},[4692],{"type":418,"value":788},{"type":413,"tag":448,"props":4694,"children":4695},{"class":450,"line":560},[4696,4701],{"type":413,"tag":448,"props":4697,"children":4698},{"style":1733},[4699],{"type":418,"value":4700},"  save",{"type":413,"tag":448,"props":4702,"children":4703},{"style":467},[4704],{"type":418,"value":4705}," http-client.private.env.json\n",{"type":413,"tag":448,"props":4707,"children":4708},{"class":450,"line":573},[4709],{"type":413,"tag":448,"props":4710,"children":4711},{"style":1029},[4712],{"type":418,"value":1197},{"type":413,"tag":420,"props":4714,"children":4715},{"id":3657},[4716],{"type":418,"value":4717},"Final thoughts",{"type":413,"tag":414,"props":4719,"children":4720},{},[4721],{"type":418,"value":4722},"In this example, I scripted with Nu the retrieval of secrets from an Azure Key Vault, but it should not be too difficult to apply the same concepts to fetch secrets from another vault.",{"type":413,"tag":414,"props":4724,"children":4725},{},[4726,4728,4735],{"type":418,"value":4727},"I had fun playing with Azure CLI and Nushell to write this script but there are many other ways to do the same thing. There are also probably other tools or services (I have just came across ",{"type":413,"tag":813,"props":4729,"children":4732},{"href":4730,"rel":4731},"https://www.doppler.com/",[817],[4733],{"type":418,"value":4734},"Doppler",{"type":418,"value":4736}," which seems nice) that can help you manage secrets securely.",{"type":413,"tag":414,"props":4738,"children":4739},{},[4740],{"type":418,"value":4741},"I am not a Nushell expert but I find it awesome, and am considering making it my main shell. You should give it a try too. A big thank you to the people in the Nushell Discord that help me with my script ❤️.",{"type":413,"tag":3710,"props":4743,"children":4744},{},[4745],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":4747},[4748,4749,4750,4751],{"id":3782,"depth":473,"text":3785},{"id":3952,"depth":473,"text":3955},{"id":3976,"depth":473,"text":3979},{"id":3657,"depth":473,"text":4717},"content:1.posts:39.http-clients-secrets.md","1.posts/39.http-clients-secrets.md",{"_path":103,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":102,"description":4755,"lead":4756,"date":4757,"image":4758,"badge":4760,"tags":4762,"body":4763,"_type":3726,"_id":4997,"_source":3728,"_file":4998,"_extension":3730},"This is my first article of the series Tips I learned this week for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.","Tooling around .NET, Azure, Github and VS Code.","2022-01-14T00:00:00.000Z",{"src":4759},"/images/surface_1.jpg",{"label":4761},"Tips",[272,239,225,233,208,206],{"type":410,"children":4764,"toc":4990},[4765,4779,4785,4798,4807,4812,4824,4836,4866,4875,4881,4895,4908,4921,4930,4943,4949,4963,4972,4985],{"type":413,"tag":414,"props":4766,"children":4767},{},[4768,4770,4777],{"type":418,"value":4769},"This is my first article of the series ",{"type":413,"tag":813,"props":4771,"children":4774},{"href":4772,"rel":4773},"https://www.techwatching.dev/tags/tips-learned-this-week/",[817],[4775],{"type":418,"value":4776},"Tips I learned this week",{"type":418,"value":4778}," for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.",{"type":413,"tag":420,"props":4780,"children":4782},{"id":4781},"net-tip-of-the-week-changing-the-net-cli-language",[4783],{"type":418,"value":4784},".NET tip of the week: changing the .NET CLI language",{"type":413,"tag":414,"props":4786,"children":4787},{},[4788,4790,4796],{"type":418,"value":4789},"Did you know that you could change the language of the .NET CLI to the one you find most appropriate? By default, the dotnet CLI messages you see when running a dotnet program are your language OS (French in my case). However, by setting the \"DOTNET_CLI_UI_LANGUAGE\" variable environment to ",{"type":413,"tag":444,"props":4791,"children":4793},{"className":4792},[],[4794],{"type":418,"value":4795},"en",{"type":418,"value":4797}," for instance I can change it to English.",{"type":413,"tag":414,"props":4799,"children":4800},{},[4801],{"type":413,"tag":832,"props":4802,"children":4806},{"alt":4803,"className":4804,"src":4805},".NET CLI language change in terminal.",[836,837],"/posts/images/w022022tips_dotnet_cli.png",[],{"type":413,"tag":414,"props":4808,"children":4809},{},[4810],{"type":418,"value":4811},"Why is it useful? Let's imagine I have an issue with a dotnet CLI command and that I want to get some help from the community by posting a question to a Q&A website with a screenshot of my error. If all the messages are in French I will probably not get many answers whereas if it's in English everyone will be able to understand what my commands are doing. There is also the fact that sometimes French accents and special characters are not well displayed by some terminals.",{"type":413,"tag":420,"props":4813,"children":4815},{"id":4814},"the-azure-tip-you-did-not-know-about-simplify-your-azure-cli-configuration-with-azure-init",[4816,4818],{"type":418,"value":4817},"The Azure tip you did not know about: simplify your Azure CLI configuration with ",{"type":413,"tag":444,"props":4819,"children":4821},{"className":4820},[],[4822],{"type":418,"value":4823},"azure init",{"type":413,"tag":414,"props":4825,"children":4826},{},[4827,4829,4834],{"type":418,"value":4828},"I don't know if you use a lot Azure CLI but it's a very nice tool! Each time I use Azure CLI, I think \"it's awesome 🤩 I should use it more often instead of using Azure Portal\". I even wrote a post about that 2 years ago: \"",{"type":413,"tag":813,"props":4830,"children":4832},{"href":1382,"rel":4831},[817],[4833],{"type":418,"value":15},{"type":418,"value":4835},"\".",{"type":413,"tag":414,"props":4837,"children":4838},{},[4839,4841,4847,4849,4856,4858,4864],{"type":418,"value":4840},"However, if you want to configure your Azure CLI, it can be sometimes a bit boring and slow to configure it using the ",{"type":413,"tag":444,"props":4842,"children":4844},{"className":4843},[],[4845],{"type":418,"value":4846},"az config",{"type":418,"value":4848}," command. That is why Microsoft has ",{"type":413,"tag":813,"props":4850,"children":4853},{"href":4851,"rel":4852},"https://techcommunity.microsoft.com/t5/azure-tools-blog/streamline-configuring-azure-cli-with-az-init/ba-p/3051810",[817],[4854],{"type":418,"value":4855},"released in preview",{"type":418,"value":4857}," an Azure CLI extension called ",{"type":413,"tag":444,"props":4859,"children":4861},{"className":4860},[],[4862],{"type":418,"value":4863},"az init",{"type":418,"value":4865}," to simplify this configuration. For example you can quickly configure the output of the commands or the syntax highlighting, things like that.",{"type":413,"tag":414,"props":4867,"children":4868},{},[4869],{"type":413,"tag":832,"props":4870,"children":4874},{"alt":4871,"className":4872,"src":4873},"azure init command output.",[836,837],"/posts/images/w022022tips_az_init.png",[],{"type":413,"tag":420,"props":4876,"children":4878},{"id":4877},"tool-of-the-week-github-code-search",[4879],{"type":418,"value":4880},"Tool of the week: GitHub Code Search",{"type":413,"tag":414,"props":4882,"children":4883},{},[4884,4886,4893],{"type":418,"value":4885},"Have you ever wished you could easily search code on GitHub in multiple repositories without cloning anything? That is now possible with ",{"type":413,"tag":813,"props":4887,"children":4890},{"href":4888,"rel":4889},"https://cs.github.com/",[817],[4891],{"type":418,"value":4892},"GitHub Code Search",{"type":418,"value":4894},". It is still in preview but looks promising! You have access to nice filters to find exactly the code you are looking for, and once you get it you can navigate in and across files.",{"type":413,"tag":414,"props":4896,"children":4897},{},[4898,4900,4906],{"type":418,"value":4899},"For a long time, I have kept a bookmark to the \"",{"type":413,"tag":813,"props":4901,"children":4904},{"href":4902,"rel":4903},"https://source.dot.net/",[817],[4905],{"type":418,"value":4902},{"type":418,"value":4907},"\" website for the times when I needed to understand how something was implemented in the .NET Core framework. But with GitHub Code Search I think I don't need it anymore. .NET Core is open source and all the source code is on GitHub so I can quickly find everything I need just by searching it on GitHub.",{"type":413,"tag":414,"props":4909,"children":4910},{},[4911,4913,4919],{"type":418,"value":4912},"For instance, let's say I don't remember exactly what configuration is injected by default in a dotnet project when you use the ",{"type":413,"tag":444,"props":4914,"children":4916},{"className":4915},[],[4917],{"type":418,"value":4918},"Host.CreateDefaultBuilder",{"type":418,"value":4920}," method. I will scope my search to dotnet organization repositories and a few keystrokes later, I can see all the configuration providers used to load some default configuration in a project.",{"type":413,"tag":414,"props":4922,"children":4923},{},[4924],{"type":413,"tag":832,"props":4925,"children":4929},{"alt":4926,"className":4927,"src":4928},"GitHub search usage.",[836,837],"/posts/images/w022022tips_githu_cs.gif",[],{"type":413,"tag":414,"props":4931,"children":4932},{},[4933,4935,4942],{"type":418,"value":4934},"You can read more about GitHub Code Search on ",{"type":413,"tag":813,"props":4936,"children":4939},{"href":4937,"rel":4938},"https://github.blog/2021-12-08-improving-github-code-search/",[817],[4940],{"type":418,"value":4941},"GitHub's blog",{"type":418,"value":898},{"type":413,"tag":420,"props":4944,"children":4946},{"id":4945},"the-vs-code-extension-you-should-try-i18n-ally",[4947],{"type":418,"value":4948},"The VS Code extension you should try: i18n ally",{"type":413,"tag":414,"props":4950,"children":4951},{},[4952,4954,4961],{"type":418,"value":4953},"When you are developing an application that supports several languages, it can quickly become annoying to go in every translation file when you need to check or modify a translation. If you are developing your application using VS Code, you probably should check out the extension ",{"type":413,"tag":813,"props":4955,"children":4958},{"href":4956,"rel":4957},"https://github.com/lokalise/i18n-ally",[817],[4959],{"type":418,"value":4960},"i18n ally",{"type":418,"value":4962}," because it will save you a lot of time.",{"type":413,"tag":414,"props":4964,"children":4965},{},[4966],{"type":413,"tag":832,"props":4967,"children":4971},{"alt":4968,"className":4969,"src":4970},"i18n ally extension in vscode.",[836,837],"/posts/images/w222021tips_i18n_ally.png",[],{"type":413,"tag":414,"props":4973,"children":4974},{},[4975,4977,4983],{"type":418,"value":4976},"It is very handy and I like the fact the extension support lots of frameworks like Vue.js, Angular, React, Svelte, and Flutter (you can find the complete list of supported frameworks ",{"type":413,"tag":813,"props":4978,"children":4981},{"href":4979,"rel":4980},"https://github.com/lokalise/i18n-ally/wiki/Supported-Frameworks",[817],[4982],{"type":418,"value":1386},{"type":418,"value":4984},"). My only regret with this extension is not to have heard about it sooner.",{"type":413,"tag":414,"props":4986,"children":4987},{},[4988],{"type":418,"value":4989},"And that's it for this week, happy learning!",{"title":401,"searchDepth":473,"depth":473,"links":4991},[4992,4993,4995,4996],{"id":4781,"depth":473,"text":4784},{"id":4814,"depth":473,"text":4994},"The Azure tip you did not know about: simplify your Azure CLI configuration with azure init",{"id":4877,"depth":473,"text":4880},{"id":4945,"depth":473,"text":4948},"content:1.posts:32.w02-2022-tips-learned-this-week.md","1.posts/32.w02-2022-tips-learned-this-week.md",{"_path":97,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":96,"description":5000,"lead":5001,"date":5002,"badge":5003,"image":5004,"tags":5006,"body":5007,"_type":3726,"_id":7562,"_source":3728,"_file":7563,"_extension":3730},"By default when you use Pulumi, the state is managed by Pulumi Service which is very convenient as you can concentrate on building your project infrastructure instead of spending time on where to store the state and how to handle concurrency. However, sometimes for governance or pricing concerns, or any other reasons, you don't want to use Pulumi Service and you prefer to manage the state yourself with your own backend. In this article, we will see how we can do that using Azure.","Pulumi without Pulumi Service.","2021-12-14T00:00:00.000Z",{"label":266},{"src":5005},"/images/cloud-crave_1.jpg",[312,315,225,318,260,228],{"type":410,"children":5008,"toc":7544},[5009,5013,5019,5025,5030,5049,5057,5062,5067,5090,5099,5105,5110,5115,5138,5143,5149,5155,5167,5201,5206,5211,5217,5239,5248,5262,5267,5412,5417,5520,5525,5602,5607,5727,5732,5768,5774,5779,5804,5825,5915,5920,5940,5949,5955,5961,5966,5971,5977,5982,5987,6014,6019,6025,6030,6166,6179,6184,6260,6273,6343,6348,6398,6403,6439,6444,6539,6545,6550,6555,6569,6591,6600,6605,6611,6616,7522,7527,7540],{"type":413,"tag":414,"props":5010,"children":5011},{},[5012],{"type":418,"value":5000},{"type":413,"tag":420,"props":5014,"children":5016},{"id":5015},"a-quick-reminder-about-states-and-backends",[5017],{"type":418,"value":5018},"A quick reminder about states and backends",{"type":413,"tag":866,"props":5020,"children":5022},{"id":5021},"what-is-this-state-we-need-to-store",[5023],{"type":418,"value":5024},"What is this state we need to store?",{"type":413,"tag":414,"props":5026,"children":5027},{},[5028],{"type":418,"value":5029},"Like other Infrastructure as Code platforms, Pulumi uses a declarative approach:",{"type":413,"tag":5031,"props":5032,"children":5033},"ul",{},[5034,5039,5044],{"type":413,"tag":2159,"props":5035,"children":5036},{},[5037],{"type":418,"value":5038},"we write code to describe the desired state of our infrastructure",{"type":413,"tag":2159,"props":5040,"children":5041},{},[5042],{"type":418,"value":5043},"Pulumi engine compares this desired state with the current state of the infrastructure and determines what changes need to be made",{"type":413,"tag":2159,"props":5045,"children":5046},{},[5047],{"type":418,"value":5048},"Pulumi deploys these changes and updates the current state of the provisioned infrastructure",{"type":413,"tag":841,"props":5050,"children":5051},{"icon":843},[5052],{"type":413,"tag":414,"props":5053,"children":5054},{},[5055],{"type":418,"value":5056},"Some people think using Pulumi means adopting an imperative approach because we are using programming languages (so imperative languages) instead of using declarative languages (like YAML, JSON, and HCL). However, being declarative is not about the language used but about defining the \"what\" (the infrastructure we want to provision) instead of the \"how\" (the steps to provision this infrastructure). So Pulumi has the best of both worlds by being declarative while using programming languages.",{"type":413,"tag":414,"props":5058,"children":5059},{},[5060],{"type":418,"value":5061},"As you understood, being able to provision and modify an infrastructure with this declarative approach requires 2 states: the desired state and the current state of the infrastructure. The desired state is the infrastructure code that we usually store in a Git repository alongside the application code. The current state however is computed by the Pulumi engine each time we modify the infrastructure and needs to be stored somewhere.",{"type":413,"tag":414,"props":5063,"children":5064},{},[5065],{"type":418,"value":5066},"That is why we need a \"backend\" to use Pulumi, it's just a place to store the current state of the provisioned infrastructure.",{"type":413,"tag":414,"props":5068,"children":5069},{},[5070,5072,5079,5081,5088],{"type":418,"value":5071},"If you want more information about states and backend, Pulumi has a ",{"type":413,"tag":813,"props":5073,"children":5076},{"href":5074,"rel":5075},"https://www.pulumi.com/docs/intro/concepts/state/",[817],[5077],{"type":418,"value":5078},"documentation page",{"type":418,"value":5080}," about that and there is also ",{"type":413,"tag":813,"props":5082,"children":5085},{"href":5083,"rel":5084},"https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/",[817],[5086],{"type":418,"value":5087},"a page",{"type":418,"value":5089}," about how Pulumi works.",{"type":413,"tag":414,"props":5091,"children":5092},{},[5093],{"type":413,"tag":832,"props":5094,"children":5098},{"alt":5095,"className":5096,"src":5097},"Diagram of how Pulumi works.",[836,837],"/posts/images/pulumiazurebackend_schema_1.png",[],{"type":413,"tag":866,"props":5100,"children":5102},{"id":5101},"what-backends-can-we-use-to-manage-the-infrastructure",[5103],{"type":418,"value":5104},"What \"backends\" can we use to manage the infrastructure?",{"type":413,"tag":414,"props":5106,"children":5107},{},[5108],{"type":418,"value":5109},"The default backend is Pulumi Service which is a web application that stores the infrastructure state and has additional features like concurrent state locking, team policies, or deployment history. This service is managed by Pulumi, is free for individuals but charged for teams, and enterprises. It can be self-hosted in the enterprise plan. Just as a side note, Pulumi Service (along with support and training) is how the company Pulumi makes money because everything else is free and open source.",{"type":413,"tag":414,"props":5111,"children":5112},{},[5113],{"type":418,"value":5114},"Yet, we don't have to pay anything to use Pulumi because Pulumi Service, no matter how good it may be, is not the only solution to store the infrastructure state. Indeed, Pulumi supports other backends that we can manage ourselves:",{"type":413,"tag":5031,"props":5116,"children":5117},{},[5118,5123,5128,5133],{"type":413,"tag":2159,"props":5119,"children":5120},{},[5121],{"type":418,"value":5122},"Local Filesystem",{"type":413,"tag":2159,"props":5124,"children":5125},{},[5126],{"type":418,"value":5127},"AWS S3 (or compatible server)",{"type":413,"tag":2159,"props":5129,"children":5130},{},[5131],{"type":418,"value":5132},"Google Cloud Storage",{"type":413,"tag":2159,"props":5134,"children":5135},{},[5136],{"type":418,"value":5137},"Azure Blob Storage",{"type":413,"tag":414,"props":5139,"children":5140},{},[5141],{"type":418,"value":5142},"In the rest of this article, we will see how to use Pulumi with Azure Blob Storage as the backend for our infrastructure state.",{"type":413,"tag":420,"props":5144,"children":5146},{"id":5145},"using-pulumi-with-the-azure-blob-storage-backend",[5147],{"type":418,"value":5148},"Using Pulumi with the Azure Blob Storage backend",{"type":413,"tag":866,"props":5150,"children":5152},{"id":5151},"what-do-we-need",[5153],{"type":418,"value":5154},"What do we need?",{"type":413,"tag":414,"props":5156,"children":5157},{},[5158,5165],{"type":413,"tag":813,"props":5159,"children":5162},{"href":5160,"rel":5161},"https://www.pulumi.com/docs/intro/concepts/state/#logging-into-the-azure-blob-storage-backend",[817],[5163],{"type":418,"value":5164},"Pulumi documentation",{"type":418,"value":5166}," on using Azure Blob Storage backend is short. It only says that we need to:",{"type":413,"tag":5031,"props":5168,"children":5169},{},[5170,5175,5180],{"type":413,"tag":2159,"props":5171,"children":5172},{},[5173],{"type":418,"value":5174},"set the AZURE_STORAGE_ACCOUNT environment variable to specify the Azure storage account to use",{"type":413,"tag":2159,"props":5176,"children":5177},{},[5178],{"type":418,"value":5179},"set the AZURE_STORAGE_KEY or the AZURE_STORAGE_SAS_TOKEN environment variables to let Pulumi access the storage",{"type":413,"tag":2159,"props":5181,"children":5182},{},[5183,5185,5191,5193,5199],{"type":418,"value":5184},"execute the following command ",{"type":413,"tag":444,"props":5186,"children":5188},{"className":5187},[],[5189],{"type":418,"value":5190},"pulumi login azblob://\u003Ccontainer-path>",{"type":418,"value":5192}," where ",{"type":413,"tag":444,"props":5194,"children":5196},{"className":5195},[],[5197],{"type":418,"value":5198},"container-path",{"type":418,"value":5200}," is the path to a blob container in the storage account",{"type":413,"tag":414,"props":5202,"children":5203},{},[5204],{"type":418,"value":5205},"Once this command is executed, we can start using Pulumi as we would with any other backend. The infrastructure's current state will automatically be stored in the blob container you specified. It will be compared to the desired state when a change is made in the code to know what resources need to be created/updated/deleted.",{"type":413,"tag":414,"props":5207,"children":5208},{},[5209],{"type":418,"value":5210},"In fact, that is not very complex. Nevertheless, the documentation assumes we already have created an Azure storage account with a blob container in it and retrieved the key to access it. That is not the case, so now that we know what we need let's script it!",{"type":413,"tag":866,"props":5212,"children":5214},{"id":5213},"how-to-create-and-configure-the-azure-blob-storage-backend",[5215],{"type":418,"value":5216},"How to create and configure the Azure Blob Storage backend?",{"type":413,"tag":414,"props":5218,"children":5219},{},[5220,5222,5229,5231,5237],{"type":418,"value":5221},"For me, the easiest way to write a script to create and configure the storage account we need is to use Azure CLI. One nice way of writing Azure CLI scripts is to do it in vscode with the ",{"type":413,"tag":813,"props":5223,"children":5226},{"href":5224,"rel":5225},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.azurecli",[817],[5227],{"type":418,"value":5228},"Azure CLI Tools extension",{"type":418,"value":5230},": you can create ",{"type":413,"tag":444,"props":5232,"children":5234},{"className":5233},[],[5235],{"type":418,"value":5236},".azcli",{"type":418,"value":5238}," files with IntelliSense on them and run the commands you are writing in the integrated terminal (see screenshot below).",{"type":413,"tag":414,"props":5240,"children":5241},{},[5242],{"type":413,"tag":832,"props":5243,"children":5247},{"alt":5244,"className":5245,"src":5246},"Azure CLI script in vscode.",[836,837],"/posts/images/pulumiazurebackend_vscode_1.png",[],{"type":413,"tag":841,"props":5249,"children":5250},{"icon":843},[5251],{"type":413,"tag":414,"props":5252,"children":5253},{},[5254,5256,5261],{"type":418,"value":5255},"If you are not familiar with Azure CLI, you can check my article \"",{"type":413,"tag":813,"props":5257,"children":5259},{"href":1382,"rel":5258},[817],[5260],{"type":418,"value":15},{"type":418,"value":4835},{"type":413,"tag":414,"props":5263,"children":5264},{},[5265],{"type":418,"value":5266},"Let's first define a few environment variables: the name of the resource group that will contain our storage account, its location, and the name of the storage account (I am using PowerShell but don't forget to change the syntax if you are using another shell like bash).",{"type":413,"tag":437,"props":5268,"children":5270},{"className":1013,"code":5269,"language":248,"meta":401,"style":401},"$random=Get-Random -Maximum 1000\n$location=\"West Europe\"\n$rgName=\"rg-iacstate-westeu-$random\"\n$saName=\"stiacstate$random\"\n",[5271],{"type":413,"tag":444,"props":5272,"children":5273},{"__ignoreMap":401},[5274,5309,5338,5375],{"type":413,"tag":448,"props":5275,"children":5276},{"class":450,"line":451},[5277,5281,5286,5290,5295,5299,5304],{"type":413,"tag":448,"props":5278,"children":5279},{"style":461},[5280],{"type":418,"value":1026},{"type":413,"tag":448,"props":5282,"children":5283},{"style":1029},[5284],{"type":418,"value":5285},"random",{"type":413,"tag":448,"props":5287,"children":5288},{"style":461},[5289],{"type":418,"value":1037},{"type":413,"tag":448,"props":5291,"children":5292},{"style":2000},[5293],{"type":418,"value":5294},"Get-Random",{"type":413,"tag":448,"props":5296,"children":5297},{"style":461},[5298],{"type":418,"value":1294},{"type":413,"tag":448,"props":5300,"children":5301},{"style":1029},[5302],{"type":418,"value":5303},"Maximum ",{"type":413,"tag":448,"props":5305,"children":5306},{"style":1733},[5307],{"type":418,"value":5308},"1000\n",{"type":413,"tag":448,"props":5310,"children":5311},{"class":450,"line":473},[5312,5316,5321,5325,5329,5334],{"type":413,"tag":448,"props":5313,"children":5314},{"style":461},[5315],{"type":418,"value":1026},{"type":413,"tag":448,"props":5317,"children":5318},{"style":1029},[5319],{"type":418,"value":5320},"location",{"type":413,"tag":448,"props":5322,"children":5323},{"style":461},[5324],{"type":418,"value":1037},{"type":413,"tag":448,"props":5326,"children":5327},{"style":461},[5328],{"type":418,"value":1183},{"type":413,"tag":448,"props":5330,"children":5331},{"style":467},[5332],{"type":418,"value":5333},"West Europe",{"type":413,"tag":448,"props":5335,"children":5336},{"style":461},[5337],{"type":418,"value":1005},{"type":413,"tag":448,"props":5339,"children":5340},{"class":450,"line":488},[5341,5345,5350,5354,5358,5363,5367,5371],{"type":413,"tag":448,"props":5342,"children":5343},{"style":461},[5344],{"type":418,"value":1026},{"type":413,"tag":448,"props":5346,"children":5347},{"style":1029},[5348],{"type":418,"value":5349},"rgName",{"type":413,"tag":448,"props":5351,"children":5352},{"style":461},[5353],{"type":418,"value":1037},{"type":413,"tag":448,"props":5355,"children":5356},{"style":461},[5357],{"type":418,"value":1183},{"type":413,"tag":448,"props":5359,"children":5360},{"style":467},[5361],{"type":418,"value":5362},"rg-iacstate-westeu-",{"type":413,"tag":448,"props":5364,"children":5365},{"style":461},[5366],{"type":418,"value":1026},{"type":413,"tag":448,"props":5368,"children":5369},{"style":1029},[5370],{"type":418,"value":5285},{"type":413,"tag":448,"props":5372,"children":5373},{"style":461},[5374],{"type":418,"value":1005},{"type":413,"tag":448,"props":5376,"children":5377},{"class":450,"line":501},[5378,5382,5387,5391,5395,5400,5404,5408],{"type":413,"tag":448,"props":5379,"children":5380},{"style":461},[5381],{"type":418,"value":1026},{"type":413,"tag":448,"props":5383,"children":5384},{"style":1029},[5385],{"type":418,"value":5386},"saName",{"type":413,"tag":448,"props":5388,"children":5389},{"style":461},[5390],{"type":418,"value":1037},{"type":413,"tag":448,"props":5392,"children":5393},{"style":461},[5394],{"type":418,"value":1183},{"type":413,"tag":448,"props":5396,"children":5397},{"style":467},[5398],{"type":418,"value":5399},"stiacstate",{"type":413,"tag":448,"props":5401,"children":5402},{"style":461},[5403],{"type":418,"value":1026},{"type":413,"tag":448,"props":5405,"children":5406},{"style":1029},[5407],{"type":418,"value":5285},{"type":413,"tag":448,"props":5409,"children":5410},{"style":461},[5411],{"type":418,"value":1005},{"type":413,"tag":414,"props":5413,"children":5414},{},[5415],{"type":418,"value":5416},"Then let's create our resource group and our storage account:",{"type":413,"tag":437,"props":5418,"children":5420},{"className":937,"code":5419,"language":939,"meta":401,"style":401},"az group create -n $rgName -l $location\naz storage account create -g $rgName -n $saName -l $location --sku Standard_LRS\n",[5421],{"type":413,"tag":444,"props":5422,"children":5423},{"__ignoreMap":401},[5424,5461],{"type":413,"tag":448,"props":5425,"children":5426},{"class":450,"line":451},[5427,5431,5436,5441,5446,5451,5456],{"type":413,"tag":448,"props":5428,"children":5429},{"style":949},[5430],{"type":418,"value":4560},{"type":413,"tag":448,"props":5432,"children":5433},{"style":467},[5434],{"type":418,"value":5435}," group",{"type":413,"tag":448,"props":5437,"children":5438},{"style":467},[5439],{"type":418,"value":5440}," create",{"type":413,"tag":448,"props":5442,"children":5443},{"style":467},[5444],{"type":418,"value":5445}," -n",{"type":413,"tag":448,"props":5447,"children":5448},{"style":1029},[5449],{"type":418,"value":5450}," $rgName ",{"type":413,"tag":448,"props":5452,"children":5453},{"style":467},[5454],{"type":418,"value":5455},"-l",{"type":413,"tag":448,"props":5457,"children":5458},{"style":1029},[5459],{"type":418,"value":5460}," $location\n",{"type":413,"tag":448,"props":5462,"children":5463},{"class":450,"line":473},[5464,5468,5473,5478,5482,5487,5491,5496,5501,5505,5510,5515],{"type":413,"tag":448,"props":5465,"children":5466},{"style":949},[5467],{"type":418,"value":4560},{"type":413,"tag":448,"props":5469,"children":5470},{"style":467},[5471],{"type":418,"value":5472}," storage",{"type":413,"tag":448,"props":5474,"children":5475},{"style":467},[5476],{"type":418,"value":5477}," account",{"type":413,"tag":448,"props":5479,"children":5480},{"style":467},[5481],{"type":418,"value":5440},{"type":413,"tag":448,"props":5483,"children":5484},{"style":467},[5485],{"type":418,"value":5486}," -g",{"type":413,"tag":448,"props":5488,"children":5489},{"style":1029},[5490],{"type":418,"value":5450},{"type":413,"tag":448,"props":5492,"children":5493},{"style":467},[5494],{"type":418,"value":5495},"-n",{"type":413,"tag":448,"props":5497,"children":5498},{"style":1029},[5499],{"type":418,"value":5500}," $saName ",{"type":413,"tag":448,"props":5502,"children":5503},{"style":467},[5504],{"type":418,"value":5455},{"type":413,"tag":448,"props":5506,"children":5507},{"style":1029},[5508],{"type":418,"value":5509}," $location ",{"type":413,"tag":448,"props":5511,"children":5512},{"style":467},[5513],{"type":418,"value":5514},"--sku",{"type":413,"tag":448,"props":5516,"children":5517},{"style":467},[5518],{"type":418,"value":5519}," Standard_LRS\n",{"type":413,"tag":414,"props":5521,"children":5522},{},[5523],{"type":418,"value":5524},"The key to access the storage account can be retrieved with the following command:",{"type":413,"tag":437,"props":5526,"children":5528},{"className":937,"code":5527,"language":939,"meta":401,"style":401},"az storage account keys list --account-name $saName -g $rgName -o tsv --query '[0].value'\n",[5529],{"type":413,"tag":444,"props":5530,"children":5531},{"__ignoreMap":401},[5532],{"type":413,"tag":448,"props":5533,"children":5534},{"class":450,"line":451},[5535,5539,5543,5547,5552,5556,5561,5565,5570,5574,5579,5584,5589,5593,5598],{"type":413,"tag":448,"props":5536,"children":5537},{"style":949},[5538],{"type":418,"value":4560},{"type":413,"tag":448,"props":5540,"children":5541},{"style":467},[5542],{"type":418,"value":5472},{"type":413,"tag":448,"props":5544,"children":5545},{"style":467},[5546],{"type":418,"value":5477},{"type":413,"tag":448,"props":5548,"children":5549},{"style":467},[5550],{"type":418,"value":5551}," keys",{"type":413,"tag":448,"props":5553,"children":5554},{"style":467},[5555],{"type":418,"value":4493},{"type":413,"tag":448,"props":5557,"children":5558},{"style":467},[5559],{"type":418,"value":5560}," --account-name",{"type":413,"tag":448,"props":5562,"children":5563},{"style":1029},[5564],{"type":418,"value":5500},{"type":413,"tag":448,"props":5566,"children":5567},{"style":467},[5568],{"type":418,"value":5569},"-g",{"type":413,"tag":448,"props":5571,"children":5572},{"style":1029},[5573],{"type":418,"value":5450},{"type":413,"tag":448,"props":5575,"children":5576},{"style":467},[5577],{"type":418,"value":5578},"-o",{"type":413,"tag":448,"props":5580,"children":5581},{"style":467},[5582],{"type":418,"value":5583}," tsv",{"type":413,"tag":448,"props":5585,"children":5586},{"style":467},[5587],{"type":418,"value":5588}," --query",{"type":413,"tag":448,"props":5590,"children":5591},{"style":461},[5592],{"type":418,"value":637},{"type":413,"tag":448,"props":5594,"children":5595},{"style":467},[5596],{"type":418,"value":5597},"[0].value",{"type":413,"tag":448,"props":5599,"children":5600},{"style":461},[5601],{"type":418,"value":647},{"type":413,"tag":414,"props":5603,"children":5604},{},[5605],{"type":418,"value":5606},"Using this command, we can now set the environment variables that will be used by the Pulumi CLI to access our Azure Blob Storage account backend:",{"type":413,"tag":437,"props":5608,"children":5610},{"className":1013,"code":5609,"language":248,"meta":401,"style":401},"$env:AZURE_STORAGE_KEY=$(az storage account keys list -n $saName -g $rgName -o tsv --query '[0].value')\n$env:AZURE_STORAGE_ACCOUNT=$saName\n",[5611],{"type":413,"tag":444,"props":5612,"children":5613},{"__ignoreMap":401},[5614,5705],{"type":413,"tag":448,"props":5615,"children":5616},{"class":450,"line":451},[5617,5621,5626,5630,5635,5639,5644,5648,5653,5657,5662,5666,5671,5675,5680,5684,5688,5693,5697,5701],{"type":413,"tag":448,"props":5618,"children":5619},{"style":461},[5620],{"type":418,"value":1026},{"type":413,"tag":448,"props":5622,"children":5623},{"style":1029},[5624],{"type":418,"value":5625},"env:AZURE_STORAGE_KEY",{"type":413,"tag":448,"props":5627,"children":5628},{"style":461},[5629],{"type":418,"value":1154},{"type":413,"tag":448,"props":5631,"children":5632},{"style":1029},[5633],{"type":418,"value":5634},"az storage account keys list ",{"type":413,"tag":448,"props":5636,"children":5637},{"style":461},[5638],{"type":418,"value":1173},{"type":413,"tag":448,"props":5640,"children":5641},{"style":1029},[5642],{"type":418,"value":5643},"n ",{"type":413,"tag":448,"props":5645,"children":5646},{"style":461},[5647],{"type":418,"value":1026},{"type":413,"tag":448,"props":5649,"children":5650},{"style":1029},[5651],{"type":418,"value":5652},"saName ",{"type":413,"tag":448,"props":5654,"children":5655},{"style":461},[5656],{"type":418,"value":1173},{"type":413,"tag":448,"props":5658,"children":5659},{"style":1029},[5660],{"type":418,"value":5661},"g ",{"type":413,"tag":448,"props":5663,"children":5664},{"style":461},[5665],{"type":418,"value":1026},{"type":413,"tag":448,"props":5667,"children":5668},{"style":1029},[5669],{"type":418,"value":5670},"rgName ",{"type":413,"tag":448,"props":5672,"children":5673},{"style":461},[5674],{"type":418,"value":1173},{"type":413,"tag":448,"props":5676,"children":5677},{"style":1029},[5678],{"type":418,"value":5679},"o tsv ",{"type":413,"tag":448,"props":5681,"children":5682},{"style":461},[5683],{"type":418,"value":1071},{"type":413,"tag":448,"props":5685,"children":5686},{"style":1029},[5687],{"type":418,"value":1276},{"type":413,"tag":448,"props":5689,"children":5690},{"style":461},[5691],{"type":418,"value":5692},"'",{"type":413,"tag":448,"props":5694,"children":5695},{"style":467},[5696],{"type":418,"value":5597},{"type":413,"tag":448,"props":5698,"children":5699},{"style":461},[5700],{"type":418,"value":5692},{"type":413,"tag":448,"props":5702,"children":5703},{"style":461},[5704],{"type":418,"value":1197},{"type":413,"tag":448,"props":5706,"children":5707},{"class":450,"line":473},[5708,5712,5717,5722],{"type":413,"tag":448,"props":5709,"children":5710},{"style":461},[5711],{"type":418,"value":1026},{"type":413,"tag":448,"props":5713,"children":5714},{"style":1029},[5715],{"type":418,"value":5716},"env:AZURE_STORAGE_ACCOUNT",{"type":413,"tag":448,"props":5718,"children":5719},{"style":461},[5720],{"type":418,"value":5721},"=$",{"type":413,"tag":448,"props":5723,"children":5724},{"style":1029},[5725],{"type":418,"value":5726},"saName\n",{"type":413,"tag":414,"props":5728,"children":5729},{},[5730],{"type":418,"value":5731},"And finally, we can create the blob container that will contain the infrastructure state:",{"type":413,"tag":437,"props":5733,"children":5735},{"className":937,"code":5734,"language":939,"meta":401,"style":401},"az storage container create -n iacstate\n",[5736],{"type":413,"tag":444,"props":5737,"children":5738},{"__ignoreMap":401},[5739],{"type":413,"tag":448,"props":5740,"children":5741},{"class":450,"line":451},[5742,5746,5750,5755,5759,5763],{"type":413,"tag":448,"props":5743,"children":5744},{"style":949},[5745],{"type":418,"value":4560},{"type":413,"tag":448,"props":5747,"children":5748},{"style":467},[5749],{"type":418,"value":5472},{"type":413,"tag":448,"props":5751,"children":5752},{"style":467},[5753],{"type":418,"value":5754}," container",{"type":413,"tag":448,"props":5756,"children":5757},{"style":467},[5758],{"type":418,"value":5440},{"type":413,"tag":448,"props":5760,"children":5761},{"style":467},[5762],{"type":418,"value":5445},{"type":413,"tag":448,"props":5764,"children":5765},{"style":467},[5766],{"type":418,"value":5767}," iacstate\n",{"type":413,"tag":866,"props":5769,"children":5771},{"id":5770},"how-to-provision-your-project-infrastructure-using-the-azure-blob-storage-backend",[5772],{"type":418,"value":5773},"How to provision your project infrastructure using the Azure Blob Storage backend?",{"type":413,"tag":414,"props":5775,"children":5776},{},[5777],{"type":418,"value":5778},"Now that our blob container exists, we can use the pulumi login command we already talked about to indicate pulumi to use the newly created azure blob storage as the backend.",{"type":413,"tag":437,"props":5780,"children":5782},{"className":1013,"code":5781,"language":248,"meta":401,"style":401},"pulumi login azblob://iacstate\n",[5783],{"type":413,"tag":444,"props":5784,"children":5785},{"__ignoreMap":401},[5786],{"type":413,"tag":448,"props":5787,"children":5788},{"class":450,"line":451},[5789,5794,5799],{"type":413,"tag":448,"props":5790,"children":5791},{"style":1029},[5792],{"type":418,"value":5793},"pulumi login azblob:",{"type":413,"tag":448,"props":5795,"children":5796},{"style":461},[5797],{"type":418,"value":5798},"//",{"type":413,"tag":448,"props":5800,"children":5801},{"style":1029},[5802],{"type":418,"value":5803},"iacstate\n",{"type":413,"tag":414,"props":5805,"children":5806},{},[5807,5809,5815,5817,5823],{"type":418,"value":5808},"To verify Pulumi can correctly provision cloud resources using our Azure Blob Storage backend, we can create a new Pulumi project using the ",{"type":413,"tag":444,"props":5810,"children":5812},{"className":5811},[],[5813],{"type":418,"value":5814},"azure-csharp",{"type":418,"value":5816}," template and deploy the infrastructure with the ",{"type":413,"tag":444,"props":5818,"children":5820},{"className":5819},[],[5821],{"type":418,"value":5822},"pulumi up",{"type":418,"value":5824}," command:",{"type":413,"tag":437,"props":5826,"children":5828},{"className":1013,"code":5827,"language":248,"meta":401,"style":401},"mkdir infra;cd infra;\npulumi new azure-csharp -n AzureStorageBackend -s dev -y\npulumi up -y\n",[5829],{"type":413,"tag":444,"props":5830,"children":5831},{"__ignoreMap":401},[5832,5855,5899],{"type":413,"tag":448,"props":5833,"children":5834},{"class":450,"line":451},[5835,5840,5845,5850],{"type":413,"tag":448,"props":5836,"children":5837},{"style":1029},[5838],{"type":418,"value":5839},"mkdir infra",{"type":413,"tag":448,"props":5841,"children":5842},{"style":461},[5843],{"type":418,"value":5844},";",{"type":413,"tag":448,"props":5846,"children":5847},{"style":1029},[5848],{"type":418,"value":5849},"cd infra",{"type":413,"tag":448,"props":5851,"children":5852},{"style":461},[5853],{"type":418,"value":5854},";\n",{"type":413,"tag":448,"props":5856,"children":5857},{"class":450,"line":473},[5858,5863,5867,5872,5876,5881,5885,5890,5894],{"type":413,"tag":448,"props":5859,"children":5860},{"style":1029},[5861],{"type":418,"value":5862},"pulumi new azure",{"type":413,"tag":448,"props":5864,"children":5865},{"style":461},[5866],{"type":418,"value":1173},{"type":413,"tag":448,"props":5868,"children":5869},{"style":1029},[5870],{"type":418,"value":5871},"csharp ",{"type":413,"tag":448,"props":5873,"children":5874},{"style":461},[5875],{"type":418,"value":1173},{"type":413,"tag":448,"props":5877,"children":5878},{"style":1029},[5879],{"type":418,"value":5880},"n AzureStorageBackend ",{"type":413,"tag":448,"props":5882,"children":5883},{"style":461},[5884],{"type":418,"value":1173},{"type":413,"tag":448,"props":5886,"children":5887},{"style":1029},[5888],{"type":418,"value":5889},"s dev ",{"type":413,"tag":448,"props":5891,"children":5892},{"style":461},[5893],{"type":418,"value":1173},{"type":413,"tag":448,"props":5895,"children":5896},{"style":1029},[5897],{"type":418,"value":5898},"y\n",{"type":413,"tag":448,"props":5900,"children":5901},{"class":450,"line":488},[5902,5907,5911],{"type":413,"tag":448,"props":5903,"children":5904},{"style":1029},[5905],{"type":418,"value":5906},"pulumi up ",{"type":413,"tag":448,"props":5908,"children":5909},{"style":461},[5910],{"type":418,"value":1173},{"type":413,"tag":448,"props":5912,"children":5913},{"style":1029},[5914],{"type":418,"value":5898},{"type":413,"tag":414,"props":5916,"children":5917},{},[5918],{"type":418,"value":5919},"When executing these commands, Pulumi will ask us to provide a passphrase. Why is that? It is to encrypt secrets contained in the infrastructure state. This way no secret is stored in plain text in the state.",{"type":413,"tag":414,"props":5921,"children":5922},{},[5923,5925,5930,5932,5938],{"type":418,"value":5924},"Once the ",{"type":413,"tag":444,"props":5926,"children":5928},{"className":5927},[],[5929],{"type":418,"value":5822},{"type":418,"value":5931}," command is finished, the infrastructure requested is provisioned, and we can see a new state file has been created in the ",{"type":413,"tag":444,"props":5933,"children":5935},{"className":5934},[],[5936],{"type":418,"value":5937},"iacstate",{"type":418,"value":5939}," blob container.",{"type":413,"tag":414,"props":5941,"children":5942},{},[5943],{"type":413,"tag":832,"props":5944,"children":5948},{"alt":5945,"className":5946,"src":5947},"Azure Blob container explorer showing the Pulumi state file.",[836,837],"/posts/images/pulumiazurebackend_azure_1.png",[],{"type":413,"tag":420,"props":5950,"children":5952},{"id":5951},"managing-state-sensitive-data",[5953],{"type":418,"value":5954},"Managing state sensitive data",{"type":413,"tag":866,"props":5956,"children":5958},{"id":5957},"why-is-it-needed-to-protect-sensitive-data-in-the-state",[5959],{"type":418,"value":5960},"Why is it needed to protect sensitive data in the state?",{"type":413,"tag":414,"props":5962,"children":5963},{},[5964],{"type":418,"value":5965},"The state is transmitted and stored securely by Pulumi and whatever the backend you use you should restrict its access. For instance, in our example, you should have assigned the permissions on the storage account so that only the right people have access to it. Nevertheless, securing the state file is not enough because it contains sensitive data (keys, connection strings, ...) that you probably don't want anyone that has access to the file to be able to get.",{"type":413,"tag":414,"props":5967,"children":5968},{},[5969],{"type":418,"value":5970},"Indeed, it's not because a developer needs to read the state file to debug an issue that you want him to be able to see some production sensitive data in plain text in the state.  Having secrets in plain text in a state file would be like putting secrets in your source control and telling it is safe because only developers of the project team have access to it. Moreover, even if an unauthorized person succeeds to get access to the state file, it won't be an issue if all secrets in it are encrypted. Hence that is very nice to see Pulumi take security seriously and always encrypt sensitive information.",{"type":413,"tag":866,"props":5972,"children":5974},{"id":5973},"what-are-the-available-encryption-providers",[5975],{"type":418,"value":5976},"What are the available encryption providers?",{"type":413,"tag":414,"props":5978,"children":5979},{},[5980],{"type":418,"value":5981},"As we have seen previously, when using a self-managed backend like Azure Blob Storage, by default Pulumi uses a passphrase to encrypt sensitive data.",{"type":413,"tag":414,"props":5983,"children":5984},{},[5985],{"type":418,"value":5986},"The passphrase is just one of the supported encryption/secrets providers but there are others:",{"type":413,"tag":5031,"props":5988,"children":5989},{},[5990,5995,5999,6004,6009],{"type":413,"tag":2159,"props":5991,"children":5992},{},[5993],{"type":418,"value":5994},"AWS Key Management Service",{"type":413,"tag":2159,"props":5996,"children":5997},{},[5998],{"type":418,"value":260},{"type":413,"tag":2159,"props":6000,"children":6001},{},[6002],{"type":418,"value":6003},"Google Cloud Key Management Service",{"type":413,"tag":2159,"props":6005,"children":6006},{},[6007],{"type":418,"value":6008},"HashiCorp Vault Transit Secrets Engine",{"type":413,"tag":2159,"props":6010,"children":6011},{},[6012],{"type":418,"value":6013},"Pulumi Service (used by default when using Pulumi Service as the backend)",{"type":413,"tag":414,"props":6015,"children":6016},{},[6017],{"type":418,"value":6018},"As for the backend, you don't have to use the default encryption provider and can come with your own resource. These providers can be used whatever the backend you chose, which lets you many possibilities. Now let's see how to use Azure Key Vault as our encryption provider.",{"type":413,"tag":866,"props":6020,"children":6022},{"id":6021},"how-to-use-azure-key-vault-as-the-encryption-provider",[6023],{"type":418,"value":6024},"How to use Azure Key Vault as the encryption provider?",{"type":413,"tag":414,"props":6026,"children":6027},{},[6028],{"type":418,"value":6029},"Let's first create a Key Vault:",{"type":413,"tag":437,"props":6031,"children":6033},{"className":1013,"code":6032,"language":248,"meta":401,"style":401},"$kvName=\"kv-iacstate-westeu-$random\"\n$vaultId=az keyvault create -g $rgName -n $kvName --enable-rbac-authorization true --query \"id\"\n",[6034],{"type":413,"tag":444,"props":6035,"children":6036},{"__ignoreMap":401},[6037,6074],{"type":413,"tag":448,"props":6038,"children":6039},{"class":450,"line":451},[6040,6044,6049,6053,6057,6062,6066,6070],{"type":413,"tag":448,"props":6041,"children":6042},{"style":461},[6043],{"type":418,"value":1026},{"type":413,"tag":448,"props":6045,"children":6046},{"style":1029},[6047],{"type":418,"value":6048},"kvName",{"type":413,"tag":448,"props":6050,"children":6051},{"style":461},[6052],{"type":418,"value":1037},{"type":413,"tag":448,"props":6054,"children":6055},{"style":461},[6056],{"type":418,"value":1183},{"type":413,"tag":448,"props":6058,"children":6059},{"style":467},[6060],{"type":418,"value":6061},"kv-iacstate-westeu-",{"type":413,"tag":448,"props":6063,"children":6064},{"style":461},[6065],{"type":418,"value":1026},{"type":413,"tag":448,"props":6067,"children":6068},{"style":1029},[6069],{"type":418,"value":5285},{"type":413,"tag":448,"props":6071,"children":6072},{"style":461},[6073],{"type":418,"value":1005},{"type":413,"tag":448,"props":6075,"children":6076},{"class":450,"line":473},[6077,6081,6086,6090,6095,6099,6103,6107,6111,6115,6119,6123,6128,6132,6137,6141,6146,6150,6154,6158,6162],{"type":413,"tag":448,"props":6078,"children":6079},{"style":461},[6080],{"type":418,"value":1026},{"type":413,"tag":448,"props":6082,"children":6083},{"style":1029},[6084],{"type":418,"value":6085},"vaultId",{"type":413,"tag":448,"props":6087,"children":6088},{"style":461},[6089],{"type":418,"value":1037},{"type":413,"tag":448,"props":6091,"children":6092},{"style":1029},[6093],{"type":418,"value":6094},"az keyvault create ",{"type":413,"tag":448,"props":6096,"children":6097},{"style":461},[6098],{"type":418,"value":1173},{"type":413,"tag":448,"props":6100,"children":6101},{"style":1029},[6102],{"type":418,"value":5661},{"type":413,"tag":448,"props":6104,"children":6105},{"style":461},[6106],{"type":418,"value":1026},{"type":413,"tag":448,"props":6108,"children":6109},{"style":1029},[6110],{"type":418,"value":5670},{"type":413,"tag":448,"props":6112,"children":6113},{"style":461},[6114],{"type":418,"value":1173},{"type":413,"tag":448,"props":6116,"children":6117},{"style":1029},[6118],{"type":418,"value":5643},{"type":413,"tag":448,"props":6120,"children":6121},{"style":461},[6122],{"type":418,"value":1026},{"type":413,"tag":448,"props":6124,"children":6125},{"style":1029},[6126],{"type":418,"value":6127},"kvName ",{"type":413,"tag":448,"props":6129,"children":6130},{"style":461},[6131],{"type":418,"value":1071},{"type":413,"tag":448,"props":6133,"children":6134},{"style":2000},[6135],{"type":418,"value":6136},"enable-rbac",{"type":413,"tag":448,"props":6138,"children":6139},{"style":461},[6140],{"type":418,"value":1173},{"type":413,"tag":448,"props":6142,"children":6143},{"style":1029},[6144],{"type":418,"value":6145},"authorization true ",{"type":413,"tag":448,"props":6147,"children":6148},{"style":461},[6149],{"type":418,"value":1071},{"type":413,"tag":448,"props":6151,"children":6152},{"style":1029},[6153],{"type":418,"value":1276},{"type":413,"tag":448,"props":6155,"children":6156},{"style":461},[6157],{"type":418,"value":1183},{"type":413,"tag":448,"props":6159,"children":6160},{"style":467},[6161],{"type":418,"value":1285},{"type":413,"tag":448,"props":6163,"children":6164},{"style":461},[6165],{"type":418,"value":1005},{"type":413,"tag":414,"props":6167,"children":6168},{},[6169,6171,6177],{"type":418,"value":6170},"We retrieve its id so that we can use it to assign the correct role to my user to be able to perform cryptographic operations. With the ",{"type":413,"tag":444,"props":6172,"children":6174},{"className":6173},[],[6175],{"type":418,"value":6176},"--enable-rbac-authorization",{"type":418,"value":6178}," parameter we set the permissions model on the key vault to Role-Based Access Control but you can use the classic Vault access policies as well. I prefer using RBAC because I think it's more modern and more consistent with how we manage permissions on other Azure resources.",{"type":413,"tag":414,"props":6180,"children":6181},{},[6182],{"type":418,"value":6183},"To assign the appropriate permission to the current logged-in user, we will need its current identifier in Azure that we can retrieve with the following command:",{"type":413,"tag":437,"props":6185,"children":6187},{"className":1013,"code":6186,"language":248,"meta":401,"style":401},"$myUserId=az ad signed-in-user show --query \"objectId\" -o tsv \n",[6188],{"type":413,"tag":444,"props":6189,"children":6190},{"__ignoreMap":401},[6191],{"type":413,"tag":448,"props":6192,"children":6193},{"class":450,"line":451},[6194,6198,6203,6207,6212,6216,6221,6225,6230,6234,6238,6242,6247,6251,6255],{"type":413,"tag":448,"props":6195,"children":6196},{"style":461},[6197],{"type":418,"value":1026},{"type":413,"tag":448,"props":6199,"children":6200},{"style":1029},[6201],{"type":418,"value":6202},"myUserId",{"type":413,"tag":448,"props":6204,"children":6205},{"style":461},[6206],{"type":418,"value":1037},{"type":413,"tag":448,"props":6208,"children":6209},{"style":1029},[6210],{"type":418,"value":6211},"az ad signed",{"type":413,"tag":448,"props":6213,"children":6214},{"style":461},[6215],{"type":418,"value":1173},{"type":413,"tag":448,"props":6217,"children":6218},{"style":1029},[6219],{"type":418,"value":6220},"in",{"type":413,"tag":448,"props":6222,"children":6223},{"style":461},[6224],{"type":418,"value":1173},{"type":413,"tag":448,"props":6226,"children":6227},{"style":1029},[6228],{"type":418,"value":6229},"user show ",{"type":413,"tag":448,"props":6231,"children":6232},{"style":461},[6233],{"type":418,"value":1071},{"type":413,"tag":448,"props":6235,"children":6236},{"style":1029},[6237],{"type":418,"value":1276},{"type":413,"tag":448,"props":6239,"children":6240},{"style":461},[6241],{"type":418,"value":1183},{"type":413,"tag":448,"props":6243,"children":6244},{"style":467},[6245],{"type":418,"value":6246},"objectId",{"type":413,"tag":448,"props":6248,"children":6249},{"style":461},[6250],{"type":418,"value":1183},{"type":413,"tag":448,"props":6252,"children":6253},{"style":461},[6254],{"type":418,"value":1294},{"type":413,"tag":448,"props":6256,"children":6257},{"style":1029},[6258],{"type":418,"value":6259},"o tsv\n",{"type":413,"tag":414,"props":6261,"children":6262},{},[6263,6265,6271],{"type":418,"value":6264},"We can then assign to this user the ",{"type":413,"tag":444,"props":6266,"children":6268},{"className":6267},[],[6269],{"type":418,"value":6270},"Key Vault Crypto Officer",{"type":418,"value":6272}," role that will allow us to create a key and encrypt/decrypt data.",{"type":413,"tag":437,"props":6274,"children":6276},{"className":1013,"code":6275,"language":248,"meta":401,"style":401},"az role assignment create --scope $vaultId --role \"Key Vault Crypto Officer\" --assignee $myUserId \n",[6277],{"type":413,"tag":444,"props":6278,"children":6279},{"__ignoreMap":401},[6280],{"type":413,"tag":448,"props":6281,"children":6282},{"class":450,"line":451},[6283,6287,6291,6295,6299,6304,6308,6313,6317,6321,6325,6329,6334,6338],{"type":413,"tag":448,"props":6284,"children":6285},{"style":1029},[6286],{"type":418,"value":1584},{"type":413,"tag":448,"props":6288,"children":6289},{"style":461},[6290],{"type":418,"value":1071},{"type":413,"tag":448,"props":6292,"children":6293},{"style":1029},[6294],{"type":418,"value":1682},{"type":413,"tag":448,"props":6296,"children":6297},{"style":461},[6298],{"type":418,"value":1026},{"type":413,"tag":448,"props":6300,"children":6301},{"style":1029},[6302],{"type":418,"value":6303},"vaultId ",{"type":413,"tag":448,"props":6305,"children":6306},{"style":461},[6307],{"type":418,"value":1071},{"type":413,"tag":448,"props":6309,"children":6310},{"style":1029},[6311],{"type":418,"value":6312},"role ",{"type":413,"tag":448,"props":6314,"children":6315},{"style":461},[6316],{"type":418,"value":1183},{"type":413,"tag":448,"props":6318,"children":6319},{"style":467},[6320],{"type":418,"value":6270},{"type":413,"tag":448,"props":6322,"children":6323},{"style":461},[6324],{"type":418,"value":1183},{"type":413,"tag":448,"props":6326,"children":6327},{"style":461},[6328],{"type":418,"value":1095},{"type":413,"tag":448,"props":6330,"children":6331},{"style":1029},[6332],{"type":418,"value":6333},"assignee ",{"type":413,"tag":448,"props":6335,"children":6336},{"style":461},[6337],{"type":418,"value":1026},{"type":413,"tag":448,"props":6339,"children":6340},{"style":1029},[6341],{"type":418,"value":6342},"myUserId\n",{"type":413,"tag":414,"props":6344,"children":6345},{},[6346],{"type":418,"value":6347},"The key to encrypt/decrypt data can be created with the following command:",{"type":413,"tag":437,"props":6349,"children":6351},{"className":1013,"code":6350,"language":248,"meta":401,"style":401},"az keyvault key create -n encryptionState --vault-name $kvName\n",[6352],{"type":413,"tag":444,"props":6353,"children":6354},{"__ignoreMap":401},[6355],{"type":413,"tag":448,"props":6356,"children":6357},{"class":450,"line":451},[6358,6363,6367,6372,6376,6381,6385,6389,6393],{"type":413,"tag":448,"props":6359,"children":6360},{"style":1029},[6361],{"type":418,"value":6362},"az keyvault key create ",{"type":413,"tag":448,"props":6364,"children":6365},{"style":461},[6366],{"type":418,"value":1173},{"type":413,"tag":448,"props":6368,"children":6369},{"style":1029},[6370],{"type":418,"value":6371},"n encryptionState ",{"type":413,"tag":448,"props":6373,"children":6374},{"style":461},[6375],{"type":418,"value":1071},{"type":413,"tag":448,"props":6377,"children":6378},{"style":1029},[6379],{"type":418,"value":6380},"vault",{"type":413,"tag":448,"props":6382,"children":6383},{"style":461},[6384],{"type":418,"value":1173},{"type":413,"tag":448,"props":6386,"children":6387},{"style":1029},[6388],{"type":418,"value":1438},{"type":413,"tag":448,"props":6390,"children":6391},{"style":461},[6392],{"type":418,"value":1026},{"type":413,"tag":448,"props":6394,"children":6395},{"style":1029},[6396],{"type":418,"value":6397},"kvName\n",{"type":413,"tag":414,"props":6399,"children":6400},{},[6401],{"type":418,"value":6402},"By default, Pulumi CLI will try to use environment variables to authenticate to the key vault, so we need to tell it to use the Azure CLI instead as we gave the permission on the key vault to the user currently logged in:",{"type":413,"tag":437,"props":6404,"children":6406},{"className":1013,"code":6405,"language":248,"meta":401,"style":401},"$env:AZURE_KEYVAULT_AUTH_VIA_CLI=\"true\"\n",[6407],{"type":413,"tag":444,"props":6408,"children":6409},{"__ignoreMap":401},[6410],{"type":413,"tag":448,"props":6411,"children":6412},{"class":450,"line":451},[6413,6417,6422,6426,6430,6435],{"type":413,"tag":448,"props":6414,"children":6415},{"style":461},[6416],{"type":418,"value":1026},{"type":413,"tag":448,"props":6418,"children":6419},{"style":1029},[6420],{"type":418,"value":6421},"env:AZURE_KEYVAULT_AUTH_VIA_CLI",{"type":413,"tag":448,"props":6423,"children":6424},{"style":461},[6425],{"type":418,"value":1037},{"type":413,"tag":448,"props":6427,"children":6428},{"style":461},[6429],{"type":418,"value":1183},{"type":413,"tag":448,"props":6431,"children":6432},{"style":467},[6433],{"type":418,"value":6434},"true",{"type":413,"tag":448,"props":6436,"children":6437},{"style":461},[6438],{"type":418,"value":1005},{"type":413,"tag":414,"props":6440,"children":6441},{},[6442],{"type":418,"value":6443},"Now that everything is configured, we can modify our previous command to create a new Pulumi project by specifying the encryption provider to use:",{"type":413,"tag":437,"props":6445,"children":6447},{"className":1013,"code":6446,"language":248,"meta":401,"style":401},"pulumi new azure-csharp -n AzureStorageBackend -s dev -y --secrets-provider=\"azurekeyvault://$kvName.vault.azure.net/keys/encryptionState\"\n",[6448],{"type":413,"tag":444,"props":6449,"children":6450},{"__ignoreMap":401},[6451],{"type":413,"tag":448,"props":6452,"children":6453},{"class":450,"line":451},[6454,6458,6462,6466,6470,6474,6478,6482,6486,6491,6495,6500,6504,6509,6513,6517,6522,6526,6530,6535],{"type":413,"tag":448,"props":6455,"children":6456},{"style":1029},[6457],{"type":418,"value":5862},{"type":413,"tag":448,"props":6459,"children":6460},{"style":461},[6461],{"type":418,"value":1173},{"type":413,"tag":448,"props":6463,"children":6464},{"style":1029},[6465],{"type":418,"value":5871},{"type":413,"tag":448,"props":6467,"children":6468},{"style":461},[6469],{"type":418,"value":1173},{"type":413,"tag":448,"props":6471,"children":6472},{"style":1029},[6473],{"type":418,"value":5880},{"type":413,"tag":448,"props":6475,"children":6476},{"style":461},[6477],{"type":418,"value":1173},{"type":413,"tag":448,"props":6479,"children":6480},{"style":1029},[6481],{"type":418,"value":5889},{"type":413,"tag":448,"props":6483,"children":6484},{"style":461},[6485],{"type":418,"value":1173},{"type":413,"tag":448,"props":6487,"children":6488},{"style":1029},[6489],{"type":418,"value":6490},"y ",{"type":413,"tag":448,"props":6492,"children":6493},{"style":461},[6494],{"type":418,"value":1071},{"type":413,"tag":448,"props":6496,"children":6497},{"style":1029},[6498],{"type":418,"value":6499},"secrets",{"type":413,"tag":448,"props":6501,"children":6502},{"style":461},[6503],{"type":418,"value":1173},{"type":413,"tag":448,"props":6505,"children":6506},{"style":1029},[6507],{"type":418,"value":6508},"provider",{"type":413,"tag":448,"props":6510,"children":6511},{"style":461},[6512],{"type":418,"value":1037},{"type":413,"tag":448,"props":6514,"children":6515},{"style":461},[6516],{"type":418,"value":1183},{"type":413,"tag":448,"props":6518,"children":6519},{"style":467},[6520],{"type":418,"value":6521},"azurekeyvault://",{"type":413,"tag":448,"props":6523,"children":6524},{"style":461},[6525],{"type":418,"value":1026},{"type":413,"tag":448,"props":6527,"children":6528},{"style":1029},[6529],{"type":418,"value":6048},{"type":413,"tag":448,"props":6531,"children":6532},{"style":467},[6533],{"type":418,"value":6534},".vault.azure.net/keys/encryptionState",{"type":413,"tag":448,"props":6536,"children":6537},{"style":461},[6538],{"type":418,"value":1005},{"type":413,"tag":420,"props":6540,"children":6542},{"id":6541},"comparing-with-how-terraform-handle-state",[6543],{"type":418,"value":6544},"Comparing with how Terraform handle state",{"type":413,"tag":414,"props":6546,"children":6547},{},[6548],{"type":418,"value":6549},"Terraform is another very popular Infrastructure as Code platform with lots of similarities so I thought it might be interesting to look at how Terraform handles state compared to Pulumi.",{"type":413,"tag":414,"props":6551,"children":6552},{},[6553],{"type":418,"value":6554},"Terraform has a SaaS platform called Terraform Cloud that can be used to manage the infrastructure state. It is similar to what Pulumi Service offers. However, when using Terraform the default backend is not Terraform Cloud but local filesystem. That is not better or worse, just a different choice HashiCorp (the company behind Terraform) did. Although I must say that when I started working on Pulumi, I found it easier not having to take care of where the state is stored and how it is managed, so maybe a SaaS backend by default is simpler.",{"type":413,"tag":414,"props":6556,"children":6557},{},[6558,6560,6567],{"type":418,"value":6559},"On Microsoft documentation, there is a tutorial ",{"type":413,"tag":813,"props":6561,"children":6564},{"href":6562,"rel":6563},"https://docs.microsoft.com/en-us/azure/developer/terraform/store-state-in-azure-storage",[817],[6565],{"type":418,"value":6566},"\"Store Terraform state in Azure Storage\"",{"type":418,"value":6568}," that shows how to use Terraform with an Azure Storage backend. I have done it and it is very similar to what we have done in this article with Pulumi. Instead of using a CLI command to configure the infrastructure to use Azure Blob Storage as the backend for the state, in Terraform, you configure it directly in one of the code files but the idea is the same. Both IaC tools store the infrastructure state in a JSON file in a blob container.",{"type":413,"tag":414,"props":6570,"children":6571},{},[6572,6574,6581,6583,6589],{"type":418,"value":6573},"One big difference however is that by default Terraform does not encrypt sensitive information in the state file. As far as I know, there is no concept of secret providers in Terraform so no built-in solution. ",{"type":413,"tag":813,"props":6575,"children":6578},{"href":6576,"rel":6577},"https://www.terraform.io/docs/language/state/sensitive-data.html",[817],[6579],{"type":418,"value":6580},"Terraform documentation",{"type":418,"value":6582}," just says to ",{"type":413,"tag":444,"props":6584,"children":6586},{"className":6585},[],[6587],{"type":418,"value":6588},"treat the state itself as sensitive data",{"type":418,"value":6590},". That means when I created a storage account using Terraform with the Azure Blob Storage backend, the keys of my storage were available in plain text in my state file (as you can see in the image below).",{"type":413,"tag":414,"props":6592,"children":6593},{},[6594],{"type":413,"tag":832,"props":6595,"children":6599},{"alt":6596,"className":6597,"src":6598},"Terraform state file containing clear text sensitive information in vscode.",[836,837],"/posts/images/pulumiazurebackend_tf_1.png",[],{"type":413,"tag":414,"props":6601,"children":6602},{},[6603],{"type":418,"value":6604},"You should not have this kind of security issue using Terraform Cloud and there are probably external tools to avoid this, but I think an IaC platform should be secure by default and that encryption of sensitive data should be built-in.",{"type":413,"tag":420,"props":6606,"children":6608},{"id":6607},"to-conclude",[6609],{"type":418,"value":6610},"To conclude",{"type":413,"tag":414,"props":6612,"children":6613},{},[6614],{"type":418,"value":6615},"You can find below the complete Azure CLI script used in this article:",{"type":413,"tag":437,"props":6617,"children":6619},{"className":1013,"code":6618,"language":248,"meta":401,"style":401},"# PowerShell variables used in the script \n$random=Get-Random -Maximum 1000\n$location=\"West Europe\"\n$rgName=\"rg-iacstate-westeu-$random\"\n$saName=\"stiacstate$random\"\n$kvName=\"kv-iacstate-westeu-$random\"\n\naz group create -n $rgName -l $location\n\n# Configure the Azure Blob Storage that will contain the state \naz storage account create -g $rgName -n $saName -l $location --sku Standard_LRS\n# Set environment variables needed to write on the storage account\n$env:AZURE_STORAGE_KEY=$(az storage account keys list -n $saName -g $rgName -o tsv --query '[0].value')\n$env:AZURE_STORAGE_ACCOUNT=$saName\naz storage container create -n iacstate\n\n# Configure the Key Vault that will be used to encrypt the sensitive data\n$vaultId=az keyvault create -g $rgName -n $kvName --enable-rbac-authorization true --query \"id\"\n$myUserId=az ad signed-in-user show --query \"objectId\" -o tsv \naz role assignment create --scope $vaultId --role \"Key Vault Crypto Officer\" --assignee $myUserId \naz keyvault key create -n encryptionState --vault-name $kvName\n# Use az cli to authenticate to key vault instead of using environment variables \n$env:AZURE_KEYVAULT_AUTH_VIA_CLI=\"true\"\n\n# Indicate pulumi to use the newly created azure blob storage as a backend\npulumi login azblob://iacstate\n# Create and use a folder to store the infrastructure code\nmkdir infra;cd infra;\n# Create a new Pulumi project using the azure blob storage as the backend and the keyvault as the encryption provider \npulumi new azure-csharp -n AzureStorageBackend -s dev -y --secrets-provider=\"azurekeyvault://$kvName.vault.azure.net/keys/encryptionState\"\n# Deploy the infrastructure\npulumi up -y\n",[6620],{"type":413,"tag":444,"props":6621,"children":6622},{"__ignoreMap":401},[6623,6631,6662,6689,6724,6759,6794,6801,6843,6850,6858,6924,6932,7015,7034,7051,7058,7066,7153,7217,7277,7316,7324,7351,7358,7366,7381,7389,7408,7416,7499,7507],{"type":413,"tag":448,"props":6624,"children":6625},{"class":450,"line":451},[6626],{"type":413,"tag":448,"props":6627,"children":6628},{"style":2393},[6629],{"type":418,"value":6630},"# PowerShell variables used in the script \n",{"type":413,"tag":448,"props":6632,"children":6633},{"class":450,"line":473},[6634,6638,6642,6646,6650,6654,6658],{"type":413,"tag":448,"props":6635,"children":6636},{"style":461},[6637],{"type":418,"value":1026},{"type":413,"tag":448,"props":6639,"children":6640},{"style":1029},[6641],{"type":418,"value":5285},{"type":413,"tag":448,"props":6643,"children":6644},{"style":461},[6645],{"type":418,"value":1037},{"type":413,"tag":448,"props":6647,"children":6648},{"style":2000},[6649],{"type":418,"value":5294},{"type":413,"tag":448,"props":6651,"children":6652},{"style":461},[6653],{"type":418,"value":1294},{"type":413,"tag":448,"props":6655,"children":6656},{"style":1029},[6657],{"type":418,"value":5303},{"type":413,"tag":448,"props":6659,"children":6660},{"style":1733},[6661],{"type":418,"value":5308},{"type":413,"tag":448,"props":6663,"children":6664},{"class":450,"line":488},[6665,6669,6673,6677,6681,6685],{"type":413,"tag":448,"props":6666,"children":6667},{"style":461},[6668],{"type":418,"value":1026},{"type":413,"tag":448,"props":6670,"children":6671},{"style":1029},[6672],{"type":418,"value":5320},{"type":413,"tag":448,"props":6674,"children":6675},{"style":461},[6676],{"type":418,"value":1037},{"type":413,"tag":448,"props":6678,"children":6679},{"style":461},[6680],{"type":418,"value":1183},{"type":413,"tag":448,"props":6682,"children":6683},{"style":467},[6684],{"type":418,"value":5333},{"type":413,"tag":448,"props":6686,"children":6687},{"style":461},[6688],{"type":418,"value":1005},{"type":413,"tag":448,"props":6690,"children":6691},{"class":450,"line":501},[6692,6696,6700,6704,6708,6712,6716,6720],{"type":413,"tag":448,"props":6693,"children":6694},{"style":461},[6695],{"type":418,"value":1026},{"type":413,"tag":448,"props":6697,"children":6698},{"style":1029},[6699],{"type":418,"value":5349},{"type":413,"tag":448,"props":6701,"children":6702},{"style":461},[6703],{"type":418,"value":1037},{"type":413,"tag":448,"props":6705,"children":6706},{"style":461},[6707],{"type":418,"value":1183},{"type":413,"tag":448,"props":6709,"children":6710},{"style":467},[6711],{"type":418,"value":5362},{"type":413,"tag":448,"props":6713,"children":6714},{"style":461},[6715],{"type":418,"value":1026},{"type":413,"tag":448,"props":6717,"children":6718},{"style":1029},[6719],{"type":418,"value":5285},{"type":413,"tag":448,"props":6721,"children":6722},{"style":461},[6723],{"type":418,"value":1005},{"type":413,"tag":448,"props":6725,"children":6726},{"class":450,"line":511},[6727,6731,6735,6739,6743,6747,6751,6755],{"type":413,"tag":448,"props":6728,"children":6729},{"style":461},[6730],{"type":418,"value":1026},{"type":413,"tag":448,"props":6732,"children":6733},{"style":1029},[6734],{"type":418,"value":5386},{"type":413,"tag":448,"props":6736,"children":6737},{"style":461},[6738],{"type":418,"value":1037},{"type":413,"tag":448,"props":6740,"children":6741},{"style":461},[6742],{"type":418,"value":1183},{"type":413,"tag":448,"props":6744,"children":6745},{"style":467},[6746],{"type":418,"value":5399},{"type":413,"tag":448,"props":6748,"children":6749},{"style":461},[6750],{"type":418,"value":1026},{"type":413,"tag":448,"props":6752,"children":6753},{"style":1029},[6754],{"type":418,"value":5285},{"type":413,"tag":448,"props":6756,"children":6757},{"style":461},[6758],{"type":418,"value":1005},{"type":413,"tag":448,"props":6760,"children":6761},{"class":450,"line":524},[6762,6766,6770,6774,6778,6782,6786,6790],{"type":413,"tag":448,"props":6763,"children":6764},{"style":461},[6765],{"type":418,"value":1026},{"type":413,"tag":448,"props":6767,"children":6768},{"style":1029},[6769],{"type":418,"value":6048},{"type":413,"tag":448,"props":6771,"children":6772},{"style":461},[6773],{"type":418,"value":1037},{"type":413,"tag":448,"props":6775,"children":6776},{"style":461},[6777],{"type":418,"value":1183},{"type":413,"tag":448,"props":6779,"children":6780},{"style":467},[6781],{"type":418,"value":6061},{"type":413,"tag":448,"props":6783,"children":6784},{"style":461},[6785],{"type":418,"value":1026},{"type":413,"tag":448,"props":6787,"children":6788},{"style":1029},[6789],{"type":418,"value":5285},{"type":413,"tag":448,"props":6791,"children":6792},{"style":461},[6793],{"type":418,"value":1005},{"type":413,"tag":448,"props":6795,"children":6796},{"class":450,"line":542},[6797],{"type":413,"tag":448,"props":6798,"children":6799},{"emptyLinePlaceholder":505},[6800],{"type":418,"value":508},{"type":413,"tag":448,"props":6802,"children":6803},{"class":450,"line":560},[6804,6809,6813,6817,6821,6825,6829,6834,6838],{"type":413,"tag":448,"props":6805,"children":6806},{"style":1029},[6807],{"type":418,"value":6808},"az group create ",{"type":413,"tag":448,"props":6810,"children":6811},{"style":461},[6812],{"type":418,"value":1173},{"type":413,"tag":448,"props":6814,"children":6815},{"style":1029},[6816],{"type":418,"value":5643},{"type":413,"tag":448,"props":6818,"children":6819},{"style":461},[6820],{"type":418,"value":1026},{"type":413,"tag":448,"props":6822,"children":6823},{"style":1029},[6824],{"type":418,"value":5670},{"type":413,"tag":448,"props":6826,"children":6827},{"style":461},[6828],{"type":418,"value":1173},{"type":413,"tag":448,"props":6830,"children":6831},{"style":1029},[6832],{"type":418,"value":6833},"l ",{"type":413,"tag":448,"props":6835,"children":6836},{"style":461},[6837],{"type":418,"value":1026},{"type":413,"tag":448,"props":6839,"children":6840},{"style":1029},[6841],{"type":418,"value":6842},"location\n",{"type":413,"tag":448,"props":6844,"children":6845},{"class":450,"line":573},[6846],{"type":413,"tag":448,"props":6847,"children":6848},{"emptyLinePlaceholder":505},[6849],{"type":418,"value":508},{"type":413,"tag":448,"props":6851,"children":6852},{"class":450,"line":586},[6853],{"type":413,"tag":448,"props":6854,"children":6855},{"style":2393},[6856],{"type":418,"value":6857},"# Configure the Azure Blob Storage that will contain the state \n",{"type":413,"tag":448,"props":6859,"children":6860},{"class":450,"line":604},[6861,6866,6870,6874,6878,6882,6886,6890,6894,6898,6902,6906,6910,6915,6919],{"type":413,"tag":448,"props":6862,"children":6863},{"style":1029},[6864],{"type":418,"value":6865},"az storage account create ",{"type":413,"tag":448,"props":6867,"children":6868},{"style":461},[6869],{"type":418,"value":1173},{"type":413,"tag":448,"props":6871,"children":6872},{"style":1029},[6873],{"type":418,"value":5661},{"type":413,"tag":448,"props":6875,"children":6876},{"style":461},[6877],{"type":418,"value":1026},{"type":413,"tag":448,"props":6879,"children":6880},{"style":1029},[6881],{"type":418,"value":5670},{"type":413,"tag":448,"props":6883,"children":6884},{"style":461},[6885],{"type":418,"value":1173},{"type":413,"tag":448,"props":6887,"children":6888},{"style":1029},[6889],{"type":418,"value":5643},{"type":413,"tag":448,"props":6891,"children":6892},{"style":461},[6893],{"type":418,"value":1026},{"type":413,"tag":448,"props":6895,"children":6896},{"style":1029},[6897],{"type":418,"value":5652},{"type":413,"tag":448,"props":6899,"children":6900},{"style":461},[6901],{"type":418,"value":1173},{"type":413,"tag":448,"props":6903,"children":6904},{"style":1029},[6905],{"type":418,"value":6833},{"type":413,"tag":448,"props":6907,"children":6908},{"style":461},[6909],{"type":418,"value":1026},{"type":413,"tag":448,"props":6911,"children":6912},{"style":1029},[6913],{"type":418,"value":6914},"location ",{"type":413,"tag":448,"props":6916,"children":6917},{"style":461},[6918],{"type":418,"value":1071},{"type":413,"tag":448,"props":6920,"children":6921},{"style":1029},[6922],{"type":418,"value":6923},"sku Standard_LRS\n",{"type":413,"tag":448,"props":6925,"children":6926},{"class":450,"line":617},[6927],{"type":413,"tag":448,"props":6928,"children":6929},{"style":2393},[6930],{"type":418,"value":6931},"# Set environment variables needed to write on the storage account\n",{"type":413,"tag":448,"props":6933,"children":6934},{"class":450,"line":650},[6935,6939,6943,6947,6951,6955,6959,6963,6967,6971,6975,6979,6983,6987,6991,6995,6999,7003,7007,7011],{"type":413,"tag":448,"props":6936,"children":6937},{"style":461},[6938],{"type":418,"value":1026},{"type":413,"tag":448,"props":6940,"children":6941},{"style":1029},[6942],{"type":418,"value":5625},{"type":413,"tag":448,"props":6944,"children":6945},{"style":461},[6946],{"type":418,"value":1154},{"type":413,"tag":448,"props":6948,"children":6949},{"style":1029},[6950],{"type":418,"value":5634},{"type":413,"tag":448,"props":6952,"children":6953},{"style":461},[6954],{"type":418,"value":1173},{"type":413,"tag":448,"props":6956,"children":6957},{"style":1029},[6958],{"type":418,"value":5643},{"type":413,"tag":448,"props":6960,"children":6961},{"style":461},[6962],{"type":418,"value":1026},{"type":413,"tag":448,"props":6964,"children":6965},{"style":1029},[6966],{"type":418,"value":5652},{"type":413,"tag":448,"props":6968,"children":6969},{"style":461},[6970],{"type":418,"value":1173},{"type":413,"tag":448,"props":6972,"children":6973},{"style":1029},[6974],{"type":418,"value":5661},{"type":413,"tag":448,"props":6976,"children":6977},{"style":461},[6978],{"type":418,"value":1026},{"type":413,"tag":448,"props":6980,"children":6981},{"style":1029},[6982],{"type":418,"value":5670},{"type":413,"tag":448,"props":6984,"children":6985},{"style":461},[6986],{"type":418,"value":1173},{"type":413,"tag":448,"props":6988,"children":6989},{"style":1029},[6990],{"type":418,"value":5679},{"type":413,"tag":448,"props":6992,"children":6993},{"style":461},[6994],{"type":418,"value":1071},{"type":413,"tag":448,"props":6996,"children":6997},{"style":1029},[6998],{"type":418,"value":1276},{"type":413,"tag":448,"props":7000,"children":7001},{"style":461},[7002],{"type":418,"value":5692},{"type":413,"tag":448,"props":7004,"children":7005},{"style":467},[7006],{"type":418,"value":5597},{"type":413,"tag":448,"props":7008,"children":7009},{"style":461},[7010],{"type":418,"value":5692},{"type":413,"tag":448,"props":7012,"children":7013},{"style":461},[7014],{"type":418,"value":1197},{"type":413,"tag":448,"props":7016,"children":7017},{"class":450,"line":668},[7018,7022,7026,7030],{"type":413,"tag":448,"props":7019,"children":7020},{"style":461},[7021],{"type":418,"value":1026},{"type":413,"tag":448,"props":7023,"children":7024},{"style":1029},[7025],{"type":418,"value":5716},{"type":413,"tag":448,"props":7027,"children":7028},{"style":461},[7029],{"type":418,"value":5721},{"type":413,"tag":448,"props":7031,"children":7032},{"style":1029},[7033],{"type":418,"value":5726},{"type":413,"tag":448,"props":7035,"children":7036},{"class":450,"line":681},[7037,7042,7046],{"type":413,"tag":448,"props":7038,"children":7039},{"style":1029},[7040],{"type":418,"value":7041},"az storage container create ",{"type":413,"tag":448,"props":7043,"children":7044},{"style":461},[7045],{"type":418,"value":1173},{"type":413,"tag":448,"props":7047,"children":7048},{"style":1029},[7049],{"type":418,"value":7050},"n iacstate\n",{"type":413,"tag":448,"props":7052,"children":7053},{"class":450,"line":699},[7054],{"type":413,"tag":448,"props":7055,"children":7056},{"emptyLinePlaceholder":505},[7057],{"type":418,"value":508},{"type":413,"tag":448,"props":7059,"children":7060},{"class":450,"line":717},[7061],{"type":413,"tag":448,"props":7062,"children":7063},{"style":2393},[7064],{"type":418,"value":7065},"# Configure the Key Vault that will be used to encrypt the sensitive data\n",{"type":413,"tag":448,"props":7067,"children":7068},{"class":450,"line":735},[7069,7073,7077,7081,7085,7089,7093,7097,7101,7105,7109,7113,7117,7121,7125,7129,7133,7137,7141,7145,7149],{"type":413,"tag":448,"props":7070,"children":7071},{"style":461},[7072],{"type":418,"value":1026},{"type":413,"tag":448,"props":7074,"children":7075},{"style":1029},[7076],{"type":418,"value":6085},{"type":413,"tag":448,"props":7078,"children":7079},{"style":461},[7080],{"type":418,"value":1037},{"type":413,"tag":448,"props":7082,"children":7083},{"style":1029},[7084],{"type":418,"value":6094},{"type":413,"tag":448,"props":7086,"children":7087},{"style":461},[7088],{"type":418,"value":1173},{"type":413,"tag":448,"props":7090,"children":7091},{"style":1029},[7092],{"type":418,"value":5661},{"type":413,"tag":448,"props":7094,"children":7095},{"style":461},[7096],{"type":418,"value":1026},{"type":413,"tag":448,"props":7098,"children":7099},{"style":1029},[7100],{"type":418,"value":5670},{"type":413,"tag":448,"props":7102,"children":7103},{"style":461},[7104],{"type":418,"value":1173},{"type":413,"tag":448,"props":7106,"children":7107},{"style":1029},[7108],{"type":418,"value":5643},{"type":413,"tag":448,"props":7110,"children":7111},{"style":461},[7112],{"type":418,"value":1026},{"type":413,"tag":448,"props":7114,"children":7115},{"style":1029},[7116],{"type":418,"value":6127},{"type":413,"tag":448,"props":7118,"children":7119},{"style":461},[7120],{"type":418,"value":1071},{"type":413,"tag":448,"props":7122,"children":7123},{"style":2000},[7124],{"type":418,"value":6136},{"type":413,"tag":448,"props":7126,"children":7127},{"style":461},[7128],{"type":418,"value":1173},{"type":413,"tag":448,"props":7130,"children":7131},{"style":1029},[7132],{"type":418,"value":6145},{"type":413,"tag":448,"props":7134,"children":7135},{"style":461},[7136],{"type":418,"value":1071},{"type":413,"tag":448,"props":7138,"children":7139},{"style":1029},[7140],{"type":418,"value":1276},{"type":413,"tag":448,"props":7142,"children":7143},{"style":461},[7144],{"type":418,"value":1183},{"type":413,"tag":448,"props":7146,"children":7147},{"style":467},[7148],{"type":418,"value":1285},{"type":413,"tag":448,"props":7150,"children":7151},{"style":461},[7152],{"type":418,"value":1005},{"type":413,"tag":448,"props":7154,"children":7155},{"class":450,"line":743},[7156,7160,7164,7168,7172,7176,7180,7184,7188,7192,7196,7200,7204,7208,7212],{"type":413,"tag":448,"props":7157,"children":7158},{"style":461},[7159],{"type":418,"value":1026},{"type":413,"tag":448,"props":7161,"children":7162},{"style":1029},[7163],{"type":418,"value":6202},{"type":413,"tag":448,"props":7165,"children":7166},{"style":461},[7167],{"type":418,"value":1037},{"type":413,"tag":448,"props":7169,"children":7170},{"style":1029},[7171],{"type":418,"value":6211},{"type":413,"tag":448,"props":7173,"children":7174},{"style":461},[7175],{"type":418,"value":1173},{"type":413,"tag":448,"props":7177,"children":7178},{"style":1029},[7179],{"type":418,"value":6220},{"type":413,"tag":448,"props":7181,"children":7182},{"style":461},[7183],{"type":418,"value":1173},{"type":413,"tag":448,"props":7185,"children":7186},{"style":1029},[7187],{"type":418,"value":6229},{"type":413,"tag":448,"props":7189,"children":7190},{"style":461},[7191],{"type":418,"value":1071},{"type":413,"tag":448,"props":7193,"children":7194},{"style":1029},[7195],{"type":418,"value":1276},{"type":413,"tag":448,"props":7197,"children":7198},{"style":461},[7199],{"type":418,"value":1183},{"type":413,"tag":448,"props":7201,"children":7202},{"style":467},[7203],{"type":418,"value":6246},{"type":413,"tag":448,"props":7205,"children":7206},{"style":461},[7207],{"type":418,"value":1183},{"type":413,"tag":448,"props":7209,"children":7210},{"style":461},[7211],{"type":418,"value":1294},{"type":413,"tag":448,"props":7213,"children":7214},{"style":1029},[7215],{"type":418,"value":7216},"o tsv \n",{"type":413,"tag":448,"props":7218,"children":7219},{"class":450,"line":772},[7220,7224,7228,7232,7236,7240,7244,7248,7252,7256,7260,7264,7268,7272],{"type":413,"tag":448,"props":7221,"children":7222},{"style":1029},[7223],{"type":418,"value":1584},{"type":413,"tag":448,"props":7225,"children":7226},{"style":461},[7227],{"type":418,"value":1071},{"type":413,"tag":448,"props":7229,"children":7230},{"style":1029},[7231],{"type":418,"value":1682},{"type":413,"tag":448,"props":7233,"children":7234},{"style":461},[7235],{"type":418,"value":1026},{"type":413,"tag":448,"props":7237,"children":7238},{"style":1029},[7239],{"type":418,"value":6303},{"type":413,"tag":448,"props":7241,"children":7242},{"style":461},[7243],{"type":418,"value":1071},{"type":413,"tag":448,"props":7245,"children":7246},{"style":1029},[7247],{"type":418,"value":6312},{"type":413,"tag":448,"props":7249,"children":7250},{"style":461},[7251],{"type":418,"value":1183},{"type":413,"tag":448,"props":7253,"children":7254},{"style":467},[7255],{"type":418,"value":6270},{"type":413,"tag":448,"props":7257,"children":7258},{"style":461},[7259],{"type":418,"value":1183},{"type":413,"tag":448,"props":7261,"children":7262},{"style":461},[7263],{"type":418,"value":1095},{"type":413,"tag":448,"props":7265,"children":7266},{"style":1029},[7267],{"type":418,"value":6333},{"type":413,"tag":448,"props":7269,"children":7270},{"style":461},[7271],{"type":418,"value":1026},{"type":413,"tag":448,"props":7273,"children":7274},{"style":1029},[7275],{"type":418,"value":7276},"myUserId \n",{"type":413,"tag":448,"props":7278,"children":7279},{"class":450,"line":791},[7280,7284,7288,7292,7296,7300,7304,7308,7312],{"type":413,"tag":448,"props":7281,"children":7282},{"style":1029},[7283],{"type":418,"value":6362},{"type":413,"tag":448,"props":7285,"children":7286},{"style":461},[7287],{"type":418,"value":1173},{"type":413,"tag":448,"props":7289,"children":7290},{"style":1029},[7291],{"type":418,"value":6371},{"type":413,"tag":448,"props":7293,"children":7294},{"style":461},[7295],{"type":418,"value":1071},{"type":413,"tag":448,"props":7297,"children":7298},{"style":1029},[7299],{"type":418,"value":6380},{"type":413,"tag":448,"props":7301,"children":7302},{"style":461},[7303],{"type":418,"value":1173},{"type":413,"tag":448,"props":7305,"children":7306},{"style":1029},[7307],{"type":418,"value":1438},{"type":413,"tag":448,"props":7309,"children":7310},{"style":461},[7311],{"type":418,"value":1026},{"type":413,"tag":448,"props":7313,"children":7314},{"style":1029},[7315],{"type":418,"value":6397},{"type":413,"tag":448,"props":7317,"children":7318},{"class":450,"line":800},[7319],{"type":413,"tag":448,"props":7320,"children":7321},{"style":2393},[7322],{"type":418,"value":7323},"# Use az cli to authenticate to key vault instead of using environment variables \n",{"type":413,"tag":448,"props":7325,"children":7326},{"class":450,"line":2909},[7327,7331,7335,7339,7343,7347],{"type":413,"tag":448,"props":7328,"children":7329},{"style":461},[7330],{"type":418,"value":1026},{"type":413,"tag":448,"props":7332,"children":7333},{"style":1029},[7334],{"type":418,"value":6421},{"type":413,"tag":448,"props":7336,"children":7337},{"style":461},[7338],{"type":418,"value":1037},{"type":413,"tag":448,"props":7340,"children":7341},{"style":461},[7342],{"type":418,"value":1183},{"type":413,"tag":448,"props":7344,"children":7345},{"style":467},[7346],{"type":418,"value":6434},{"type":413,"tag":448,"props":7348,"children":7349},{"style":461},[7350],{"type":418,"value":1005},{"type":413,"tag":448,"props":7352,"children":7353},{"class":450,"line":3021},[7354],{"type":413,"tag":448,"props":7355,"children":7356},{"emptyLinePlaceholder":505},[7357],{"type":418,"value":508},{"type":413,"tag":448,"props":7359,"children":7360},{"class":450,"line":3029},[7361],{"type":413,"tag":448,"props":7362,"children":7363},{"style":2393},[7364],{"type":418,"value":7365},"# Indicate pulumi to use the newly created azure blob storage as a backend\n",{"type":413,"tag":448,"props":7367,"children":7368},{"class":450,"line":3038},[7369,7373,7377],{"type":413,"tag":448,"props":7370,"children":7371},{"style":1029},[7372],{"type":418,"value":5793},{"type":413,"tag":448,"props":7374,"children":7375},{"style":461},[7376],{"type":418,"value":5798},{"type":413,"tag":448,"props":7378,"children":7379},{"style":1029},[7380],{"type":418,"value":5803},{"type":413,"tag":448,"props":7382,"children":7383},{"class":450,"line":3062},[7384],{"type":413,"tag":448,"props":7385,"children":7386},{"style":2393},[7387],{"type":418,"value":7388},"# Create and use a folder to store the infrastructure code\n",{"type":413,"tag":448,"props":7390,"children":7391},{"class":450,"line":3086},[7392,7396,7400,7404],{"type":413,"tag":448,"props":7393,"children":7394},{"style":1029},[7395],{"type":418,"value":5839},{"type":413,"tag":448,"props":7397,"children":7398},{"style":461},[7399],{"type":418,"value":5844},{"type":413,"tag":448,"props":7401,"children":7402},{"style":1029},[7403],{"type":418,"value":5849},{"type":413,"tag":448,"props":7405,"children":7406},{"style":461},[7407],{"type":418,"value":5854},{"type":413,"tag":448,"props":7409,"children":7410},{"class":450,"line":3110},[7411],{"type":413,"tag":448,"props":7412,"children":7413},{"style":2393},[7414],{"type":418,"value":7415},"# Create a new Pulumi project using the azure blob storage as the backend and the keyvault as the encryption provider \n",{"type":413,"tag":448,"props":7417,"children":7418},{"class":450,"line":3150},[7419,7423,7427,7431,7435,7439,7443,7447,7451,7455,7459,7463,7467,7471,7475,7479,7483,7487,7491,7495],{"type":413,"tag":448,"props":7420,"children":7421},{"style":1029},[7422],{"type":418,"value":5862},{"type":413,"tag":448,"props":7424,"children":7425},{"style":461},[7426],{"type":418,"value":1173},{"type":413,"tag":448,"props":7428,"children":7429},{"style":1029},[7430],{"type":418,"value":5871},{"type":413,"tag":448,"props":7432,"children":7433},{"style":461},[7434],{"type":418,"value":1173},{"type":413,"tag":448,"props":7436,"children":7437},{"style":1029},[7438],{"type":418,"value":5880},{"type":413,"tag":448,"props":7440,"children":7441},{"style":461},[7442],{"type":418,"value":1173},{"type":413,"tag":448,"props":7444,"children":7445},{"style":1029},[7446],{"type":418,"value":5889},{"type":413,"tag":448,"props":7448,"children":7449},{"style":461},[7450],{"type":418,"value":1173},{"type":413,"tag":448,"props":7452,"children":7453},{"style":1029},[7454],{"type":418,"value":6490},{"type":413,"tag":448,"props":7456,"children":7457},{"style":461},[7458],{"type":418,"value":1071},{"type":413,"tag":448,"props":7460,"children":7461},{"style":1029},[7462],{"type":418,"value":6499},{"type":413,"tag":448,"props":7464,"children":7465},{"style":461},[7466],{"type":418,"value":1173},{"type":413,"tag":448,"props":7468,"children":7469},{"style":1029},[7470],{"type":418,"value":6508},{"type":413,"tag":448,"props":7472,"children":7473},{"style":461},[7474],{"type":418,"value":1037},{"type":413,"tag":448,"props":7476,"children":7477},{"style":461},[7478],{"type":418,"value":1183},{"type":413,"tag":448,"props":7480,"children":7481},{"style":467},[7482],{"type":418,"value":6521},{"type":413,"tag":448,"props":7484,"children":7485},{"style":461},[7486],{"type":418,"value":1026},{"type":413,"tag":448,"props":7488,"children":7489},{"style":1029},[7490],{"type":418,"value":6048},{"type":413,"tag":448,"props":7492,"children":7493},{"style":467},[7494],{"type":418,"value":6534},{"type":413,"tag":448,"props":7496,"children":7497},{"style":461},[7498],{"type":418,"value":1005},{"type":413,"tag":448,"props":7500,"children":7501},{"class":450,"line":3182},[7502],{"type":413,"tag":448,"props":7503,"children":7504},{"style":2393},[7505],{"type":418,"value":7506},"# Deploy the infrastructure\n",{"type":413,"tag":448,"props":7508,"children":7509},{"class":450,"line":3202},[7510,7514,7518],{"type":413,"tag":448,"props":7511,"children":7512},{"style":1029},[7513],{"type":418,"value":5906},{"type":413,"tag":448,"props":7515,"children":7516},{"style":461},[7517],{"type":418,"value":1173},{"type":413,"tag":448,"props":7519,"children":7520},{"style":1029},[7521],{"type":418,"value":5898},{"type":413,"tag":414,"props":7523,"children":7524},{},[7525],{"type":418,"value":7526},"Using Pulumi without Pulumi Service was not complicated as I thought it would be. I like the fact that Pulumi is not limited to being used with Pulumi Service backend and secret provider. It gives us the choice to use what we want: if I want to use Google Cloud Storage as my back-end and AWS Key Management Service as my encryption provider I totally can. Many options are available and well integrated without requiring much work which is nice.",{"type":413,"tag":414,"props":7528,"children":7529},{},[7530,7532,7538],{"type":418,"value":7531},"Yet honestly, I think that using Pulumi Service will be my default choice because of the many built-in features it offers (deployment history, concurrent state locking, collaboration functionalities, ...). It's free for individuals so I would not bother with a self-managed backend for individuals. For teams and companies, you have to pay (even if there is a monthly free grant of credits for the team plan) but I don't have enough perspective to say if it's worth it. You can find the pricing ",{"type":413,"tag":813,"props":7533,"children":7536},{"href":7534,"rel":7535},"https://www.pulumi.com/pricing/",[817],[7537],{"type":418,"value":1386},{"type":418,"value":7539}," if you want to see it by yourself. I guess the choice between that and a self-managed backend will probably depend more on the project and the organization you are working for.",{"type":413,"tag":3710,"props":7541,"children":7542},{},[7543],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":7545},[7546,7550,7555,7560,7561],{"id":5015,"depth":473,"text":5018,"children":7547},[7548,7549],{"id":5021,"depth":488,"text":5024},{"id":5101,"depth":488,"text":5104},{"id":5145,"depth":473,"text":5148,"children":7551},[7552,7553,7554],{"id":5151,"depth":488,"text":5154},{"id":5213,"depth":488,"text":5216},{"id":5770,"depth":488,"text":5773},{"id":5951,"depth":473,"text":5954,"children":7556},[7557,7558,7559],{"id":5957,"depth":488,"text":5960},{"id":5973,"depth":488,"text":5976},{"id":6021,"depth":488,"text":6024},{"id":6541,"depth":473,"text":6544},{"id":6607,"depth":473,"text":6610},"content:1.posts:30.pulumi-azure-backend.md","1.posts/30.pulumi-azure-backend.md",{"_path":67,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":66,"description":7565,"lead":7566,"date":7567,"image":7568,"badge":7570,"tags":7572,"body":7573,"_type":3726,"_id":9975,"_source":3728,"_file":9976,"_extension":3730},"In Microsoft.Data.SqlClient v3.0.0, a new authentication mode Active Directory Default has been released. Let's see what this means when querying an Azure SQL Database from some C# code.","Talking about Active Directory Default authentication mode for SqlClient.","2021-06-22T00:00:00.000Z",{"src":7569},"/images/cloud-azure_1.jpg",{"label":7571},"Development",[252,299,302,228,225,236],{"type":410,"children":7574,"toc":9964},[7575,7596,7619,7624,7630,7650,7781,7792,7797,7820,7825,7831,7836,7841,7854,7866,8071,8110,8115,8128,8162,8241,8256,8262,8267,8273,8287,9257,9262,9297,9302,9316,9322,9336,9349,9853,9858,9918,9927,9943,9947,9960],{"type":413,"tag":414,"props":7576,"children":7577},{},[7578,7580,7586,7588,7594],{"type":418,"value":7579},"In ",{"type":413,"tag":444,"props":7581,"children":7583},{"className":7582},[],[7584],{"type":418,"value":7585},"Microsoft.Data.SqlClient",{"type":418,"value":7587}," v3.0.0, a new authentication mode ",{"type":413,"tag":444,"props":7589,"children":7591},{"className":7590},[],[7592],{"type":418,"value":7593},"Active Directory Default",{"type":418,"value":7595}," has been released. Let's see what this means when querying an Azure SQL Database from some C# code.",{"type":413,"tag":841,"props":7597,"children":7598},{"icon":843},[7599],{"type":413,"tag":414,"props":7600,"children":7601},{},[7602,7604,7609,7611,7617],{"type":418,"value":7603},"If you do not have heard about ",{"type":413,"tag":444,"props":7605,"children":7607},{"className":7606},[],[7608],{"type":418,"value":7585},{"type":418,"value":7610},", it is the new data provider for Microsoft SQL Server and Azure SQL Database which supports both .NET Framework and .NET Core and replace the old ",{"type":413,"tag":444,"props":7612,"children":7614},{"className":7613},[],[7615],{"type":418,"value":7616},"System.Data.SqlClient",{"type":418,"value":7618}," components.",{"type":413,"tag":414,"props":7620,"children":7621},{},[7622],{"type":418,"value":7623},"But first, let's talk about how we used to do that before.",{"type":413,"tag":420,"props":7625,"children":7627},{"id":7626},"the-traditional-way-using-a-secret-connection-string",[7628],{"type":418,"value":7629},"The traditional way: using a secret connection string",{"type":413,"tag":414,"props":7631,"children":7632},{},[7633,7634,7640,7642,7648],{"type":418,"value":1930},{"type":413,"tag":444,"props":7635,"children":7637},{"className":7636},[],[7638],{"type":418,"value":7639},"traditional way",{"type":418,"value":7641}," to connect to an Azure SQL database from an application in C# is to provide to the ",{"type":413,"tag":444,"props":7643,"children":7645},{"className":7644},[],[7646],{"type":418,"value":7647},"SqlConnection",{"type":418,"value":7649}," constructor a connection string that contains a username and a password. The corresponding C# code is quite simple:",{"type":413,"tag":437,"props":7651,"children":7654},{"className":7652,"code":7653,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","var connectionString = \"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;User ID=globalSqlAdmin;Password=MySecretPassword;\");\n\nusing (var sqlConnection = new SqlConnection(connectionString));\nawait connection.OpenAsync();\n",[7655],{"type":413,"tag":444,"props":7656,"children":7657},{"__ignoreMap":401},[7658,7697,7704,7754],{"type":413,"tag":448,"props":7659,"children":7660},{"class":450,"line":451},[7661,7666,7671,7676,7680,7685,7689,7693],{"type":413,"tag":448,"props":7662,"children":7663},{"style":949},[7664],{"type":418,"value":7665},"var",{"type":413,"tag":448,"props":7667,"children":7668},{"style":949},[7669],{"type":418,"value":7670}," connectionString",{"type":413,"tag":448,"props":7672,"children":7673},{"style":461},[7674],{"type":418,"value":7675}," =",{"type":413,"tag":448,"props":7677,"children":7678},{"style":461},[7679],{"type":418,"value":995},{"type":413,"tag":448,"props":7681,"children":7682},{"style":467},[7683],{"type":418,"value":7684},"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;User ID=globalSqlAdmin;Password=MySecretPassword;",{"type":413,"tag":448,"props":7686,"children":7687},{"style":461},[7688],{"type":418,"value":1183},{"type":413,"tag":448,"props":7690,"children":7691},{"style":1029},[7692],{"type":418,"value":2031},{"type":413,"tag":448,"props":7694,"children":7695},{"style":461},[7696],{"type":418,"value":5854},{"type":413,"tag":448,"props":7698,"children":7699},{"class":450,"line":473},[7700],{"type":413,"tag":448,"props":7701,"children":7702},{"emptyLinePlaceholder":505},[7703],{"type":418,"value":508},{"type":413,"tag":448,"props":7705,"children":7706},{"class":450,"line":488},[7707,7712,7717,7721,7726,7730,7735,7740,7744,7749],{"type":413,"tag":448,"props":7708,"children":7709},{"style":785},[7710],{"type":418,"value":7711},"using",{"type":413,"tag":448,"props":7713,"children":7714},{"style":461},[7715],{"type":418,"value":7716}," (",{"type":413,"tag":448,"props":7718,"children":7719},{"style":949},[7720],{"type":418,"value":7665},{"type":413,"tag":448,"props":7722,"children":7723},{"style":949},[7724],{"type":418,"value":7725}," sqlConnection",{"type":413,"tag":448,"props":7727,"children":7728},{"style":461},[7729],{"type":418,"value":7675},{"type":413,"tag":448,"props":7731,"children":7732},{"style":461},[7733],{"type":418,"value":7734}," new",{"type":413,"tag":448,"props":7736,"children":7737},{"style":949},[7738],{"type":418,"value":7739}," SqlConnection",{"type":413,"tag":448,"props":7741,"children":7742},{"style":461},[7743],{"type":418,"value":2041},{"type":413,"tag":448,"props":7745,"children":7746},{"style":1029},[7747],{"type":418,"value":7748},"connectionString",{"type":413,"tag":448,"props":7750,"children":7751},{"style":461},[7752],{"type":418,"value":7753},"));\n",{"type":413,"tag":448,"props":7755,"children":7756},{"class":450,"line":501},[7757,7762,7767,7771,7776],{"type":413,"tag":448,"props":7758,"children":7759},{"style":461},[7760],{"type":418,"value":7761},"await",{"type":413,"tag":448,"props":7763,"children":7764},{"style":1029},[7765],{"type":418,"value":7766}," connection",{"type":413,"tag":448,"props":7768,"children":7769},{"style":461},[7770],{"type":418,"value":898},{"type":413,"tag":448,"props":7772,"children":7773},{"style":2000},[7774],{"type":418,"value":7775},"OpenAsync",{"type":413,"tag":448,"props":7777,"children":7778},{"style":461},[7779],{"type":418,"value":7780},"();\n",{"type":413,"tag":414,"props":7782,"children":7783},{},[7784,7786,7791],{"type":418,"value":7785},"In that case, the connection string is a secret we must secure and not just by putting it in some configuration location everyone can have access to, but by storing it in a secured place like ",{"type":413,"tag":444,"props":7787,"children":7789},{"className":7788},[],[7790],{"type":418,"value":260},{"type":418,"value":898},{"type":413,"tag":414,"props":7793,"children":7794},{},[7795],{"type":418,"value":7796},"However, even if you secure it appropriately, using a connection string with a username/password in it has some disadvantages:",{"type":413,"tag":5031,"props":7798,"children":7799},{},[7800,7805,7810,7815],{"type":413,"tag":2159,"props":7801,"children":7802},{},[7803],{"type":418,"value":7804},"you need to handle who has access to it (so who has access to the key vault)",{"type":413,"tag":2159,"props":7806,"children":7807},{},[7808],{"type":418,"value":7809},"every application or every developer could potentially use the same connection string so auditing is not very convenient (for instance identifying in the database logs which user has run a specific transaction)",{"type":413,"tag":2159,"props":7811,"children":7812},{},[7813],{"type":418,"value":7814},"you only control who has access to the connection string in the key vault, not what people do with it (share it by email, store it on their local computer, ...) so not who can access the database",{"type":413,"tag":2159,"props":7816,"children":7817},{},[7818],{"type":418,"value":7819},"you need to handle the rotation of the secret, in other words, change the username/password regularly (because you can revoke the access to someone to the database, if he had access to the connection string at some point in time it is not a secret for him anymore)",{"type":413,"tag":414,"props":7821,"children":7822},{},[7823],{"type":418,"value":7824},"For all these reasons, using a secret connection string to connect to an Azure SQL Database is not the right approach.",{"type":413,"tag":420,"props":7826,"children":7828},{"id":7827},"the-new-way-using-azure-active-directory-authentication",[7829],{"type":418,"value":7830},"The new way: using Azure Active Directory Authentication",{"type":413,"tag":414,"props":7832,"children":7833},{},[7834],{"type":418,"value":7835},"Instead of using a secret connection string to connect to a database, the idea is to use the Azure Active Directory authentication mechanism. Azure Active Directory is the location that contains all the identities of your users and your applications in your company. So you can manage directly which identity (user or application) have access to a database.",{"type":413,"tag":414,"props":7837,"children":7838},{},[7839],{"type":418,"value":7840},"Applications or users that want to query a database will authenticate against Azure AD to retrieve an access token that will allow them to access the database using a connection string without any username nor password.",{"type":413,"tag":414,"props":7842,"children":7843},{},[7844,7846,7853],{"type":418,"value":7845},"If you want to know more about the advantages of using Azure AD authentication for connecting to an Azure SQL Database you can have a look in the ",{"type":413,"tag":813,"props":7847,"children":7850},{"href":7848,"rel":7849},"https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-overview",[817],[7851],{"type":418,"value":7852},"official documentation",{"type":418,"value":898},{"type":413,"tag":414,"props":7855,"children":7856},{},[7857,7859,7864],{"type":418,"value":7858},"In the code we can remove the user id and password from the connection string but we have to retrieve an Azure AD access token and pass it to the ",{"type":413,"tag":444,"props":7860,"children":7862},{"className":7861},[],[7863],{"type":418,"value":7647},{"type":418,"value":7865}," instance:",{"type":413,"tag":437,"props":7867,"children":7869},{"className":7652,"code":7868,"language":326,"meta":401,"style":401},"var accessToken = await new DefaultAzureCredential().GetTokenAsync(new TokenRequestContext(new string[] { \"https://database.windows.net//.default\" }));\nusing var connection = new SqlConnection(\"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;\")\n{\n    AccessToken = accessToken.Token\n};\nawait connection.OpenAsync();\n",[7870],{"type":413,"tag":444,"props":7871,"children":7872},{"__ignoreMap":401},[7873,7959,8008,8015,8040,8048],{"type":413,"tag":448,"props":7874,"children":7875},{"class":450,"line":451},[7876,7880,7885,7889,7894,7898,7903,7908,7913,7918,7923,7927,7932,7937,7941,7945,7950,7954],{"type":413,"tag":448,"props":7877,"children":7878},{"style":949},[7879],{"type":418,"value":7665},{"type":413,"tag":448,"props":7881,"children":7882},{"style":949},[7883],{"type":418,"value":7884}," accessToken",{"type":413,"tag":448,"props":7886,"children":7887},{"style":461},[7888],{"type":418,"value":7675},{"type":413,"tag":448,"props":7890,"children":7891},{"style":461},[7892],{"type":418,"value":7893}," await",{"type":413,"tag":448,"props":7895,"children":7896},{"style":461},[7897],{"type":418,"value":7734},{"type":413,"tag":448,"props":7899,"children":7900},{"style":949},[7901],{"type":418,"value":7902}," DefaultAzureCredential",{"type":413,"tag":448,"props":7904,"children":7905},{"style":461},[7906],{"type":418,"value":7907},"().",{"type":413,"tag":448,"props":7909,"children":7910},{"style":2000},[7911],{"type":418,"value":7912},"GetTokenAsync",{"type":413,"tag":448,"props":7914,"children":7915},{"style":461},[7916],{"type":418,"value":7917},"(new",{"type":413,"tag":448,"props":7919,"children":7920},{"style":949},[7921],{"type":418,"value":7922}," TokenRequestContext",{"type":413,"tag":448,"props":7924,"children":7925},{"style":461},[7926],{"type":418,"value":7917},{"type":413,"tag":448,"props":7928,"children":7929},{"style":461},[7930],{"type":418,"value":7931}," string",{"type":413,"tag":448,"props":7933,"children":7934},{"style":461},[7935],{"type":418,"value":7936},"[]",{"type":413,"tag":448,"props":7938,"children":7939},{"style":461},[7940],{"type":418,"value":4542},{"type":413,"tag":448,"props":7942,"children":7943},{"style":461},[7944],{"type":418,"value":995},{"type":413,"tag":448,"props":7946,"children":7947},{"style":467},[7948],{"type":418,"value":7949},"https://database.windows.net//.default",{"type":413,"tag":448,"props":7951,"children":7952},{"style":461},[7953],{"type":418,"value":1183},{"type":413,"tag":448,"props":7955,"children":7956},{"style":461},[7957],{"type":418,"value":7958}," }));\n",{"type":413,"tag":448,"props":7960,"children":7961},{"class":450,"line":473},[7962,7966,7971,7975,7979,7983,7987,7991,7995,8000,8004],{"type":413,"tag":448,"props":7963,"children":7964},{"style":785},[7965],{"type":418,"value":7711},{"type":413,"tag":448,"props":7967,"children":7968},{"style":949},[7969],{"type":418,"value":7970}," var",{"type":413,"tag":448,"props":7972,"children":7973},{"style":949},[7974],{"type":418,"value":7766},{"type":413,"tag":448,"props":7976,"children":7977},{"style":461},[7978],{"type":418,"value":7675},{"type":413,"tag":448,"props":7980,"children":7981},{"style":461},[7982],{"type":418,"value":7734},{"type":413,"tag":448,"props":7984,"children":7985},{"style":949},[7986],{"type":418,"value":7739},{"type":413,"tag":448,"props":7988,"children":7989},{"style":461},[7990],{"type":418,"value":2041},{"type":413,"tag":448,"props":7992,"children":7993},{"style":461},[7994],{"type":418,"value":1183},{"type":413,"tag":448,"props":7996,"children":7997},{"style":467},[7998],{"type":418,"value":7999},"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;",{"type":413,"tag":448,"props":8001,"children":8002},{"style":461},[8003],{"type":418,"value":1183},{"type":413,"tag":448,"props":8005,"children":8006},{"style":461},[8007],{"type":418,"value":1197},{"type":413,"tag":448,"props":8009,"children":8010},{"class":450,"line":488},[8011],{"type":413,"tag":448,"props":8012,"children":8013},{"style":461},[8014],{"type":418,"value":1741},{"type":413,"tag":448,"props":8016,"children":8017},{"class":450,"line":501},[8018,8023,8027,8031,8035],{"type":413,"tag":448,"props":8019,"children":8020},{"style":1029},[8021],{"type":418,"value":8022},"    AccessToken ",{"type":413,"tag":448,"props":8024,"children":8025},{"style":461},[8026],{"type":418,"value":1037},{"type":413,"tag":448,"props":8028,"children":8029},{"style":1029},[8030],{"type":418,"value":7884},{"type":413,"tag":448,"props":8032,"children":8033},{"style":461},[8034],{"type":418,"value":898},{"type":413,"tag":448,"props":8036,"children":8037},{"style":1029},[8038],{"type":418,"value":8039},"Token\n",{"type":413,"tag":448,"props":8041,"children":8042},{"class":450,"line":511},[8043],{"type":413,"tag":448,"props":8044,"children":8045},{"style":461},[8046],{"type":418,"value":8047},"};\n",{"type":413,"tag":448,"props":8049,"children":8050},{"class":450,"line":524},[8051,8055,8059,8063,8067],{"type":413,"tag":448,"props":8052,"children":8053},{"style":461},[8054],{"type":418,"value":7761},{"type":413,"tag":448,"props":8056,"children":8057},{"style":1029},[8058],{"type":418,"value":7766},{"type":413,"tag":448,"props":8060,"children":8061},{"style":461},[8062],{"type":418,"value":898},{"type":413,"tag":448,"props":8064,"children":8065},{"style":2000},[8066],{"type":418,"value":7775},{"type":413,"tag":448,"props":8068,"children":8069},{"style":461},[8070],{"type":418,"value":7780},{"type":413,"tag":414,"props":8072,"children":8073},{},[8074,8076,8083,8085,8091,8093,8100,8102,8108],{"type":418,"value":8075},"The code is using the ",{"type":413,"tag":813,"props":8077,"children":8080},{"href":8078,"rel":8079},"https://docs.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme",[817],[8081],{"type":418,"value":8082},"Azure Identity library",{"type":418,"value":8084}," which as the documentation says \"",{"type":413,"tag":8086,"props":8087,"children":8088},"em",{},[8089],{"type":418,"value":8090},"provides Azure Active Directory token authentication support across the Azure SDK",{"type":418,"value":8092},"\". It is the recommended way to get an Azure token although you may have seen code that uses another library ",{"type":413,"tag":813,"props":8094,"children":8097},{"href":8095,"rel":8096},"https://www.nuget.org/packages/Microsoft.Azure.Services.AppAuthentication",[817],[8098],{"type":418,"value":8099},"Microsoft.Azure.Services.AppAuthentication",{"type":418,"value":8101}," to do the same thing. The class ",{"type":413,"tag":444,"props":8103,"children":8105},{"className":8104},[],[8106],{"type":418,"value":8107},"DefaultAzureCredential",{"type":418,"value":8109}," from Azure Identity library combines multiple authentication mechanisms (like Managed Identities, Visual Studio, Azure CLI ...) that will be tried in order to retrieve a token so it is a practical class that can handle most of the scenarios.",{"type":413,"tag":414,"props":8111,"children":8112},{},[8113],{"type":418,"value":8114},"Therefore, provided that you have granted access to your database to the user you are using locally (in Visual Studio, in vs code, or in Azure CLI) and to the managed identity of your application in Azure (App Service or Azure Function for instance) the same code will work both locally and in Azure.",{"type":413,"tag":420,"props":8116,"children":8118},{"id":8117},"here-comes-active-directory-default-authentication-mode",[8119,8121,8126],{"type":418,"value":8120},"Here comes ",{"type":413,"tag":444,"props":8122,"children":8124},{"className":8123},[],[8125],{"type":418,"value":7593},{"type":418,"value":8127}," authentication mode",{"type":413,"tag":414,"props":8129,"children":8130},{},[8131,8133,8138,8140,8145,8147,8153,8155,8160],{"type":418,"value":8132},"We have seen that using Azure Active Directory Authentication was a better solution than using a connection string with secrets in it to connect to a database. However, it involves manually retrieving an Azure AD token which makes the code a bit more complex to read. That is exactly why ",{"type":413,"tag":444,"props":8134,"children":8136},{"className":8135},[],[8137],{"type":418,"value":7593},{"type":418,"value":8139}," new authentication mode was introduced in ",{"type":413,"tag":444,"props":8141,"children":8143},{"className":8142},[],[8144],{"type":418,"value":7585},{"type":418,"value":8146}," v3.0.0. Under the hood, ",{"type":413,"tag":444,"props":8148,"children":8150},{"className":8149},[],[8151],{"type":418,"value":8152},"SqlClient",{"type":418,"value":8154}," does the same thing that we were showing previously so we don't have to do it ourselves: just specifying the authentication mode to ",{"type":413,"tag":444,"props":8156,"children":8158},{"className":8157},[],[8159],{"type":418,"value":7593},{"type":418,"value":8161}," in the connection string is enough to make it work.",{"type":413,"tag":437,"props":8163,"children":8165},{"className":7652,"code":8164,"language":326,"meta":401,"style":401},"using var connection = new SqlConnection(\"Server=server-testingmsi6499.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi6499;\");\nawait connection.OpenAsync();\n",[8166],{"type":413,"tag":444,"props":8167,"children":8168},{"__ignoreMap":401},[8169,8218],{"type":413,"tag":448,"props":8170,"children":8171},{"class":450,"line":451},[8172,8176,8180,8184,8188,8192,8196,8200,8204,8209,8213],{"type":413,"tag":448,"props":8173,"children":8174},{"style":785},[8175],{"type":418,"value":7711},{"type":413,"tag":448,"props":8177,"children":8178},{"style":949},[8179],{"type":418,"value":7970},{"type":413,"tag":448,"props":8181,"children":8182},{"style":949},[8183],{"type":418,"value":7766},{"type":413,"tag":448,"props":8185,"children":8186},{"style":461},[8187],{"type":418,"value":7675},{"type":413,"tag":448,"props":8189,"children":8190},{"style":461},[8191],{"type":418,"value":7734},{"type":413,"tag":448,"props":8193,"children":8194},{"style":949},[8195],{"type":418,"value":7739},{"type":413,"tag":448,"props":8197,"children":8198},{"style":461},[8199],{"type":418,"value":2041},{"type":413,"tag":448,"props":8201,"children":8202},{"style":461},[8203],{"type":418,"value":1183},{"type":413,"tag":448,"props":8205,"children":8206},{"style":467},[8207],{"type":418,"value":8208},"Server=server-testingmsi6499.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi6499;",{"type":413,"tag":448,"props":8210,"children":8211},{"style":461},[8212],{"type":418,"value":1183},{"type":413,"tag":448,"props":8214,"children":8215},{"style":461},[8216],{"type":418,"value":8217},");\n",{"type":413,"tag":448,"props":8219,"children":8220},{"class":450,"line":473},[8221,8225,8229,8233,8237],{"type":413,"tag":448,"props":8222,"children":8223},{"style":461},[8224],{"type":418,"value":7761},{"type":413,"tag":448,"props":8226,"children":8227},{"style":1029},[8228],{"type":418,"value":7766},{"type":413,"tag":448,"props":8230,"children":8231},{"style":461},[8232],{"type":418,"value":898},{"type":413,"tag":448,"props":8234,"children":8235},{"style":2000},[8236],{"type":418,"value":7775},{"type":413,"tag":448,"props":8238,"children":8239},{"style":461},[8240],{"type":418,"value":7780},{"type":413,"tag":841,"props":8242,"children":8243},{"icon":843},[8244],{"type":413,"tag":414,"props":8245,"children":8246},{},[8247,8249,8255],{"type":418,"value":8248},"There are other Azure Active Directory authentication methods available, you can find them in the documentation ",{"type":413,"tag":813,"props":8250,"children":8253},{"href":8251,"rel":8252},"https://docs.microsoft.com/en-us/sql/connect/ado-net/sql/azure-active-directory-authentication?view=sql-server-ver15#using-active-directory-password-authentication",[817],[8254],{"type":418,"value":1386},{"type":418,"value":898},{"type":413,"tag":420,"props":8257,"children":8259},{"id":8258},"a-complete-example",[8260],{"type":418,"value":8261},"A complete example",{"type":413,"tag":414,"props":8263,"children":8264},{},[8265],{"type":418,"value":8266},"Enough theory, what if you want to quickly test this by yourself?",{"type":413,"tag":866,"props":8268,"children":8270},{"id":8269},"a-bit-of-azure-cli-to-initialize-the-database",[8271],{"type":418,"value":8272},"A bit of Azure CLI to initialize the database",{"type":413,"tag":414,"props":8274,"children":8275},{},[8276,8278,8285],{"type":418,"value":8277},"I took an ",{"type":413,"tag":813,"props":8279,"children":8282},{"href":8280,"rel":8281},"https://docs.microsoft.com/en-us/azure/azure-sql/database/scripts/create-and-configure-database-cli",[817],[8283],{"type":418,"value":8284},"Azure CLI sample script",{"type":418,"value":8286}," from Microsoft and modify it a little to configure a database with all that is necessary to use Azure Active Directory to connect my user to it.",{"type":413,"tag":437,"props":8288,"children":8290},{"className":937,"code":8289,"language":939,"meta":401,"style":401},"#!/bin/bash\nlocation=\"West Europe\" # to change with your preferred location\nrandomIdentifier=testingmsi${RANDOM:0:5}\n\nresourceGroup=\"resource-$randomIdentifier\"\nserver=\"server-$randomIdentifier\"\ndatabase=\"database-$randomIdentifier\"\n\nlogin=\"globalSqlAdmin\"\npassword=\"P@ssw0rdToChange!\" # to change to have a more secured password\n\n# Retrieve your public IP.\n# Replace by your local machine IP if you are executing this script from cloud shell.\nstartIP=$(dig +short myip.opendns.com @resolver1.opendns.com)\nendIP=$startIP\n\n# Retrieve your current logged-in user to be used as SQL server admin. \n# Change with another user id if you want another user to be an admin.\nazureaduser=$(az ad signed-in-user show --query \"objectId\" -o tsv)\n\necho \"Creating $resourceGroup...\"\naz group create --name $resourceGroup --location \"$location\"\n\necho \"Creating $server in $location...\"\naz sql server create --name $server --resource-group $resourceGroup --location \"$location\" --admin-user $login --admin-password $password\n\necho \"Configuring firewall...\"\naz sql server firewall-rule create --resource-group $resourceGroup --server $server -n AllowYourIp --start-ip-address $startIP --end-ip-address $endIP\n\necho \"Creating $database on $server...\"\naz sql db create --resource-group $resourceGroup --server $server --name $database --sample-name AdventureWorksLT --service-objective Basic --zone-redundant false\n\necho \"Creating AD admin in sql server...\"\naz sql server ad-admin create --resource-group $resourceGroup --server-name $server --display-name ADMIN --object-id $azureaduser\n\necho \"Database connection string to use: \\\"Server=$server.database.windows.net; Authentication=Active Directory Default; Database=$database;\\\"\"\n",[8291],{"type":413,"tag":444,"props":8292,"children":8293},{"__ignoreMap":401},[8294,8302,8330,8378,8385,8415,8444,8473,8480,8505,8535,8542,8550,8558,8594,8611,8618,8626,8634,8693,8700,8731,8774,8781,8818,8893,8900,8920,8991,8998,9035,9111,9118,9138,9199,9206],{"type":413,"tag":448,"props":8295,"children":8296},{"class":450,"line":451},[8297],{"type":413,"tag":448,"props":8298,"children":8299},{"style":2393},[8300],{"type":418,"value":8301},"#!/bin/bash\n",{"type":413,"tag":448,"props":8303,"children":8304},{"class":450,"line":473},[8305,8309,8313,8317,8321,8325],{"type":413,"tag":448,"props":8306,"children":8307},{"style":1029},[8308],{"type":418,"value":5320},{"type":413,"tag":448,"props":8310,"children":8311},{"style":461},[8312],{"type":418,"value":1037},{"type":413,"tag":448,"props":8314,"children":8315},{"style":461},[8316],{"type":418,"value":1183},{"type":413,"tag":448,"props":8318,"children":8319},{"style":467},[8320],{"type":418,"value":5333},{"type":413,"tag":448,"props":8322,"children":8323},{"style":461},[8324],{"type":418,"value":1183},{"type":413,"tag":448,"props":8326,"children":8327},{"style":2393},[8328],{"type":418,"value":8329}," # to change with your preferred location\n",{"type":413,"tag":448,"props":8331,"children":8332},{"class":450,"line":488},[8333,8338,8342,8347,8351,8356,8360,8365,8369,8374],{"type":413,"tag":448,"props":8334,"children":8335},{"style":1029},[8336],{"type":418,"value":8337},"randomIdentifier",{"type":413,"tag":448,"props":8339,"children":8340},{"style":461},[8341],{"type":418,"value":1037},{"type":413,"tag":448,"props":8343,"children":8344},{"style":467},[8345],{"type":418,"value":8346},"testingmsi",{"type":413,"tag":448,"props":8348,"children":8349},{"style":461},[8350],{"type":418,"value":1452},{"type":413,"tag":448,"props":8352,"children":8353},{"style":1029},[8354],{"type":418,"value":8355},"RANDOM",{"type":413,"tag":448,"props":8357,"children":8358},{"style":461},[8359],{"type":418,"value":464},{"type":413,"tag":448,"props":8361,"children":8362},{"style":1029},[8363],{"type":418,"value":8364},"0",{"type":413,"tag":448,"props":8366,"children":8367},{"style":461},[8368],{"type":418,"value":464},{"type":413,"tag":448,"props":8370,"children":8371},{"style":1029},[8372],{"type":418,"value":8373},"5",{"type":413,"tag":448,"props":8375,"children":8376},{"style":461},[8377],{"type":418,"value":1922},{"type":413,"tag":448,"props":8379,"children":8380},{"class":450,"line":501},[8381],{"type":413,"tag":448,"props":8382,"children":8383},{"emptyLinePlaceholder":505},[8384],{"type":418,"value":508},{"type":413,"tag":448,"props":8386,"children":8387},{"class":450,"line":511},[8388,8393,8397,8401,8406,8411],{"type":413,"tag":448,"props":8389,"children":8390},{"style":1029},[8391],{"type":418,"value":8392},"resourceGroup",{"type":413,"tag":448,"props":8394,"children":8395},{"style":461},[8396],{"type":418,"value":1037},{"type":413,"tag":448,"props":8398,"children":8399},{"style":461},[8400],{"type":418,"value":1183},{"type":413,"tag":448,"props":8402,"children":8403},{"style":467},[8404],{"type":418,"value":8405},"resource-",{"type":413,"tag":448,"props":8407,"children":8408},{"style":1029},[8409],{"type":418,"value":8410},"$randomIdentifier",{"type":413,"tag":448,"props":8412,"children":8413},{"style":461},[8414],{"type":418,"value":1005},{"type":413,"tag":448,"props":8416,"children":8417},{"class":450,"line":524},[8418,8423,8427,8431,8436,8440],{"type":413,"tag":448,"props":8419,"children":8420},{"style":1029},[8421],{"type":418,"value":8422},"server",{"type":413,"tag":448,"props":8424,"children":8425},{"style":461},[8426],{"type":418,"value":1037},{"type":413,"tag":448,"props":8428,"children":8429},{"style":461},[8430],{"type":418,"value":1183},{"type":413,"tag":448,"props":8432,"children":8433},{"style":467},[8434],{"type":418,"value":8435},"server-",{"type":413,"tag":448,"props":8437,"children":8438},{"style":1029},[8439],{"type":418,"value":8410},{"type":413,"tag":448,"props":8441,"children":8442},{"style":461},[8443],{"type":418,"value":1005},{"type":413,"tag":448,"props":8445,"children":8446},{"class":450,"line":542},[8447,8452,8456,8460,8465,8469],{"type":413,"tag":448,"props":8448,"children":8449},{"style":1029},[8450],{"type":418,"value":8451},"database",{"type":413,"tag":448,"props":8453,"children":8454},{"style":461},[8455],{"type":418,"value":1037},{"type":413,"tag":448,"props":8457,"children":8458},{"style":461},[8459],{"type":418,"value":1183},{"type":413,"tag":448,"props":8461,"children":8462},{"style":467},[8463],{"type":418,"value":8464},"database-",{"type":413,"tag":448,"props":8466,"children":8467},{"style":1029},[8468],{"type":418,"value":8410},{"type":413,"tag":448,"props":8470,"children":8471},{"style":461},[8472],{"type":418,"value":1005},{"type":413,"tag":448,"props":8474,"children":8475},{"class":450,"line":560},[8476],{"type":413,"tag":448,"props":8477,"children":8478},{"emptyLinePlaceholder":505},[8479],{"type":418,"value":508},{"type":413,"tag":448,"props":8481,"children":8482},{"class":450,"line":573},[8483,8488,8492,8496,8501],{"type":413,"tag":448,"props":8484,"children":8485},{"style":1029},[8486],{"type":418,"value":8487},"login",{"type":413,"tag":448,"props":8489,"children":8490},{"style":461},[8491],{"type":418,"value":1037},{"type":413,"tag":448,"props":8493,"children":8494},{"style":461},[8495],{"type":418,"value":1183},{"type":413,"tag":448,"props":8497,"children":8498},{"style":467},[8499],{"type":418,"value":8500},"globalSqlAdmin",{"type":413,"tag":448,"props":8502,"children":8503},{"style":461},[8504],{"type":418,"value":1005},{"type":413,"tag":448,"props":8506,"children":8507},{"class":450,"line":586},[8508,8513,8517,8521,8526,8530],{"type":413,"tag":448,"props":8509,"children":8510},{"style":1029},[8511],{"type":418,"value":8512},"password",{"type":413,"tag":448,"props":8514,"children":8515},{"style":461},[8516],{"type":418,"value":1037},{"type":413,"tag":448,"props":8518,"children":8519},{"style":461},[8520],{"type":418,"value":1183},{"type":413,"tag":448,"props":8522,"children":8523},{"style":467},[8524],{"type":418,"value":8525},"P@ssw0rdToChange!",{"type":413,"tag":448,"props":8527,"children":8528},{"style":461},[8529],{"type":418,"value":1183},{"type":413,"tag":448,"props":8531,"children":8532},{"style":2393},[8533],{"type":418,"value":8534}," # to change to have a more secured password\n",{"type":413,"tag":448,"props":8536,"children":8537},{"class":450,"line":604},[8538],{"type":413,"tag":448,"props":8539,"children":8540},{"emptyLinePlaceholder":505},[8541],{"type":418,"value":508},{"type":413,"tag":448,"props":8543,"children":8544},{"class":450,"line":617},[8545],{"type":413,"tag":448,"props":8546,"children":8547},{"style":2393},[8548],{"type":418,"value":8549},"# Retrieve your public IP.\n",{"type":413,"tag":448,"props":8551,"children":8552},{"class":450,"line":650},[8553],{"type":413,"tag":448,"props":8554,"children":8555},{"style":2393},[8556],{"type":418,"value":8557},"# Replace by your local machine IP if you are executing this script from cloud shell.\n",{"type":413,"tag":448,"props":8559,"children":8560},{"class":450,"line":668},[8561,8566,8570,8575,8580,8585,8590],{"type":413,"tag":448,"props":8562,"children":8563},{"style":1029},[8564],{"type":418,"value":8565},"startIP",{"type":413,"tag":448,"props":8567,"children":8568},{"style":461},[8569],{"type":418,"value":1154},{"type":413,"tag":448,"props":8571,"children":8572},{"style":949},[8573],{"type":418,"value":8574},"dig",{"type":413,"tag":448,"props":8576,"children":8577},{"style":467},[8578],{"type":418,"value":8579}," +short",{"type":413,"tag":448,"props":8581,"children":8582},{"style":467},[8583],{"type":418,"value":8584}," myip.opendns.com",{"type":413,"tag":448,"props":8586,"children":8587},{"style":467},[8588],{"type":418,"value":8589}," @resolver1.opendns.com",{"type":413,"tag":448,"props":8591,"children":8592},{"style":461},[8593],{"type":418,"value":1197},{"type":413,"tag":448,"props":8595,"children":8596},{"class":450,"line":681},[8597,8602,8606],{"type":413,"tag":448,"props":8598,"children":8599},{"style":1029},[8600],{"type":418,"value":8601},"endIP",{"type":413,"tag":448,"props":8603,"children":8604},{"style":461},[8605],{"type":418,"value":1037},{"type":413,"tag":448,"props":8607,"children":8608},{"style":1029},[8609],{"type":418,"value":8610},"$startIP\n",{"type":413,"tag":448,"props":8612,"children":8613},{"class":450,"line":699},[8614],{"type":413,"tag":448,"props":8615,"children":8616},{"emptyLinePlaceholder":505},[8617],{"type":418,"value":508},{"type":413,"tag":448,"props":8619,"children":8620},{"class":450,"line":717},[8621],{"type":413,"tag":448,"props":8622,"children":8623},{"style":2393},[8624],{"type":418,"value":8625},"# Retrieve your current logged-in user to be used as SQL server admin. \n",{"type":413,"tag":448,"props":8627,"children":8628},{"class":450,"line":735},[8629],{"type":413,"tag":448,"props":8630,"children":8631},{"style":2393},[8632],{"type":418,"value":8633},"# Change with another user id if you want another user to be an admin.\n",{"type":413,"tag":448,"props":8635,"children":8636},{"class":450,"line":743},[8637,8642,8646,8650,8655,8660,8664,8668,8672,8676,8680,8685,8689],{"type":413,"tag":448,"props":8638,"children":8639},{"style":1029},[8640],{"type":418,"value":8641},"azureaduser",{"type":413,"tag":448,"props":8643,"children":8644},{"style":461},[8645],{"type":418,"value":1154},{"type":413,"tag":448,"props":8647,"children":8648},{"style":949},[8649],{"type":418,"value":4560},{"type":413,"tag":448,"props":8651,"children":8652},{"style":467},[8653],{"type":418,"value":8654}," ad",{"type":413,"tag":448,"props":8656,"children":8657},{"style":467},[8658],{"type":418,"value":8659}," signed-in-user",{"type":413,"tag":448,"props":8661,"children":8662},{"style":467},[8663],{"type":418,"value":4573},{"type":413,"tag":448,"props":8665,"children":8666},{"style":467},[8667],{"type":418,"value":5588},{"type":413,"tag":448,"props":8669,"children":8670},{"style":461},[8671],{"type":418,"value":995},{"type":413,"tag":448,"props":8673,"children":8674},{"style":467},[8675],{"type":418,"value":6246},{"type":413,"tag":448,"props":8677,"children":8678},{"style":461},[8679],{"type":418,"value":1183},{"type":413,"tag":448,"props":8681,"children":8682},{"style":467},[8683],{"type":418,"value":8684}," -o",{"type":413,"tag":448,"props":8686,"children":8687},{"style":467},[8688],{"type":418,"value":5583},{"type":413,"tag":448,"props":8690,"children":8691},{"style":461},[8692],{"type":418,"value":1197},{"type":413,"tag":448,"props":8694,"children":8695},{"class":450,"line":772},[8696],{"type":413,"tag":448,"props":8697,"children":8698},{"emptyLinePlaceholder":505},[8699],{"type":418,"value":508},{"type":413,"tag":448,"props":8701,"children":8702},{"class":450,"line":791},[8703,8708,8712,8717,8722,8727],{"type":413,"tag":448,"props":8704,"children":8705},{"style":2000},[8706],{"type":418,"value":8707},"echo",{"type":413,"tag":448,"props":8709,"children":8710},{"style":461},[8711],{"type":418,"value":995},{"type":413,"tag":448,"props":8713,"children":8714},{"style":467},[8715],{"type":418,"value":8716},"Creating ",{"type":413,"tag":448,"props":8718,"children":8719},{"style":1029},[8720],{"type":418,"value":8721},"$resourceGroup",{"type":413,"tag":448,"props":8723,"children":8724},{"style":467},[8725],{"type":418,"value":8726},"...",{"type":413,"tag":448,"props":8728,"children":8729},{"style":461},[8730],{"type":418,"value":1005},{"type":413,"tag":448,"props":8732,"children":8733},{"class":450,"line":800},[8734,8738,8742,8746,8751,8756,8761,8765,8770],{"type":413,"tag":448,"props":8735,"children":8736},{"style":949},[8737],{"type":418,"value":4560},{"type":413,"tag":448,"props":8739,"children":8740},{"style":467},[8741],{"type":418,"value":5435},{"type":413,"tag":448,"props":8743,"children":8744},{"style":467},[8745],{"type":418,"value":5440},{"type":413,"tag":448,"props":8747,"children":8748},{"style":467},[8749],{"type":418,"value":8750}," --name",{"type":413,"tag":448,"props":8752,"children":8753},{"style":1029},[8754],{"type":418,"value":8755}," $resourceGroup ",{"type":413,"tag":448,"props":8757,"children":8758},{"style":467},[8759],{"type":418,"value":8760},"--location",{"type":413,"tag":448,"props":8762,"children":8763},{"style":461},[8764],{"type":418,"value":995},{"type":413,"tag":448,"props":8766,"children":8767},{"style":1029},[8768],{"type":418,"value":8769},"$location",{"type":413,"tag":448,"props":8771,"children":8772},{"style":461},[8773],{"type":418,"value":1005},{"type":413,"tag":448,"props":8775,"children":8776},{"class":450,"line":2909},[8777],{"type":413,"tag":448,"props":8778,"children":8779},{"emptyLinePlaceholder":505},[8780],{"type":418,"value":508},{"type":413,"tag":448,"props":8782,"children":8783},{"class":450,"line":3021},[8784,8788,8792,8796,8801,8806,8810,8814],{"type":413,"tag":448,"props":8785,"children":8786},{"style":2000},[8787],{"type":418,"value":8707},{"type":413,"tag":448,"props":8789,"children":8790},{"style":461},[8791],{"type":418,"value":995},{"type":413,"tag":448,"props":8793,"children":8794},{"style":467},[8795],{"type":418,"value":8716},{"type":413,"tag":448,"props":8797,"children":8798},{"style":1029},[8799],{"type":418,"value":8800},"$server",{"type":413,"tag":448,"props":8802,"children":8803},{"style":467},[8804],{"type":418,"value":8805}," in ",{"type":413,"tag":448,"props":8807,"children":8808},{"style":1029},[8809],{"type":418,"value":8769},{"type":413,"tag":448,"props":8811,"children":8812},{"style":467},[8813],{"type":418,"value":8726},{"type":413,"tag":448,"props":8815,"children":8816},{"style":461},[8817],{"type":418,"value":1005},{"type":413,"tag":448,"props":8819,"children":8820},{"class":450,"line":3029},[8821,8825,8830,8835,8839,8843,8848,8853,8857,8861,8865,8869,8873,8878,8883,8888],{"type":413,"tag":448,"props":8822,"children":8823},{"style":949},[8824],{"type":418,"value":4560},{"type":413,"tag":448,"props":8826,"children":8827},{"style":467},[8828],{"type":418,"value":8829}," sql",{"type":413,"tag":448,"props":8831,"children":8832},{"style":467},[8833],{"type":418,"value":8834}," server",{"type":413,"tag":448,"props":8836,"children":8837},{"style":467},[8838],{"type":418,"value":5440},{"type":413,"tag":448,"props":8840,"children":8841},{"style":467},[8842],{"type":418,"value":8750},{"type":413,"tag":448,"props":8844,"children":8845},{"style":1029},[8846],{"type":418,"value":8847}," $server ",{"type":413,"tag":448,"props":8849,"children":8850},{"style":467},[8851],{"type":418,"value":8852},"--resource-group",{"type":413,"tag":448,"props":8854,"children":8855},{"style":1029},[8856],{"type":418,"value":8755},{"type":413,"tag":448,"props":8858,"children":8859},{"style":467},[8860],{"type":418,"value":8760},{"type":413,"tag":448,"props":8862,"children":8863},{"style":461},[8864],{"type":418,"value":995},{"type":413,"tag":448,"props":8866,"children":8867},{"style":1029},[8868],{"type":418,"value":8769},{"type":413,"tag":448,"props":8870,"children":8871},{"style":461},[8872],{"type":418,"value":1183},{"type":413,"tag":448,"props":8874,"children":8875},{"style":467},[8876],{"type":418,"value":8877}," --admin-user",{"type":413,"tag":448,"props":8879,"children":8880},{"style":1029},[8881],{"type":418,"value":8882}," $login ",{"type":413,"tag":448,"props":8884,"children":8885},{"style":467},[8886],{"type":418,"value":8887},"--admin-password",{"type":413,"tag":448,"props":8889,"children":8890},{"style":1029},[8891],{"type":418,"value":8892}," $password\n",{"type":413,"tag":448,"props":8894,"children":8895},{"class":450,"line":3038},[8896],{"type":413,"tag":448,"props":8897,"children":8898},{"emptyLinePlaceholder":505},[8899],{"type":418,"value":508},{"type":413,"tag":448,"props":8901,"children":8902},{"class":450,"line":3062},[8903,8907,8911,8916],{"type":413,"tag":448,"props":8904,"children":8905},{"style":2000},[8906],{"type":418,"value":8707},{"type":413,"tag":448,"props":8908,"children":8909},{"style":461},[8910],{"type":418,"value":995},{"type":413,"tag":448,"props":8912,"children":8913},{"style":467},[8914],{"type":418,"value":8915},"Configuring firewall...",{"type":413,"tag":448,"props":8917,"children":8918},{"style":461},[8919],{"type":418,"value":1005},{"type":413,"tag":448,"props":8921,"children":8922},{"class":450,"line":3086},[8923,8927,8931,8935,8940,8944,8949,8953,8958,8962,8966,8971,8976,8981,8986],{"type":413,"tag":448,"props":8924,"children":8925},{"style":949},[8926],{"type":418,"value":4560},{"type":413,"tag":448,"props":8928,"children":8929},{"style":467},[8930],{"type":418,"value":8829},{"type":413,"tag":448,"props":8932,"children":8933},{"style":467},[8934],{"type":418,"value":8834},{"type":413,"tag":448,"props":8936,"children":8937},{"style":467},[8938],{"type":418,"value":8939}," firewall-rule",{"type":413,"tag":448,"props":8941,"children":8942},{"style":467},[8943],{"type":418,"value":5440},{"type":413,"tag":448,"props":8945,"children":8946},{"style":467},[8947],{"type":418,"value":8948}," --resource-group",{"type":413,"tag":448,"props":8950,"children":8951},{"style":1029},[8952],{"type":418,"value":8755},{"type":413,"tag":448,"props":8954,"children":8955},{"style":467},[8956],{"type":418,"value":8957},"--server",{"type":413,"tag":448,"props":8959,"children":8960},{"style":1029},[8961],{"type":418,"value":8847},{"type":413,"tag":448,"props":8963,"children":8964},{"style":467},[8965],{"type":418,"value":5495},{"type":413,"tag":448,"props":8967,"children":8968},{"style":467},[8969],{"type":418,"value":8970}," AllowYourIp",{"type":413,"tag":448,"props":8972,"children":8973},{"style":467},[8974],{"type":418,"value":8975}," --start-ip-address",{"type":413,"tag":448,"props":8977,"children":8978},{"style":1029},[8979],{"type":418,"value":8980}," $startIP ",{"type":413,"tag":448,"props":8982,"children":8983},{"style":467},[8984],{"type":418,"value":8985},"--end-ip-address",{"type":413,"tag":448,"props":8987,"children":8988},{"style":1029},[8989],{"type":418,"value":8990}," $endIP\n",{"type":413,"tag":448,"props":8992,"children":8993},{"class":450,"line":3110},[8994],{"type":413,"tag":448,"props":8995,"children":8996},{"emptyLinePlaceholder":505},[8997],{"type":418,"value":508},{"type":413,"tag":448,"props":8999,"children":9000},{"class":450,"line":3150},[9001,9005,9009,9013,9018,9023,9027,9031],{"type":413,"tag":448,"props":9002,"children":9003},{"style":2000},[9004],{"type":418,"value":8707},{"type":413,"tag":448,"props":9006,"children":9007},{"style":461},[9008],{"type":418,"value":995},{"type":413,"tag":448,"props":9010,"children":9011},{"style":467},[9012],{"type":418,"value":8716},{"type":413,"tag":448,"props":9014,"children":9015},{"style":1029},[9016],{"type":418,"value":9017},"$database",{"type":413,"tag":448,"props":9019,"children":9020},{"style":467},[9021],{"type":418,"value":9022}," on ",{"type":413,"tag":448,"props":9024,"children":9025},{"style":1029},[9026],{"type":418,"value":8800},{"type":413,"tag":448,"props":9028,"children":9029},{"style":467},[9030],{"type":418,"value":8726},{"type":413,"tag":448,"props":9032,"children":9033},{"style":461},[9034],{"type":418,"value":1005},{"type":413,"tag":448,"props":9036,"children":9037},{"class":450,"line":3182},[9038,9042,9046,9051,9055,9059,9063,9067,9071,9076,9081,9086,9091,9096,9101,9106],{"type":413,"tag":448,"props":9039,"children":9040},{"style":949},[9041],{"type":418,"value":4560},{"type":413,"tag":448,"props":9043,"children":9044},{"style":467},[9045],{"type":418,"value":8829},{"type":413,"tag":448,"props":9047,"children":9048},{"style":467},[9049],{"type":418,"value":9050}," db",{"type":413,"tag":448,"props":9052,"children":9053},{"style":467},[9054],{"type":418,"value":5440},{"type":413,"tag":448,"props":9056,"children":9057},{"style":467},[9058],{"type":418,"value":8948},{"type":413,"tag":448,"props":9060,"children":9061},{"style":1029},[9062],{"type":418,"value":8755},{"type":413,"tag":448,"props":9064,"children":9065},{"style":467},[9066],{"type":418,"value":8957},{"type":413,"tag":448,"props":9068,"children":9069},{"style":1029},[9070],{"type":418,"value":8847},{"type":413,"tag":448,"props":9072,"children":9073},{"style":467},[9074],{"type":418,"value":9075},"--name",{"type":413,"tag":448,"props":9077,"children":9078},{"style":1029},[9079],{"type":418,"value":9080}," $database ",{"type":413,"tag":448,"props":9082,"children":9083},{"style":467},[9084],{"type":418,"value":9085},"--sample-name",{"type":413,"tag":448,"props":9087,"children":9088},{"style":467},[9089],{"type":418,"value":9090}," AdventureWorksLT",{"type":413,"tag":448,"props":9092,"children":9093},{"style":467},[9094],{"type":418,"value":9095}," --service-objective",{"type":413,"tag":448,"props":9097,"children":9098},{"style":467},[9099],{"type":418,"value":9100}," Basic",{"type":413,"tag":448,"props":9102,"children":9103},{"style":467},[9104],{"type":418,"value":9105}," --zone-redundant",{"type":413,"tag":448,"props":9107,"children":9108},{"style":461},[9109],{"type":418,"value":9110}," false\n",{"type":413,"tag":448,"props":9112,"children":9113},{"class":450,"line":3202},[9114],{"type":413,"tag":448,"props":9115,"children":9116},{"emptyLinePlaceholder":505},[9117],{"type":418,"value":508},{"type":413,"tag":448,"props":9119,"children":9120},{"class":450,"line":3218},[9121,9125,9129,9134],{"type":413,"tag":448,"props":9122,"children":9123},{"style":2000},[9124],{"type":418,"value":8707},{"type":413,"tag":448,"props":9126,"children":9127},{"style":461},[9128],{"type":418,"value":995},{"type":413,"tag":448,"props":9130,"children":9131},{"style":467},[9132],{"type":418,"value":9133},"Creating AD admin in sql server...",{"type":413,"tag":448,"props":9135,"children":9136},{"style":461},[9137],{"type":418,"value":1005},{"type":413,"tag":448,"props":9139,"children":9140},{"class":450,"line":3226},[9141,9145,9149,9153,9158,9162,9166,9170,9175,9179,9184,9189,9194],{"type":413,"tag":448,"props":9142,"children":9143},{"style":949},[9144],{"type":418,"value":4560},{"type":413,"tag":448,"props":9146,"children":9147},{"style":467},[9148],{"type":418,"value":8829},{"type":413,"tag":448,"props":9150,"children":9151},{"style":467},[9152],{"type":418,"value":8834},{"type":413,"tag":448,"props":9154,"children":9155},{"style":467},[9156],{"type":418,"value":9157}," ad-admin",{"type":413,"tag":448,"props":9159,"children":9160},{"style":467},[9161],{"type":418,"value":5440},{"type":413,"tag":448,"props":9163,"children":9164},{"style":467},[9165],{"type":418,"value":8948},{"type":413,"tag":448,"props":9167,"children":9168},{"style":1029},[9169],{"type":418,"value":8755},{"type":413,"tag":448,"props":9171,"children":9172},{"style":467},[9173],{"type":418,"value":9174},"--server-name",{"type":413,"tag":448,"props":9176,"children":9177},{"style":1029},[9178],{"type":418,"value":8847},{"type":413,"tag":448,"props":9180,"children":9181},{"style":467},[9182],{"type":418,"value":9183},"--display-name",{"type":413,"tag":448,"props":9185,"children":9186},{"style":467},[9187],{"type":418,"value":9188}," ADMIN",{"type":413,"tag":448,"props":9190,"children":9191},{"style":467},[9192],{"type":418,"value":9193}," --object-id",{"type":413,"tag":448,"props":9195,"children":9196},{"style":1029},[9197],{"type":418,"value":9198}," $azureaduser\n",{"type":413,"tag":448,"props":9200,"children":9201},{"class":450,"line":3234},[9202],{"type":413,"tag":448,"props":9203,"children":9204},{"emptyLinePlaceholder":505},[9205],{"type":418,"value":508},{"type":413,"tag":448,"props":9207,"children":9208},{"class":450,"line":3242},[9209,9213,9217,9222,9227,9232,9236,9241,9245,9249,9253],{"type":413,"tag":448,"props":9210,"children":9211},{"style":2000},[9212],{"type":418,"value":8707},{"type":413,"tag":448,"props":9214,"children":9215},{"style":461},[9216],{"type":418,"value":995},{"type":413,"tag":448,"props":9218,"children":9219},{"style":467},[9220],{"type":418,"value":9221},"Database connection string to use: ",{"type":413,"tag":448,"props":9223,"children":9224},{"style":1029},[9225],{"type":418,"value":9226},"\\\"",{"type":413,"tag":448,"props":9228,"children":9229},{"style":467},[9230],{"type":418,"value":9231},"Server=",{"type":413,"tag":448,"props":9233,"children":9234},{"style":1029},[9235],{"type":418,"value":8800},{"type":413,"tag":448,"props":9237,"children":9238},{"style":467},[9239],{"type":418,"value":9240},".database.windows.net; Authentication=Active Directory Default; Database=",{"type":413,"tag":448,"props":9242,"children":9243},{"style":1029},[9244],{"type":418,"value":9017},{"type":413,"tag":448,"props":9246,"children":9247},{"style":467},[9248],{"type":418,"value":5844},{"type":413,"tag":448,"props":9250,"children":9251},{"style":1029},[9252],{"type":418,"value":9226},{"type":413,"tag":448,"props":9254,"children":9255},{"style":461},[9256],{"type":418,"value":1005},{"type":413,"tag":414,"props":9258,"children":9259},{},[9260],{"type":418,"value":9261},"This script should be self-explanatory if you have already played a little with Azure CLI. Basically, what it does is:",{"type":413,"tag":5031,"props":9263,"children":9264},{},[9265,9270,9282,9287,9292],{"type":413,"tag":2159,"props":9266,"children":9267},{},[9268],{"type":418,"value":9269},"create an azure SQL server",{"type":413,"tag":2159,"props":9271,"children":9272},{},[9273,9275,9280],{"type":418,"value":9274},"configure the server firewall to allow you to query it from your local IP address (if you are executing the script from cloud shell, replace ",{"type":413,"tag":444,"props":9276,"children":9278},{"className":9277},[],[9279],{"type":418,"value":8565},{"type":418,"value":9281}," variable with your local machine IP)",{"type":413,"tag":2159,"props":9283,"children":9284},{},[9285],{"type":418,"value":9286},"create an azure SQL database with already tables and data in it from the sample AdventureWorksLT",{"type":413,"tag":2159,"props":9288,"children":9289},{},[9290],{"type":418,"value":9291},"set you logged in azure ad user as the AD administrator of the database",{"type":413,"tag":2159,"props":9293,"children":9294},{},[9295],{"type":418,"value":9296},"write in the console the connection string to use in your C# code to access the database",{"type":413,"tag":414,"props":9298,"children":9299},{},[9300],{"type":418,"value":9301},"If you want to customize something do not hesitate to modify the scripts and especially variables like the resources location, the SQL server user/password, or the name of the resources. This is a bash script but if you want to execute it in PowerShell, all the Azure CLI commands should work fine, you just have to change the variables declarations as the syntax is different in PowerShell. If you don't have Azure CLI installed on your laptop you can use Azure Cloud Shell to execute this script.",{"type":413,"tag":841,"props":9303,"children":9304},{"icon":843},[9305],{"type":413,"tag":414,"props":9306,"children":9307},{},[9308,9310,9315],{"type":418,"value":9309},"If you are new to Azure CLI, you can read my article ",{"type":413,"tag":813,"props":9311,"children":9313},{"href":1382,"rel":9312},[817],[9314],{"type":418,"value":15},{"type":418,"value":898},{"type":413,"tag":866,"props":9317,"children":9319},{"id":9318},"querying-the-database-from-a-minima-api-in-c",[9320],{"type":418,"value":9321},"Querying the database from a minima API in C#",{"type":413,"tag":414,"props":9323,"children":9324},{},[9325,9327,9334],{"type":418,"value":9326},"Usually, I like to create a console application (with the ",{"type":413,"tag":813,"props":9328,"children":9331},{"href":9329,"rel":9330},"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio#worker-service-template",[817],[9332],{"type":418,"value":9333},"worker service template",{"type":418,"value":9335}," for instance) for my samples, yet this time I decided to try the new minimal APIs from .NET 6 (currently in preview).",{"type":413,"tag":414,"props":9337,"children":9338},{},[9339,9341,9347],{"type":418,"value":9340},"Minimal APIs would probably deserve an entire blog post, but let's just say a minimal API in .NET 6 allow you to build a small HTTP API with less ceremony than a classic controller-based API. As all the code can be written in a ",{"type":413,"tag":444,"props":9342,"children":9344},{"className":9343},[],[9345],{"type":418,"value":9346},"Program.cs",{"type":418,"value":9348}," file, so it's very convenient when you want to quickly build a web application without too much complexity (especially if you are new to ASP.NET Core) or if you are developing a small microservice.",{"type":413,"tag":437,"props":9350,"children":9352},{"className":7652,"code":9351,"language":326,"meta":401,"style":401},"using Dapper;\nusing Microsoft.Data.SqlClient;\n\nvar builder = WebApplication.CreateBuilder(args);\nvar app = builder.Build();\n\nif (app.Environment.IsDevelopment())\n{\n    app.UseDeveloperExceptionPage();\n}\n\napp.MapGet(\"/\", async () =>\n{\n    using var connection = new SqlConnection(\"Server=server-testingmsi28497.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi28497;\");\n    var products = await connection.QueryAsync\u003CProduct>(\"SELECT TOP 10 ProductID, Name from [SalesLT].[Product]\");\n    return products;\n});\n\napp.Run();\n\npublic record Product(int ProductID, string Name);\n",[9353],{"type":413,"tag":444,"props":9354,"children":9355},{"__ignoreMap":401},[9356,9372,9405,9412,9455,9488,9495,9535,9542,9563,9570,9577,9628,9635,9684,9750,9766,9774,9781,9801,9808],{"type":413,"tag":448,"props":9357,"children":9358},{"class":450,"line":451},[9359,9363,9368],{"type":413,"tag":448,"props":9360,"children":9361},{"style":1733},[9362],{"type":418,"value":7711},{"type":413,"tag":448,"props":9364,"children":9365},{"style":1029},[9366],{"type":418,"value":9367}," Dapper",{"type":413,"tag":448,"props":9369,"children":9370},{"style":461},[9371],{"type":418,"value":5854},{"type":413,"tag":448,"props":9373,"children":9374},{"class":450,"line":473},[9375,9379,9384,9388,9393,9397,9401],{"type":413,"tag":448,"props":9376,"children":9377},{"style":1733},[9378],{"type":418,"value":7711},{"type":413,"tag":448,"props":9380,"children":9381},{"style":1029},[9382],{"type":418,"value":9383}," Microsoft",{"type":413,"tag":448,"props":9385,"children":9386},{"style":461},[9387],{"type":418,"value":898},{"type":413,"tag":448,"props":9389,"children":9390},{"style":1029},[9391],{"type":418,"value":9392},"Data",{"type":413,"tag":448,"props":9394,"children":9395},{"style":461},[9396],{"type":418,"value":898},{"type":413,"tag":448,"props":9398,"children":9399},{"style":1029},[9400],{"type":418,"value":8152},{"type":413,"tag":448,"props":9402,"children":9403},{"style":461},[9404],{"type":418,"value":5854},{"type":413,"tag":448,"props":9406,"children":9407},{"class":450,"line":488},[9408],{"type":413,"tag":448,"props":9409,"children":9410},{"emptyLinePlaceholder":505},[9411],{"type":418,"value":508},{"type":413,"tag":448,"props":9413,"children":9414},{"class":450,"line":501},[9415,9419,9424,9428,9433,9437,9442,9446,9451],{"type":413,"tag":448,"props":9416,"children":9417},{"style":949},[9418],{"type":418,"value":7665},{"type":413,"tag":448,"props":9420,"children":9421},{"style":949},[9422],{"type":418,"value":9423}," builder",{"type":413,"tag":448,"props":9425,"children":9426},{"style":461},[9427],{"type":418,"value":7675},{"type":413,"tag":448,"props":9429,"children":9430},{"style":1029},[9431],{"type":418,"value":9432}," WebApplication",{"type":413,"tag":448,"props":9434,"children":9435},{"style":461},[9436],{"type":418,"value":898},{"type":413,"tag":448,"props":9438,"children":9439},{"style":2000},[9440],{"type":418,"value":9441},"CreateBuilder",{"type":413,"tag":448,"props":9443,"children":9444},{"style":461},[9445],{"type":418,"value":2041},{"type":413,"tag":448,"props":9447,"children":9448},{"style":1029},[9449],{"type":418,"value":9450},"args",{"type":413,"tag":448,"props":9452,"children":9453},{"style":461},[9454],{"type":418,"value":8217},{"type":413,"tag":448,"props":9456,"children":9457},{"class":450,"line":511},[9458,9462,9467,9471,9475,9479,9484],{"type":413,"tag":448,"props":9459,"children":9460},{"style":949},[9461],{"type":418,"value":7665},{"type":413,"tag":448,"props":9463,"children":9464},{"style":949},[9465],{"type":418,"value":9466}," app",{"type":413,"tag":448,"props":9468,"children":9469},{"style":461},[9470],{"type":418,"value":7675},{"type":413,"tag":448,"props":9472,"children":9473},{"style":1029},[9474],{"type":418,"value":9423},{"type":413,"tag":448,"props":9476,"children":9477},{"style":461},[9478],{"type":418,"value":898},{"type":413,"tag":448,"props":9480,"children":9481},{"style":2000},[9482],{"type":418,"value":9483},"Build",{"type":413,"tag":448,"props":9485,"children":9486},{"style":461},[9487],{"type":418,"value":7780},{"type":413,"tag":448,"props":9489,"children":9490},{"class":450,"line":524},[9491],{"type":413,"tag":448,"props":9492,"children":9493},{"emptyLinePlaceholder":505},[9494],{"type":418,"value":508},{"type":413,"tag":448,"props":9496,"children":9497},{"class":450,"line":542},[9498,9503,9507,9512,9516,9521,9525,9530],{"type":413,"tag":448,"props":9499,"children":9500},{"style":785},[9501],{"type":418,"value":9502},"if",{"type":413,"tag":448,"props":9504,"children":9505},{"style":461},[9506],{"type":418,"value":7716},{"type":413,"tag":448,"props":9508,"children":9509},{"style":1029},[9510],{"type":418,"value":9511},"app",{"type":413,"tag":448,"props":9513,"children":9514},{"style":461},[9515],{"type":418,"value":898},{"type":413,"tag":448,"props":9517,"children":9518},{"style":1029},[9519],{"type":418,"value":9520},"Environment",{"type":413,"tag":448,"props":9522,"children":9523},{"style":461},[9524],{"type":418,"value":898},{"type":413,"tag":448,"props":9526,"children":9527},{"style":2000},[9528],{"type":418,"value":9529},"IsDevelopment",{"type":413,"tag":448,"props":9531,"children":9532},{"style":461},[9533],{"type":418,"value":9534},"())\n",{"type":413,"tag":448,"props":9536,"children":9537},{"class":450,"line":560},[9538],{"type":413,"tag":448,"props":9539,"children":9540},{"style":461},[9541],{"type":418,"value":1741},{"type":413,"tag":448,"props":9543,"children":9544},{"class":450,"line":573},[9545,9550,9554,9559],{"type":413,"tag":448,"props":9546,"children":9547},{"style":1029},[9548],{"type":418,"value":9549},"    app",{"type":413,"tag":448,"props":9551,"children":9552},{"style":461},[9553],{"type":418,"value":898},{"type":413,"tag":448,"props":9555,"children":9556},{"style":2000},[9557],{"type":418,"value":9558},"UseDeveloperExceptionPage",{"type":413,"tag":448,"props":9560,"children":9561},{"style":461},[9562],{"type":418,"value":7780},{"type":413,"tag":448,"props":9564,"children":9565},{"class":450,"line":586},[9566],{"type":413,"tag":448,"props":9567,"children":9568},{"style":461},[9569],{"type":418,"value":1922},{"type":413,"tag":448,"props":9571,"children":9572},{"class":450,"line":604},[9573],{"type":413,"tag":448,"props":9574,"children":9575},{"emptyLinePlaceholder":505},[9576],{"type":418,"value":508},{"type":413,"tag":448,"props":9578,"children":9579},{"class":450,"line":617},[9580,9584,9588,9593,9597,9601,9605,9609,9613,9618,9623],{"type":413,"tag":448,"props":9581,"children":9582},{"style":1029},[9583],{"type":418,"value":9511},{"type":413,"tag":448,"props":9585,"children":9586},{"style":461},[9587],{"type":418,"value":898},{"type":413,"tag":448,"props":9589,"children":9590},{"style":2000},[9591],{"type":418,"value":9592},"MapGet",{"type":413,"tag":448,"props":9594,"children":9595},{"style":461},[9596],{"type":418,"value":2041},{"type":413,"tag":448,"props":9598,"children":9599},{"style":461},[9600],{"type":418,"value":1183},{"type":413,"tag":448,"props":9602,"children":9603},{"style":467},[9604],{"type":418,"value":1687},{"type":413,"tag":448,"props":9606,"children":9607},{"style":461},[9608],{"type":418,"value":1183},{"type":413,"tag":448,"props":9610,"children":9611},{"style":461},[9612],{"type":418,"value":2059},{"type":413,"tag":448,"props":9614,"children":9615},{"style":4059},[9616],{"type":418,"value":9617}," async",{"type":413,"tag":448,"props":9619,"children":9620},{"style":461},[9621],{"type":418,"value":9622}," ()",{"type":413,"tag":448,"props":9624,"children":9625},{"style":461},[9626],{"type":418,"value":9627}," =>\n",{"type":413,"tag":448,"props":9629,"children":9630},{"class":450,"line":650},[9631],{"type":413,"tag":448,"props":9632,"children":9633},{"style":461},[9634],{"type":418,"value":1741},{"type":413,"tag":448,"props":9636,"children":9637},{"class":450,"line":668},[9638,9643,9647,9651,9655,9659,9663,9667,9671,9676,9680],{"type":413,"tag":448,"props":9639,"children":9640},{"style":785},[9641],{"type":418,"value":9642},"    using",{"type":413,"tag":448,"props":9644,"children":9645},{"style":949},[9646],{"type":418,"value":7970},{"type":413,"tag":448,"props":9648,"children":9649},{"style":949},[9650],{"type":418,"value":7766},{"type":413,"tag":448,"props":9652,"children":9653},{"style":461},[9654],{"type":418,"value":7675},{"type":413,"tag":448,"props":9656,"children":9657},{"style":461},[9658],{"type":418,"value":7734},{"type":413,"tag":448,"props":9660,"children":9661},{"style":949},[9662],{"type":418,"value":7739},{"type":413,"tag":448,"props":9664,"children":9665},{"style":461},[9666],{"type":418,"value":2041},{"type":413,"tag":448,"props":9668,"children":9669},{"style":461},[9670],{"type":418,"value":1183},{"type":413,"tag":448,"props":9672,"children":9673},{"style":467},[9674],{"type":418,"value":9675},"Server=server-testingmsi28497.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi28497;",{"type":413,"tag":448,"props":9677,"children":9678},{"style":461},[9679],{"type":418,"value":1183},{"type":413,"tag":448,"props":9681,"children":9682},{"style":461},[9683],{"type":418,"value":8217},{"type":413,"tag":448,"props":9685,"children":9686},{"class":450,"line":681},[9687,9692,9697,9701,9705,9709,9713,9718,9723,9728,9733,9737,9742,9746],{"type":413,"tag":448,"props":9688,"children":9689},{"style":949},[9690],{"type":418,"value":9691},"    var",{"type":413,"tag":448,"props":9693,"children":9694},{"style":949},[9695],{"type":418,"value":9696}," products",{"type":413,"tag":448,"props":9698,"children":9699},{"style":461},[9700],{"type":418,"value":7675},{"type":413,"tag":448,"props":9702,"children":9703},{"style":461},[9704],{"type":418,"value":7893},{"type":413,"tag":448,"props":9706,"children":9707},{"style":1029},[9708],{"type":418,"value":7766},{"type":413,"tag":448,"props":9710,"children":9711},{"style":461},[9712],{"type":418,"value":898},{"type":413,"tag":448,"props":9714,"children":9715},{"style":2000},[9716],{"type":418,"value":9717},"QueryAsync",{"type":413,"tag":448,"props":9719,"children":9720},{"style":461},[9721],{"type":418,"value":9722},"\u003C",{"type":413,"tag":448,"props":9724,"children":9725},{"style":949},[9726],{"type":418,"value":9727},"Product",{"type":413,"tag":448,"props":9729,"children":9730},{"style":461},[9731],{"type":418,"value":9732},">(",{"type":413,"tag":448,"props":9734,"children":9735},{"style":461},[9736],{"type":418,"value":1183},{"type":413,"tag":448,"props":9738,"children":9739},{"style":467},[9740],{"type":418,"value":9741},"SELECT TOP 10 ProductID, Name from [SalesLT].[Product]",{"type":413,"tag":448,"props":9743,"children":9744},{"style":461},[9745],{"type":418,"value":1183},{"type":413,"tag":448,"props":9747,"children":9748},{"style":461},[9749],{"type":418,"value":8217},{"type":413,"tag":448,"props":9751,"children":9752},{"class":450,"line":699},[9753,9758,9762],{"type":413,"tag":448,"props":9754,"children":9755},{"style":785},[9756],{"type":418,"value":9757},"    return",{"type":413,"tag":448,"props":9759,"children":9760},{"style":1029},[9761],{"type":418,"value":9696},{"type":413,"tag":448,"props":9763,"children":9764},{"style":461},[9765],{"type":418,"value":5854},{"type":413,"tag":448,"props":9767,"children":9768},{"class":450,"line":717},[9769],{"type":413,"tag":448,"props":9770,"children":9771},{"style":461},[9772],{"type":418,"value":9773},"});\n",{"type":413,"tag":448,"props":9775,"children":9776},{"class":450,"line":735},[9777],{"type":413,"tag":448,"props":9778,"children":9779},{"emptyLinePlaceholder":505},[9780],{"type":418,"value":508},{"type":413,"tag":448,"props":9782,"children":9783},{"class":450,"line":743},[9784,9788,9792,9797],{"type":413,"tag":448,"props":9785,"children":9786},{"style":1029},[9787],{"type":418,"value":9511},{"type":413,"tag":448,"props":9789,"children":9790},{"style":461},[9791],{"type":418,"value":898},{"type":413,"tag":448,"props":9793,"children":9794},{"style":2000},[9795],{"type":418,"value":9796},"Run",{"type":413,"tag":448,"props":9798,"children":9799},{"style":461},[9800],{"type":418,"value":7780},{"type":413,"tag":448,"props":9802,"children":9803},{"class":450,"line":772},[9804],{"type":413,"tag":448,"props":9805,"children":9806},{"emptyLinePlaceholder":505},[9807],{"type":418,"value":508},{"type":413,"tag":448,"props":9809,"children":9810},{"class":450,"line":791},[9811,9816,9821,9826,9831,9836,9840,9844,9849],{"type":413,"tag":448,"props":9812,"children":9813},{"style":4059},[9814],{"type":418,"value":9815},"public",{"type":413,"tag":448,"props":9817,"children":9818},{"style":949},[9819],{"type":418,"value":9820}," record",{"type":413,"tag":448,"props":9822,"children":9823},{"style":949},[9824],{"type":418,"value":9825}," Product",{"type":413,"tag":448,"props":9827,"children":9828},{"style":461},[9829],{"type":418,"value":9830},"(int",{"type":413,"tag":448,"props":9832,"children":9833},{"style":949},[9834],{"type":418,"value":9835}," ProductID",{"type":413,"tag":448,"props":9837,"children":9838},{"style":461},[9839],{"type":418,"value":2059},{"type":413,"tag":448,"props":9841,"children":9842},{"style":461},[9843],{"type":418,"value":7931},{"type":413,"tag":448,"props":9845,"children":9846},{"style":949},[9847],{"type":418,"value":9848}," Name",{"type":413,"tag":448,"props":9850,"children":9851},{"style":461},[9852],{"type":418,"value":8217},{"type":413,"tag":414,"props":9854,"children":9855},{},[9856],{"type":418,"value":9857},"As you can see this code is only 26 lines long:",{"type":413,"tag":5031,"props":9859,"children":9860},{},[9861,9874,9888,9900],{"type":413,"tag":2159,"props":9862,"children":9863},{},[9864,9866,9872],{"type":418,"value":9865},"there is only one route, that returns the Product identifiers and names from the table ",{"type":413,"tag":444,"props":9867,"children":9869},{"className":9868},[],[9870],{"type":418,"value":9871},"[SalesLT].[Product]",{"type":418,"value":9873}," of the database created with the previous Azure CLI script",{"type":413,"tag":2159,"props":9875,"children":9876},{},[9877,9879,9886],{"type":418,"value":9878},"the SQL query is done by using the micro ORM ",{"type":413,"tag":813,"props":9880,"children":9883},{"href":9881,"rel":9882},"https://github.com/DapperLib/Dapper",[817],[9884],{"type":418,"value":9885},"Dapper",{"type":418,"value":9887}," which simplifies the boilerplate code to query an SQL database while keeping performance",{"type":413,"tag":2159,"props":9889,"children":9890},{},[9891,9893,9898],{"type":418,"value":9892},"the result of the SQL query is mapped to a record class ",{"type":413,"tag":444,"props":9894,"children":9896},{"className":9895},[],[9897],{"type":418,"value":9727},{"type":418,"value":9899}," which is declared in one line",{"type":413,"tag":2159,"props":9901,"children":9902},{},[9903,9905,9910,9912,9917],{"type":418,"value":9904},"the code uses ",{"type":413,"tag":444,"props":9906,"children":9908},{"className":9907},[],[9909],{"type":418,"value":7585},{"type":418,"value":9911}," v3.0.0 with the ",{"type":413,"tag":444,"props":9913,"children":9915},{"className":9914},[],[9916],{"type":418,"value":7593},{"type":418,"value":8127},{"type":413,"tag":414,"props":9919,"children":9920},{},[9921],{"type":413,"tag":832,"props":9922,"children":9926},{"alt":9923,"className":9924,"src":9925},"C# code querying an SQL Database using Active Directory Default authentication mode.",[836,837],"/posts/images/sqlclient_minapi_1.png",[],{"type":413,"tag":841,"props":9928,"children":9929},{"icon":843},[9930],{"type":413,"tag":414,"props":9931,"children":9932},{},[9933,9935,9941],{"type":418,"value":9934},"To keep things simple, I am connecting to the database with the Azure AD account which is an admin of the SQL server. But I could also have assigned a role with lower permissions to my account, see ",{"type":413,"tag":813,"props":9936,"children":9939},{"href":9937,"rel":9938},"https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi#grant-permissions-to-managed-identity",[817],[9940],{"type":418,"value":1386},{"type":418,"value":9942}," for more information on how to do that.",{"type":413,"tag":420,"props":9944,"children":9945},{"id":6607},[9946],{"type":418,"value":6610},{"type":413,"tag":414,"props":9948,"children":9949},{},[9950,9952,9958],{"type":418,"value":9951},"While building an application interacting with Azure we often neglect to use mechanisms like Azure AD authentication that remove the need for secrets. But as we have seen in this article some libraries like ",{"type":413,"tag":444,"props":9953,"children":9955},{"className":9954},[],[9956],{"type":418,"value":9957},"Microsoft.Data.Sql.Client",{"type":418,"value":9959}," or the Azure SDKs allow us to do that quite easily. I love how connecting to an Azure SQL Database in C# is becoming more simple and more secure at the same time.",{"type":413,"tag":3710,"props":9961,"children":9962},{},[9963],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":9965},[9966,9967,9968,9970,9974],{"id":7626,"depth":473,"text":7629},{"id":7827,"depth":473,"text":7830},{"id":8117,"depth":473,"text":9969},"Here comes Active Directory Default authentication mode",{"id":8258,"depth":473,"text":8261,"children":9971},[9972,9973],{"id":8269,"depth":488,"text":8272},{"id":9318,"depth":488,"text":9321},{"id":6607,"depth":473,"text":6610},"content:1.posts:20.sqlclient-active-directory-authent.md","1.posts/20.sqlclient-active-directory-authent.md",{"_path":64,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":63,"description":9978,"lead":9979,"date":9980,"image":9981,"badge":9982,"tags":9983,"body":9984,"_type":3726,"_id":10330,"_source":3728,"_file":10331,"_extension":3730},"This week I learned some Azure CLI commands, how to have JSON IntelliSense in vscode and that Azure Storage Explorer was usable again.","IntelliSense in vscode, Azure CLI command to get assigned roles, and Azure Storage Explorer new version.","2021-06-07T00:00:00.000Z",{"src":4759},{"label":4761},[272,208,225,228],{"type":410,"children":9985,"toc":10325},[9986,9990,9996,10001,10014,10023,10028,10041,10047,10067,10076,10102,10122,10164,10169,10280,10286,10298,10303,10312,10317,10321],{"type":413,"tag":414,"props":9987,"children":9988},{},[9989],{"type":418,"value":9978},{"type":413,"tag":420,"props":9991,"children":9993},{"id":9992},"autocompletion-and-schema-validation-when-editing-a-json-file-in-vscode",[9994],{"type":418,"value":9995},"Autocompletion and schema validation when editing a JSON file in vscode.",{"type":413,"tag":414,"props":9997,"children":9998},{},[9999],{"type":418,"value":10000},"When you are editing a JSON file in vscode, chances are that there is a JSON schema somewhere that describes the shape of the JSON you are modifying. Wouldn't it be great if vscode could provide you suggestions and validate the JSON according to such a schema while you are typing ⌨?",{"type":413,"tag":414,"props":10002,"children":10003},{},[10004,10006,10012],{"type":418,"value":10005},"Well in fact it is possible, you just have to add at the beginning of your file a ",{"type":413,"tag":444,"props":10007,"children":10009},{"className":10008},[],[10010],{"type":418,"value":10011},"$schema",{"type":418,"value":10013}," key (with the URI of the JSON schema as the value) and you will have IntelliSense to edit your JSON in vscode.",{"type":413,"tag":414,"props":10015,"children":10016},{},[10017],{"type":413,"tag":832,"props":10018,"children":10022},{"alt":10019,"className":10020,"src":10021},"Json file in vscode.",[836,837],"/posts/images/w222021tips_vscode_1.png",[],{"type":413,"tag":414,"props":10024,"children":10025},{},[10026],{"type":418,"value":10027},"In the screenshot above, I am editing a JSON file where the linked JSON schema is a Microsoft Teams app manifest schema, and as you can see vscode gives me suggestions based on this schema.",{"type":413,"tag":414,"props":10029,"children":10030},{},[10031,10033,10040],{"type":418,"value":10032},"This is a tip that you probably already know but as far as I am concerned I only discovered it recently and it is really useful. If you want to do more advanced things like mapping some files types to specific JSON schemas you can have a look in ",{"type":413,"tag":813,"props":10034,"children":10037},{"href":10035,"rel":10036},"https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings",[817],[10038],{"type":418,"value":10039},"vscode documentation",{"type":418,"value":898},{"type":413,"tag":420,"props":10042,"children":10044},{"id":10043},"listing-assigned-roles-for-a-user-on-a-subscription-with-azure-cli",[10045],{"type":418,"value":10046},"Listing assigned roles for a user on a subscription with Azure CLI",{"type":413,"tag":414,"props":10048,"children":10049},{},[10050,10052,10065],{"type":418,"value":10051},"I recently had to list all the roles assigned to my user on a subscription. 👮‍♀️\nFor that I used the ",{"type":413,"tag":813,"props":10053,"children":10056},{"href":10054,"rel":10055},"https://docs.microsoft.com/en-us/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_list",[817],[10057,10063],{"type":413,"tag":444,"props":10058,"children":10060},{"className":10059},[],[10061],{"type":418,"value":10062},"az role assignment list",{"type":418,"value":10064}," command",{"type":418,"value":10066}," like this:",{"type":413,"tag":414,"props":10068,"children":10069},{},[10070],{"type":413,"tag":832,"props":10071,"children":10075},{"alt":10072,"className":10073,"src":10074},"Terminal showing az role assigment command.",[836,837],"/posts/images/w222021tips_azcli_1.png",[],{"type":413,"tag":414,"props":10077,"children":10078},{},[10079,10081,10086,10088,10094,10095,10101],{"type":418,"value":10080},"I am filtering the command result with the ",{"type":413,"tag":444,"props":10082,"children":10084},{"className":10083},[],[10085],{"type":418,"value":1369},{"type":418,"value":10087}," argument to only have the information I am interested in which are ",{"type":413,"tag":444,"props":10089,"children":10091},{"className":10090},[],[10092],{"type":418,"value":10093},"roleDefinitionName",{"type":418,"value":3690},{"type":413,"tag":444,"props":10096,"children":10098},{"className":10097},[],[10099],{"type":418,"value":10100},"scope",{"type":418,"value":898},{"type":413,"tag":414,"props":10103,"children":10104},{},[10105,10107,10113,10115,10121],{"type":418,"value":10106},"You can specify a subscription by using the optional parameter ",{"type":413,"tag":444,"props":10108,"children":10110},{"className":10109},[],[10111],{"type":418,"value":10112},"--subscription",{"type":418,"value":10114}," but by default, the subscription selected is the current subscription which you can see by doing an ",{"type":413,"tag":444,"props":10116,"children":10118},{"className":10117},[],[10119],{"type":418,"value":10120},"az account show",{"type":418,"value":898},{"type":413,"tag":414,"props":10123,"children":10124},{},[10125,10127,10133,10135,10141,10143,10149,10151,10162],{"type":418,"value":10126},"The variable ",{"type":413,"tag":444,"props":10128,"children":10130},{"className":10129},[],[10131],{"type":418,"value":10132},"UserId",{"type":418,"value":10134}," which is passed to the option ",{"type":413,"tag":444,"props":10136,"children":10138},{"className":10137},[],[10139],{"type":418,"value":10140},"--assignee",{"type":418,"value":10142}," contains my user id but I could have also passed my user principal name. As I was looking to list my assigned roles on a subscription in a tenant id where I am a guest, my user principal name is a bit strange with an ",{"type":413,"tag":444,"props":10144,"children":10146},{"className":10145},[],[10147],{"type":418,"value":10148},"#EXT#",{"type":418,"value":10150}," in it so I can never remember what it is. And as I don't know by heart my user id either, I use the ",{"type":413,"tag":813,"props":10152,"children":10155},{"href":10153,"rel":10154},"https://docs.microsoft.com/en-us/cli/azure/ad/user?view=azure-cli-latest#az_ad_user_show",[817],[10156],{"type":413,"tag":444,"props":10157,"children":10159},{"className":10158},[],[10160],{"type":418,"value":10161},"az ad signed-in-user show",{"type":418,"value":10163}," command to get my user id.",{"type":413,"tag":414,"props":10165,"children":10166},{},[10167],{"type":418,"value":10168},"So at the end my command to list the assigned roles to my user on the current subscription is the following:",{"type":413,"tag":437,"props":10170,"children":10172},{"className":1013,"code":10171,"language":248,"meta":401,"style":401},"az role assignment list --assignee $(az ad signed-in-user show --query \"objectId\") --query \"[*].{role:roleDefinitionName,scope:scope}\" --include-inherited\n",[10173],{"type":413,"tag":444,"props":10174,"children":10175},{"__ignoreMap":401},[10176],{"type":413,"tag":448,"props":10177,"children":10178},{"class":450,"line":451},[10179,10184,10188,10192,10197,10201,10205,10209,10213,10217,10221,10225,10229,10233,10237,10241,10245,10249,10253,10258,10262,10266,10271,10275],{"type":413,"tag":448,"props":10180,"children":10181},{"style":1029},[10182],{"type":418,"value":10183},"az role assignment list ",{"type":413,"tag":448,"props":10185,"children":10186},{"style":461},[10187],{"type":418,"value":1071},{"type":413,"tag":448,"props":10189,"children":10190},{"style":1029},[10191],{"type":418,"value":6333},{"type":413,"tag":448,"props":10193,"children":10194},{"style":461},[10195],{"type":418,"value":10196},"$(",{"type":413,"tag":448,"props":10198,"children":10199},{"style":1029},[10200],{"type":418,"value":6211},{"type":413,"tag":448,"props":10202,"children":10203},{"style":461},[10204],{"type":418,"value":1173},{"type":413,"tag":448,"props":10206,"children":10207},{"style":1029},[10208],{"type":418,"value":6220},{"type":413,"tag":448,"props":10210,"children":10211},{"style":461},[10212],{"type":418,"value":1173},{"type":413,"tag":448,"props":10214,"children":10215},{"style":1029},[10216],{"type":418,"value":6229},{"type":413,"tag":448,"props":10218,"children":10219},{"style":461},[10220],{"type":418,"value":1071},{"type":413,"tag":448,"props":10222,"children":10223},{"style":1029},[10224],{"type":418,"value":1276},{"type":413,"tag":448,"props":10226,"children":10227},{"style":461},[10228],{"type":418,"value":1183},{"type":413,"tag":448,"props":10230,"children":10231},{"style":467},[10232],{"type":418,"value":6246},{"type":413,"tag":448,"props":10234,"children":10235},{"style":461},[10236],{"type":418,"value":1183},{"type":413,"tag":448,"props":10238,"children":10239},{"style":461},[10240],{"type":418,"value":2031},{"type":413,"tag":448,"props":10242,"children":10243},{"style":461},[10244],{"type":418,"value":1095},{"type":413,"tag":448,"props":10246,"children":10247},{"style":1029},[10248],{"type":418,"value":1276},{"type":413,"tag":448,"props":10250,"children":10251},{"style":461},[10252],{"type":418,"value":1183},{"type":413,"tag":448,"props":10254,"children":10255},{"style":467},[10256],{"type":418,"value":10257},"[*].{role:roleDefinitionName,scope:scope}",{"type":413,"tag":448,"props":10259,"children":10260},{"style":461},[10261],{"type":418,"value":1183},{"type":413,"tag":448,"props":10263,"children":10264},{"style":461},[10265],{"type":418,"value":1095},{"type":413,"tag":448,"props":10267,"children":10268},{"style":1029},[10269],{"type":418,"value":10270},"include",{"type":413,"tag":448,"props":10272,"children":10273},{"style":461},[10274],{"type":418,"value":1173},{"type":413,"tag":448,"props":10276,"children":10277},{"style":1029},[10278],{"type":418,"value":10279},"inherited\n",{"type":413,"tag":420,"props":10281,"children":10283},{"id":10282},"azure-storage-explorer-just-got-better",[10284],{"type":418,"value":10285},"Azure Storage Explorer just got better!",{"type":413,"tag":414,"props":10287,"children":10288},{},[10289,10296],{"type":413,"tag":813,"props":10290,"children":10293},{"href":10291,"rel":10292},"https://azure.microsoft.com/en-us/features/storage-explorer/",[817],[10294],{"type":418,"value":10295},"Azure Storage Explorer",{"type":418,"value":10297}," is a tool to manage your Azure cloud storage resources from your desktop. Instead of going to the Azure portal and navigating between all the panes and resources, you can do everything from this tool like viewing the tables and blobs in the storage accounts you have access to.",{"type":413,"tag":414,"props":10299,"children":10300},{},[10301],{"type":418,"value":10302},"Unfortunately, if your account had access to multiple subscriptions on multiple tenants with MFA enabled, using Azure Storage Explorer was a nightmare where you had to log in to every tenant multiple times to access any storage account. If you had the correct permissions you ended up grabbing a secret connection string to access your storage account from Azure Storage Explorer but it was not a good solution (using secrets instead of your Azure AD account to access resources is never a good idea ⛔).",{"type":413,"tag":414,"props":10304,"children":10305},{},[10306],{"type":413,"tag":832,"props":10307,"children":10311},{"alt":10308,"className":10309,"src":10310},"Azure Storage Explorer account management section.",[836,837],"/posts/images/w222021tips_storageexplorer_1.png",[],{"type":413,"tag":414,"props":10313,"children":10314},{},[10315],{"type":418,"value":10316},"As you can see on the screenshot above, in v1.19.x Azure Storage Explorer account management section has been completely refreshed to allow us to control exactly the tenants and the subscriptions that we want to load. This way we only have to enter the credentials we need and Azure Storage Explorer becomes usable again! 🎉",{"type":413,"tag":414,"props":10318,"children":10319},{},[10320],{"type":418,"value":4989},{"type":413,"tag":3710,"props":10322,"children":10323},{},[10324],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":10326},[10327,10328,10329],{"id":9992,"depth":473,"text":9995},{"id":10043,"depth":473,"text":10046},{"id":10282,"depth":473,"text":10285},"content:1.posts:19.w22-2021-tips-learned-this-week.md","1.posts/19.w22-2021-tips-learned-this-week.md",{"_path":16,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":15,"description":10333,"lead":10334,"date":10335,"image":10336,"badge":10338,"tags":10339,"body":10340,"_type":3726,"_id":12815,"_source":3728,"_file":12816,"_extension":3730},"Let's jum into Azure CLI to manage Azure resources. The article will show the syntax, the main functionalities and some less-known features like Azure CLI interactive mode.","Let's jump into Azure CLI!","2019-04-08T00:00:00.000Z",{"src":10337},"/images/green-characters.jpg",{"label":3738},[225,228,230],{"type":410,"children":10341,"toc":12798},[10342,10347,10395,10408,10414,10445,10454,10459,10464,10470,10483,10488,10525,10558,10570,10613,10638,10658,10667,10679,10685,10691,10700,10726,10735,10752,10758,10763,10771,11043,11049,11062,11074,11087,12064,12069,12083,12093,12107,12116,12130,12139,12155,12161,12166,12171,12455,12460,12466,12471,12477,12482,12487,12510,12516,12521,12530,12542,12551,12556,12565,12571,12584,12589,12598,12611,12620,12625,12638,12644,12649,12662,12671,12705,12714,12733,12742,12747,12763,12780,12784,12789,12794],{"type":413,"tag":414,"props":10343,"children":10344},{},[10345],{"type":418,"value":10346},"In this article about Azure CLI, we will talk about:",{"type":413,"tag":5031,"props":10348,"children":10349},{},[10350,10359,10368,10377,10386],{"type":413,"tag":2159,"props":10351,"children":10352},{},[10353],{"type":413,"tag":813,"props":10354,"children":10356},{"href":10355},"#_1-managing-azure-resources",[10357],{"type":418,"value":10358},"Managing Azure resources",{"type":413,"tag":2159,"props":10360,"children":10361},{},[10362],{"type":413,"tag":813,"props":10363,"children":10365},{"href":10364},"#_2-azure-cli-syntax",[10366],{"type":418,"value":10367},"Azure CLI Syntax",{"type":413,"tag":2159,"props":10369,"children":10370},{},[10371],{"type":413,"tag":813,"props":10372,"children":10374},{"href":10373},"#_3-deep-dive-in-azure-cli",[10375],{"type":418,"value":10376},"Deep dive in Azure CLI",{"type":413,"tag":2159,"props":10378,"children":10379},{},[10380],{"type":413,"tag":813,"props":10381,"children":10383},{"href":10382},"#_4-where-to-use-azure-cli",[10384],{"type":418,"value":10385},"Where to use Azure CLI",{"type":413,"tag":2159,"props":10387,"children":10388},{},[10389],{"type":413,"tag":813,"props":10390,"children":10392},{"href":10391},"#_5-azure-cli-interactive-mode",[10393],{"type":418,"value":10394},"Azure CLI Interactive mode",{"type":413,"tag":414,"props":10396,"children":10397},{},[10398,10400,10407],{"type":418,"value":10399},"Azure CLI can be installed by following the instructions on ",{"type":413,"tag":813,"props":10401,"children":10404},{"href":10402,"rel":10403},"https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest",[817],[10405],{"type":418,"value":10406},"this page",{"type":418,"value":898},{"type":413,"tag":420,"props":10409,"children":10411},{"id":10410},"_1-managing-azure-resources",[10412],{"type":418,"value":10413},"1 - Managing Azure resources",{"type":413,"tag":414,"props":10415,"children":10416},{},[10417,10419,10426,10428,10435,10437,10443],{"type":418,"value":10418},"Azure resources can be managed in different ways but the main ones are the ",{"type":413,"tag":813,"props":10420,"children":10423},{"href":10421,"rel":10422},"https://portal.azure.com",[817],[10424],{"type":418,"value":10425},"Azure Portal",{"type":418,"value":10427},", ",{"type":413,"tag":813,"props":10429,"children":10432},{"href":10430,"rel":10431},"https://docs.microsoft.com/en-us/powershell/azure/",[817],[10433],{"type":418,"value":10434},"Azure PowerShell",{"type":418,"value":10436},", and ",{"type":413,"tag":813,"props":10438,"children":10441},{"href":10439,"rel":10440},"https://docs.microsoft.com/en-us/cli/azure",[817],[10442],{"type":418,"value":225},{"type":418,"value":10444},". If you are new to Azure or if you are creating resources you are not familiar with, it is always nice to have a GUI to understand what you are doing and Azure Portal is the right way to go.",{"type":413,"tag":414,"props":10446,"children":10447},{},[10448],{"type":413,"tag":832,"props":10449,"children":10453},{"alt":10450,"className":10451,"src":10452},"Azure portal home",[836,837],"/posts/images/azurecli_portal_1.png",[],{"type":413,"tag":414,"props":10455,"children":10456},{},[10457],{"type":418,"value":10458},"However, handling resources in the portal, moving from pane to pane to always do the same kind of operations can quickly become a little cumbersome. So if you want to be more productive or if you are more of a command line person, you will find in Azure CLI or Azure PowerShell really good alternatives to Azure Portal. Both of them are cross-platform tools (PowerShell Core runs on Windows, macOS, and Linux 😀) and provide the same functionalities to manage Azure resources.",{"type":413,"tag":414,"props":10460,"children":10461},{},[10462],{"type":418,"value":10463},"Until recently, when I was not using the Azure Portal I was more prompt to use Azure PowerShell than Azure CLI, probably because I was often finding samples of what I wanted to do written in PowerShell. But in fact, there are lots of commands in Azure PowerShell and even with autocomplete I am not good at remembering them. So I couldn't stop returning to using Azure Portal 😕. And yet, lately, I finally came back to the command line when I started to discover the power of Azure CLI: such a nice and above all easy tool to use and that's what I will try to show you next.",{"type":413,"tag":420,"props":10465,"children":10467},{"id":10466},"_2-azure-cli-syntax",[10468],{"type":418,"value":10469},"2 - Azure CLI Syntax",{"type":413,"tag":414,"props":10471,"children":10472},{},[10473,10475,10481],{"type":418,"value":10474},"The Azure CLI Syntax is simple to understand. For instance, the command ",{"type":413,"tag":444,"props":10476,"children":10478},{"className":10477},[],[10479],{"type":418,"value":10480},"az webapp list",{"type":418,"value":10482}," will list the WebApps in the subscription you are currently logged in.",{"type":413,"tag":414,"props":10484,"children":10485},{},[10486],{"type":418,"value":10487},"An Azure CLI command has the following structure:",{"type":413,"tag":5031,"props":10489,"children":10490},{},[10491,10504,10515],{"type":413,"tag":2159,"props":10492,"children":10493},{},[10494,10496,10502],{"type":418,"value":10495},"a ",{"type":413,"tag":10497,"props":10498,"children":10499},"strong",{},[10500],{"type":418,"value":10501},"command group",{"type":418,"value":10503}," that represents an Azure service and which can be the composition of subgroups",{"type":413,"tag":2159,"props":10505,"children":10506},{},[10507,10508,10513],{"type":418,"value":10495},{"type":413,"tag":10497,"props":10509,"children":10510},{},[10511],{"type":418,"value":10512},"command",{"type":418,"value":10514}," which is the action you want to do on the group / Azure service",{"type":413,"tag":2159,"props":10516,"children":10517},{},[10518,10523],{"type":413,"tag":10497,"props":10519,"children":10520},{},[10521],{"type":418,"value":10522},"arguments",{"type":418,"value":10524}," optionally which are a list of parameter names and values",{"type":413,"tag":414,"props":10526,"children":10527},{},[10528,10530,10536,10537,10542,10544,10549,10551,10556],{"type":418,"value":10529},"To sign in to your Azure account in your terminal, you have to execute the Azure CLI command ",{"type":413,"tag":444,"props":10531,"children":10533},{"className":10532},[],[10534],{"type":418,"value":10535},"az login",{"type":418,"value":5192},{"type":413,"tag":444,"props":10538,"children":10540},{"className":10539},[],[10541],{"type":418,"value":4560},{"type":418,"value":10543}," is the command group and ",{"type":413,"tag":444,"props":10545,"children":10547},{"className":10546},[],[10548],{"type":418,"value":8487},{"type":418,"value":10550}," is the command relative to the group/service ",{"type":413,"tag":444,"props":10552,"children":10554},{"className":10553},[],[10555],{"type":418,"value":4560},{"type":418,"value":10557}," (meaning Azure).",{"type":413,"tag":414,"props":10559,"children":10560},{},[10561,10563,10568],{"type":418,"value":10562},"In our previous example, ",{"type":413,"tag":444,"props":10564,"children":10566},{"className":10565},[],[10567],{"type":418,"value":10480},{"type":418,"value":10569}," :",{"type":413,"tag":5031,"props":10571,"children":10572},{},[10573,10597,10608],{"type":413,"tag":2159,"props":10574,"children":10575},{},[10576,10582,10584,10589,10591],{"type":413,"tag":444,"props":10577,"children":10579},{"className":10578},[],[10580],{"type":418,"value":10581},"az webapp",{"type":418,"value":10583}," was the command group composed of ",{"type":413,"tag":444,"props":10585,"children":10587},{"className":10586},[],[10588],{"type":418,"value":4560},{"type":418,"value":10590}," and its subgroup ",{"type":413,"tag":444,"props":10592,"children":10594},{"className":10593},[],[10595],{"type":418,"value":10596},"webapp",{"type":413,"tag":2159,"props":10598,"children":10599},{},[10600,10606],{"type":413,"tag":444,"props":10601,"children":10603},{"className":10602},[],[10604],{"type":418,"value":10605},"list",{"type":418,"value":10607}," was the command",{"type":413,"tag":2159,"props":10609,"children":10610},{},[10611],{"type":418,"value":10612},"no arguments here",{"type":413,"tag":414,"props":10614,"children":10615},{},[10616,10618,10623,10625,10630,10632],{"type":418,"value":10617},"We could have added some arguments to this command, like the ",{"type":413,"tag":444,"props":10619,"children":10621},{"className":10620},[],[10622],{"type":418,"value":8852},{"type":418,"value":10624}," argument (or ",{"type":413,"tag":444,"props":10626,"children":10628},{"className":10627},[],[10629],{"type":418,"value":5569},{"type":418,"value":10631},") to list only the WebApps in a specific resource group and that would have become ",{"type":413,"tag":444,"props":10633,"children":10635},{"className":10634},[],[10636],{"type":418,"value":10637},"az webapp list --resource-group 'myResourceGroupName'",{"type":413,"tag":414,"props":10639,"children":10640},{},[10641,10643,10649,10651,10656],{"type":418,"value":10642},"A few arguments are globally available arguments which means that can be used for every command. This is the case of the ",{"type":413,"tag":444,"props":10644,"children":10646},{"className":10645},[],[10647],{"type":418,"value":10648},"--help",{"type":418,"value":10650}," argument which displays help information about a command. The following example showing the use of the ",{"type":413,"tag":444,"props":10652,"children":10654},{"className":10653},[],[10655],{"type":418,"value":10648},{"type":418,"value":10657}," argument allows us to better understand the structure of an Azure CLI command.",{"type":413,"tag":414,"props":10659,"children":10660},{},[10661],{"type":413,"tag":832,"props":10662,"children":10666},{"alt":10663,"className":10664,"src":10665},"Azure CLI Help output.",[836,837],"/posts/images/azurecli_console_1.png",[],{"type":413,"tag":414,"props":10668,"children":10669},{},[10670,10672,10677],{"type":418,"value":10671},"Once used to the Azure CLI syntax, it is way more convenient than the Azure Portal and you don't have to search what Azure PowerShell command you need to use. You just have to look for the available subgroups and commands in the Azure service where you want to work (don't forget to use ",{"type":413,"tag":444,"props":10673,"children":10675},{"className":10674},[],[10676],{"type":418,"value":10648},{"type":418,"value":10678},") and you will quickly get the job done.",{"type":413,"tag":420,"props":10680,"children":10682},{"id":10681},"_3-deep-dive-in-azure-cli",[10683],{"type":418,"value":10684},"3 - Deep dive in Azure CLI",{"type":413,"tag":866,"props":10686,"children":10688},{"id":10687},"command-output",[10689],{"type":418,"value":10690},"Command output",{"type":413,"tag":414,"props":10692,"children":10693},{},[10694],{"type":413,"tag":832,"props":10695,"children":10699},{"alt":10696,"className":10697,"src":10698},"Azure CLI command outputs.",[836,837],"/posts/images/azurecli_console_2.png",[],{"type":413,"tag":414,"props":10701,"children":10702},{},[10703,10705,10711,10712,10717,10719,10725],{"type":418,"value":10704},"By default, the output format of Azure CLI commands is JSON but there are other formats you can use by specifying an output argument (",{"type":413,"tag":444,"props":10706,"children":10708},{"className":10707},[],[10709],{"type":418,"value":10710},"--output",{"type":418,"value":3813},{"type":413,"tag":444,"props":10713,"children":10715},{"className":10714},[],[10716],{"type":418,"value":5578},{"type":418,"value":10718},") like this: ",{"type":413,"tag":444,"props":10720,"children":10722},{"className":10721},[],[10723],{"type":418,"value":10724},"az group list -o table",{"type":418,"value":898},{"type":413,"tag":414,"props":10727,"children":10728},{},[10729],{"type":413,"tag":832,"props":10730,"children":10734},{"alt":10731,"className":10732,"src":10733},"Azure CLI json and table outputs.",[836,837],"/posts/images/azurecli_console_3.png",[],{"type":413,"tag":841,"props":10736,"children":10738},{"icon":10737},"i-fluent-emoji-flat-gem-stone",[10739],{"type":413,"tag":414,"props":10740,"children":10741},{},[10742,10744,10750],{"type":418,"value":10743},"The default output format can be configured using the ",{"type":413,"tag":444,"props":10745,"children":10747},{"className":10746},[],[10748],{"type":418,"value":10749},"az configure",{"type":418,"value":10751}," command. This command also allows you to configure other settings like a default resource group for your commands for instance.",{"type":413,"tag":866,"props":10753,"children":10755},{"id":10754},"using-variables",[10756],{"type":418,"value":10757},"Using variables",{"type":413,"tag":414,"props":10759,"children":10760},{},[10761],{"type":418,"value":10762},"Whether you choose to run your commands in Bash or PowerShell, you can use variables with Azure CLI, only the syntax for creating variables will change depending on the command-line shell you use.",{"type":413,"tag":841,"props":10764,"children":10765},{"icon":843},[10766],{"type":413,"tag":414,"props":10767,"children":10768},{},[10769],{"type":418,"value":10770},"The samples in this article use the PowerShell syntax.",{"type":413,"tag":437,"props":10772,"children":10774},{"className":1013,"code":10773,"language":248,"meta":401,"style":401},"$rgName = 'TestingAzureCLI'\n\n# Create a new resource group\naz group create -n $rgName -l westeurope\n\n# Create an App Service plan with the Free tier\naz appservice plan create -n $webAppName -g $rgName --sku FREE\n\n# Show the App Service plan just created \naz appservice plan show -n $webAppName -g $rgName \n\n# Store the result of the show query in a PowerShell variable\n$servicePlan = az appservice plan show -n $webAppName -g $rgName \n",[10775],{"type":413,"tag":444,"props":10776,"children":10777},{"__ignoreMap":401},[10778,10806,10813,10821,10853,10860,10868,10918,10925,10933,10974,10981,10989],{"type":413,"tag":448,"props":10779,"children":10780},{"class":450,"line":451},[10781,10785,10789,10793,10797,10802],{"type":413,"tag":448,"props":10782,"children":10783},{"style":461},[10784],{"type":418,"value":1026},{"type":413,"tag":448,"props":10786,"children":10787},{"style":1029},[10788],{"type":418,"value":5670},{"type":413,"tag":448,"props":10790,"children":10791},{"style":461},[10792],{"type":418,"value":1037},{"type":413,"tag":448,"props":10794,"children":10795},{"style":461},[10796],{"type":418,"value":637},{"type":413,"tag":448,"props":10798,"children":10799},{"style":467},[10800],{"type":418,"value":10801},"TestingAzureCLI",{"type":413,"tag":448,"props":10803,"children":10804},{"style":461},[10805],{"type":418,"value":647},{"type":413,"tag":448,"props":10807,"children":10808},{"class":450,"line":473},[10809],{"type":413,"tag":448,"props":10810,"children":10811},{"emptyLinePlaceholder":505},[10812],{"type":418,"value":508},{"type":413,"tag":448,"props":10814,"children":10815},{"class":450,"line":488},[10816],{"type":413,"tag":448,"props":10817,"children":10818},{"style":2393},[10819],{"type":418,"value":10820},"# Create a new resource group\n",{"type":413,"tag":448,"props":10822,"children":10823},{"class":450,"line":501},[10824,10828,10832,10836,10840,10844,10848],{"type":413,"tag":448,"props":10825,"children":10826},{"style":1029},[10827],{"type":418,"value":6808},{"type":413,"tag":448,"props":10829,"children":10830},{"style":461},[10831],{"type":418,"value":1173},{"type":413,"tag":448,"props":10833,"children":10834},{"style":1029},[10835],{"type":418,"value":5643},{"type":413,"tag":448,"props":10837,"children":10838},{"style":461},[10839],{"type":418,"value":1026},{"type":413,"tag":448,"props":10841,"children":10842},{"style":1029},[10843],{"type":418,"value":5670},{"type":413,"tag":448,"props":10845,"children":10846},{"style":461},[10847],{"type":418,"value":1173},{"type":413,"tag":448,"props":10849,"children":10850},{"style":1029},[10851],{"type":418,"value":10852},"l westeurope\n",{"type":413,"tag":448,"props":10854,"children":10855},{"class":450,"line":511},[10856],{"type":413,"tag":448,"props":10857,"children":10858},{"emptyLinePlaceholder":505},[10859],{"type":418,"value":508},{"type":413,"tag":448,"props":10861,"children":10862},{"class":450,"line":524},[10863],{"type":413,"tag":448,"props":10864,"children":10865},{"style":2393},[10866],{"type":418,"value":10867},"# Create an App Service plan with the Free tier\n",{"type":413,"tag":448,"props":10869,"children":10870},{"class":450,"line":542},[10871,10876,10880,10884,10888,10893,10897,10901,10905,10909,10913],{"type":413,"tag":448,"props":10872,"children":10873},{"style":1029},[10874],{"type":418,"value":10875},"az appservice plan create ",{"type":413,"tag":448,"props":10877,"children":10878},{"style":461},[10879],{"type":418,"value":1173},{"type":413,"tag":448,"props":10881,"children":10882},{"style":1029},[10883],{"type":418,"value":5643},{"type":413,"tag":448,"props":10885,"children":10886},{"style":461},[10887],{"type":418,"value":1026},{"type":413,"tag":448,"props":10889,"children":10890},{"style":1029},[10891],{"type":418,"value":10892},"webAppName ",{"type":413,"tag":448,"props":10894,"children":10895},{"style":461},[10896],{"type":418,"value":1173},{"type":413,"tag":448,"props":10898,"children":10899},{"style":1029},[10900],{"type":418,"value":5661},{"type":413,"tag":448,"props":10902,"children":10903},{"style":461},[10904],{"type":418,"value":1026},{"type":413,"tag":448,"props":10906,"children":10907},{"style":1029},[10908],{"type":418,"value":5670},{"type":413,"tag":448,"props":10910,"children":10911},{"style":461},[10912],{"type":418,"value":1071},{"type":413,"tag":448,"props":10914,"children":10915},{"style":1029},[10916],{"type":418,"value":10917},"sku FREE\n",{"type":413,"tag":448,"props":10919,"children":10920},{"class":450,"line":560},[10921],{"type":413,"tag":448,"props":10922,"children":10923},{"emptyLinePlaceholder":505},[10924],{"type":418,"value":508},{"type":413,"tag":448,"props":10926,"children":10927},{"class":450,"line":573},[10928],{"type":413,"tag":448,"props":10929,"children":10930},{"style":2393},[10931],{"type":418,"value":10932},"# Show the App Service plan just created \n",{"type":413,"tag":448,"props":10934,"children":10935},{"class":450,"line":586},[10936,10941,10945,10949,10953,10957,10961,10965,10969],{"type":413,"tag":448,"props":10937,"children":10938},{"style":1029},[10939],{"type":418,"value":10940},"az appservice plan show ",{"type":413,"tag":448,"props":10942,"children":10943},{"style":461},[10944],{"type":418,"value":1173},{"type":413,"tag":448,"props":10946,"children":10947},{"style":1029},[10948],{"type":418,"value":5643},{"type":413,"tag":448,"props":10950,"children":10951},{"style":461},[10952],{"type":418,"value":1026},{"type":413,"tag":448,"props":10954,"children":10955},{"style":1029},[10956],{"type":418,"value":10892},{"type":413,"tag":448,"props":10958,"children":10959},{"style":461},[10960],{"type":418,"value":1173},{"type":413,"tag":448,"props":10962,"children":10963},{"style":1029},[10964],{"type":418,"value":5661},{"type":413,"tag":448,"props":10966,"children":10967},{"style":461},[10968],{"type":418,"value":1026},{"type":413,"tag":448,"props":10970,"children":10971},{"style":1029},[10972],{"type":418,"value":10973},"rgName \n",{"type":413,"tag":448,"props":10975,"children":10976},{"class":450,"line":604},[10977],{"type":413,"tag":448,"props":10978,"children":10979},{"emptyLinePlaceholder":505},[10980],{"type":418,"value":508},{"type":413,"tag":448,"props":10982,"children":10983},{"class":450,"line":617},[10984],{"type":413,"tag":448,"props":10985,"children":10986},{"style":2393},[10987],{"type":418,"value":10988},"# Store the result of the show query in a PowerShell variable\n",{"type":413,"tag":448,"props":10990,"children":10991},{"class":450,"line":650},[10992,10996,11001,11005,11010,11014,11018,11022,11026,11030,11034,11038],{"type":413,"tag":448,"props":10993,"children":10994},{"style":461},[10995],{"type":418,"value":1026},{"type":413,"tag":448,"props":10997,"children":10998},{"style":1029},[10999],{"type":418,"value":11000},"servicePlan ",{"type":413,"tag":448,"props":11002,"children":11003},{"style":461},[11004],{"type":418,"value":1037},{"type":413,"tag":448,"props":11006,"children":11007},{"style":1029},[11008],{"type":418,"value":11009}," az appservice plan show ",{"type":413,"tag":448,"props":11011,"children":11012},{"style":461},[11013],{"type":418,"value":1173},{"type":413,"tag":448,"props":11015,"children":11016},{"style":1029},[11017],{"type":418,"value":5643},{"type":413,"tag":448,"props":11019,"children":11020},{"style":461},[11021],{"type":418,"value":1026},{"type":413,"tag":448,"props":11023,"children":11024},{"style":1029},[11025],{"type":418,"value":10892},{"type":413,"tag":448,"props":11027,"children":11028},{"style":461},[11029],{"type":418,"value":1173},{"type":413,"tag":448,"props":11031,"children":11032},{"style":1029},[11033],{"type":418,"value":5661},{"type":413,"tag":448,"props":11035,"children":11036},{"style":461},[11037],{"type":418,"value":1026},{"type":413,"tag":448,"props":11039,"children":11040},{"style":1029},[11041],{"type":418,"value":11042},"rgName\n",{"type":413,"tag":866,"props":11044,"children":11046},{"id":11045},"jmespath",[11047],{"type":418,"value":11048},"JMESPath",{"type":413,"tag":414,"props":11050,"children":11051},{},[11052,11054,11060],{"type":418,"value":11053},"If you don't know ",{"type":413,"tag":813,"props":11055,"children":11058},{"href":11056,"rel":11057},"http://jmespath.org/",[817],[11059],{"type":418,"value":11048},{"type":418,"value":11061},", it is a query language for JSON that allows to extract and transform elements from a JSON document or CLI output in the context of Azure CLI.",{"type":413,"tag":414,"props":11063,"children":11064},{},[11065,11067,11072],{"type":418,"value":11066},"To use JMESPath you have to add in your CLI command the argument ",{"type":413,"tag":444,"props":11068,"children":11070},{"className":11069},[],[11071],{"type":418,"value":1369},{"type":418,"value":11073}," followed by your JMESPath query.\nLet's see that with some examples.",{"type":413,"tag":414,"props":11075,"children":11076},{},[11077,11079,11085],{"type":418,"value":11078},"The query ",{"type":413,"tag":444,"props":11080,"children":11082},{"className":11081},[],[11083],{"type":418,"value":11084},"az group list",{"type":418,"value":11086}," executed on my subscription returns the following JSON:",{"type":413,"tag":437,"props":11088,"children":11090},{"className":4035,"code":11089,"language":4037,"meta":401,"style":401},"[\n  {\n    \"id\": \"/subscriptions/********-****-****-****-************/resourceGroups/CloudShellRG\",\n    \"location\": \"westeurope\",\n    \"managedBy\": null,\n    \"name\": \"CloudShellRG\",\n    \"properties\": {\n      \"provisioningState\": \"Succeeded\"\n    },\n    \"tags\": {\n      \"Environment\": \"Production\"\n    },\n    \"type\": null\n  },\n  {\n    \"id\": \"/subscriptions/********-****-****-****-************/resourceGroups/MyApp1ResourceGroup\",\n    \"location\": \"canadacentral\",\n    \"managedBy\": null,\n    \"name\": \"MyApp1ResourceGroup\",\n    \"properties\": {\n      \"provisioningState\": \"Succeeded\"\n    },\n    \"tags\": {\n      \"Department\": \"RH\",\n      \"Environment\": \"Dev\"\n    },\n    \"type\": null\n  },\n  {\n    \"id\": \"/subscriptions/********-****-****-****-************/resourceGroups/TestingAzureCLI\",\n    \"location\": \"westeurope\",\n    \"managedBy\": null,\n    \"name\": \"TestingAzureCLI\",\n    \"properties\": {\n      \"provisioningState\": \"Succeeded\"\n    },\n    \"tags\": {\n      \"Department\": \"IT\",\n      \"Environment\": \"Production\"\n    },\n    \"type\": null\n  }\n]\n",[11091],{"type":413,"tag":444,"props":11092,"children":11093},{"__ignoreMap":401},[11094,11102,11109,11145,11181,11206,11242,11267,11301,11309,11333,11365,11372,11397,11405,11412,11448,11484,11507,11543,11566,11597,11604,11627,11664,11696,11703,11726,11733,11740,11776,11811,11834,11869,11892,11923,11930,11953,11988,12019,12026,12049,12056],{"type":413,"tag":448,"props":11095,"children":11096},{"class":450,"line":451},[11097],{"type":413,"tag":448,"props":11098,"children":11099},{"style":461},[11100],{"type":418,"value":11101},"[\n",{"type":413,"tag":448,"props":11103,"children":11104},{"class":450,"line":473},[11105],{"type":413,"tag":448,"props":11106,"children":11107},{"style":461},[11108],{"type":418,"value":4078},{"type":413,"tag":448,"props":11110,"children":11111},{"class":450,"line":488},[11112,11116,11120,11124,11128,11132,11137,11141],{"type":413,"tag":448,"props":11113,"children":11114},{"style":461},[11115],{"type":418,"value":4086},{"type":413,"tag":448,"props":11117,"children":11118},{"style":4059},[11119],{"type":418,"value":1285},{"type":413,"tag":448,"props":11121,"children":11122},{"style":461},[11123],{"type":418,"value":1183},{"type":413,"tag":448,"props":11125,"children":11126},{"style":461},[11127],{"type":418,"value":464},{"type":413,"tag":448,"props":11129,"children":11130},{"style":461},[11131],{"type":418,"value":995},{"type":413,"tag":448,"props":11133,"children":11134},{"style":467},[11135],{"type":418,"value":11136},"/subscriptions/********-****-****-****-************/resourceGroups/CloudShellRG",{"type":413,"tag":448,"props":11138,"children":11139},{"style":461},[11140],{"type":418,"value":1183},{"type":413,"tag":448,"props":11142,"children":11143},{"style":461},[11144],{"type":418,"value":4117},{"type":413,"tag":448,"props":11146,"children":11147},{"class":450,"line":501},[11148,11152,11156,11160,11164,11168,11173,11177],{"type":413,"tag":448,"props":11149,"children":11150},{"style":461},[11151],{"type":418,"value":4086},{"type":413,"tag":448,"props":11153,"children":11154},{"style":4059},[11155],{"type":418,"value":5320},{"type":413,"tag":448,"props":11157,"children":11158},{"style":461},[11159],{"type":418,"value":1183},{"type":413,"tag":448,"props":11161,"children":11162},{"style":461},[11163],{"type":418,"value":464},{"type":413,"tag":448,"props":11165,"children":11166},{"style":461},[11167],{"type":418,"value":995},{"type":413,"tag":448,"props":11169,"children":11170},{"style":467},[11171],{"type":418,"value":11172},"westeurope",{"type":413,"tag":448,"props":11174,"children":11175},{"style":461},[11176],{"type":418,"value":1183},{"type":413,"tag":448,"props":11178,"children":11179},{"style":461},[11180],{"type":418,"value":4117},{"type":413,"tag":448,"props":11182,"children":11183},{"class":450,"line":511},[11184,11188,11193,11197,11201],{"type":413,"tag":448,"props":11185,"children":11186},{"style":461},[11187],{"type":418,"value":4086},{"type":413,"tag":448,"props":11189,"children":11190},{"style":4059},[11191],{"type":418,"value":11192},"managedBy",{"type":413,"tag":448,"props":11194,"children":11195},{"style":461},[11196],{"type":418,"value":1183},{"type":413,"tag":448,"props":11198,"children":11199},{"style":461},[11200],{"type":418,"value":464},{"type":413,"tag":448,"props":11202,"children":11203},{"style":461},[11204],{"type":418,"value":11205}," null,\n",{"type":413,"tag":448,"props":11207,"children":11208},{"class":450,"line":524},[11209,11213,11217,11221,11225,11229,11234,11238],{"type":413,"tag":448,"props":11210,"children":11211},{"style":461},[11212],{"type":418,"value":4086},{"type":413,"tag":448,"props":11214,"children":11215},{"style":4059},[11216],{"type":418,"value":458},{"type":413,"tag":448,"props":11218,"children":11219},{"style":461},[11220],{"type":418,"value":1183},{"type":413,"tag":448,"props":11222,"children":11223},{"style":461},[11224],{"type":418,"value":464},{"type":413,"tag":448,"props":11226,"children":11227},{"style":461},[11228],{"type":418,"value":995},{"type":413,"tag":448,"props":11230,"children":11231},{"style":467},[11232],{"type":418,"value":11233},"CloudShellRG",{"type":413,"tag":448,"props":11235,"children":11236},{"style":461},[11237],{"type":418,"value":1183},{"type":413,"tag":448,"props":11239,"children":11240},{"style":461},[11241],{"type":418,"value":4117},{"type":413,"tag":448,"props":11243,"children":11244},{"class":450,"line":542},[11245,11249,11254,11258,11262],{"type":413,"tag":448,"props":11246,"children":11247},{"style":461},[11248],{"type":418,"value":4086},{"type":413,"tag":448,"props":11250,"children":11251},{"style":4059},[11252],{"type":418,"value":11253},"properties",{"type":413,"tag":448,"props":11255,"children":11256},{"style":461},[11257],{"type":418,"value":1183},{"type":413,"tag":448,"props":11259,"children":11260},{"style":461},[11261],{"type":418,"value":464},{"type":413,"tag":448,"props":11263,"children":11264},{"style":461},[11265],{"type":418,"value":11266}," {\n",{"type":413,"tag":448,"props":11268,"children":11269},{"class":450,"line":560},[11270,11275,11280,11284,11288,11292,11297],{"type":413,"tag":448,"props":11271,"children":11272},{"style":461},[11273],{"type":418,"value":11274},"      \"",{"type":413,"tag":448,"props":11276,"children":11277},{"style":949},[11278],{"type":418,"value":11279},"provisioningState",{"type":413,"tag":448,"props":11281,"children":11282},{"style":461},[11283],{"type":418,"value":1183},{"type":413,"tag":448,"props":11285,"children":11286},{"style":461},[11287],{"type":418,"value":464},{"type":413,"tag":448,"props":11289,"children":11290},{"style":461},[11291],{"type":418,"value":995},{"type":413,"tag":448,"props":11293,"children":11294},{"style":467},[11295],{"type":418,"value":11296},"Succeeded",{"type":413,"tag":448,"props":11298,"children":11299},{"style":461},[11300],{"type":418,"value":1005},{"type":413,"tag":448,"props":11302,"children":11303},{"class":450,"line":573},[11304],{"type":413,"tag":448,"props":11305,"children":11306},{"style":461},[11307],{"type":418,"value":11308},"    },\n",{"type":413,"tag":448,"props":11310,"children":11311},{"class":450,"line":586},[11312,11316,11321,11325,11329],{"type":413,"tag":448,"props":11313,"children":11314},{"style":461},[11315],{"type":418,"value":4086},{"type":413,"tag":448,"props":11317,"children":11318},{"style":4059},[11319],{"type":418,"value":11320},"tags",{"type":413,"tag":448,"props":11322,"children":11323},{"style":461},[11324],{"type":418,"value":1183},{"type":413,"tag":448,"props":11326,"children":11327},{"style":461},[11328],{"type":418,"value":464},{"type":413,"tag":448,"props":11330,"children":11331},{"style":461},[11332],{"type":418,"value":11266},{"type":413,"tag":448,"props":11334,"children":11335},{"class":450,"line":604},[11336,11340,11344,11348,11352,11356,11361],{"type":413,"tag":448,"props":11337,"children":11338},{"style":461},[11339],{"type":418,"value":11274},{"type":413,"tag":448,"props":11341,"children":11342},{"style":949},[11343],{"type":418,"value":9520},{"type":413,"tag":448,"props":11345,"children":11346},{"style":461},[11347],{"type":418,"value":1183},{"type":413,"tag":448,"props":11349,"children":11350},{"style":461},[11351],{"type":418,"value":464},{"type":413,"tag":448,"props":11353,"children":11354},{"style":461},[11355],{"type":418,"value":995},{"type":413,"tag":448,"props":11357,"children":11358},{"style":467},[11359],{"type":418,"value":11360},"Production",{"type":413,"tag":448,"props":11362,"children":11363},{"style":461},[11364],{"type":418,"value":1005},{"type":413,"tag":448,"props":11366,"children":11367},{"class":450,"line":617},[11368],{"type":413,"tag":448,"props":11369,"children":11370},{"style":461},[11371],{"type":418,"value":11308},{"type":413,"tag":448,"props":11373,"children":11374},{"class":450,"line":650},[11375,11379,11384,11388,11392],{"type":413,"tag":448,"props":11376,"children":11377},{"style":461},[11378],{"type":418,"value":4086},{"type":413,"tag":448,"props":11380,"children":11381},{"style":4059},[11382],{"type":418,"value":11383},"type",{"type":413,"tag":448,"props":11385,"children":11386},{"style":461},[11387],{"type":418,"value":1183},{"type":413,"tag":448,"props":11389,"children":11390},{"style":461},[11391],{"type":418,"value":464},{"type":413,"tag":448,"props":11393,"children":11394},{"style":461},[11395],{"type":418,"value":11396}," null\n",{"type":413,"tag":448,"props":11398,"children":11399},{"class":450,"line":668},[11400],{"type":413,"tag":448,"props":11401,"children":11402},{"style":461},[11403],{"type":418,"value":11404},"  },\n",{"type":413,"tag":448,"props":11406,"children":11407},{"class":450,"line":681},[11408],{"type":413,"tag":448,"props":11409,"children":11410},{"style":461},[11411],{"type":418,"value":4078},{"type":413,"tag":448,"props":11413,"children":11414},{"class":450,"line":699},[11415,11419,11423,11427,11431,11435,11440,11444],{"type":413,"tag":448,"props":11416,"children":11417},{"style":461},[11418],{"type":418,"value":4086},{"type":413,"tag":448,"props":11420,"children":11421},{"style":4059},[11422],{"type":418,"value":1285},{"type":413,"tag":448,"props":11424,"children":11425},{"style":461},[11426],{"type":418,"value":1183},{"type":413,"tag":448,"props":11428,"children":11429},{"style":461},[11430],{"type":418,"value":464},{"type":413,"tag":448,"props":11432,"children":11433},{"style":461},[11434],{"type":418,"value":995},{"type":413,"tag":448,"props":11436,"children":11437},{"style":467},[11438],{"type":418,"value":11439},"/subscriptions/********-****-****-****-************/resourceGroups/MyApp1ResourceGroup",{"type":413,"tag":448,"props":11441,"children":11442},{"style":461},[11443],{"type":418,"value":1183},{"type":413,"tag":448,"props":11445,"children":11446},{"style":461},[11447],{"type":418,"value":4117},{"type":413,"tag":448,"props":11449,"children":11450},{"class":450,"line":717},[11451,11455,11459,11463,11467,11471,11476,11480],{"type":413,"tag":448,"props":11452,"children":11453},{"style":461},[11454],{"type":418,"value":4086},{"type":413,"tag":448,"props":11456,"children":11457},{"style":4059},[11458],{"type":418,"value":5320},{"type":413,"tag":448,"props":11460,"children":11461},{"style":461},[11462],{"type":418,"value":1183},{"type":413,"tag":448,"props":11464,"children":11465},{"style":461},[11466],{"type":418,"value":464},{"type":413,"tag":448,"props":11468,"children":11469},{"style":461},[11470],{"type":418,"value":995},{"type":413,"tag":448,"props":11472,"children":11473},{"style":467},[11474],{"type":418,"value":11475},"canadacentral",{"type":413,"tag":448,"props":11477,"children":11478},{"style":461},[11479],{"type":418,"value":1183},{"type":413,"tag":448,"props":11481,"children":11482},{"style":461},[11483],{"type":418,"value":4117},{"type":413,"tag":448,"props":11485,"children":11486},{"class":450,"line":735},[11487,11491,11495,11499,11503],{"type":413,"tag":448,"props":11488,"children":11489},{"style":461},[11490],{"type":418,"value":4086},{"type":413,"tag":448,"props":11492,"children":11493},{"style":4059},[11494],{"type":418,"value":11192},{"type":413,"tag":448,"props":11496,"children":11497},{"style":461},[11498],{"type":418,"value":1183},{"type":413,"tag":448,"props":11500,"children":11501},{"style":461},[11502],{"type":418,"value":464},{"type":413,"tag":448,"props":11504,"children":11505},{"style":461},[11506],{"type":418,"value":11205},{"type":413,"tag":448,"props":11508,"children":11509},{"class":450,"line":743},[11510,11514,11518,11522,11526,11530,11535,11539],{"type":413,"tag":448,"props":11511,"children":11512},{"style":461},[11513],{"type":418,"value":4086},{"type":413,"tag":448,"props":11515,"children":11516},{"style":4059},[11517],{"type":418,"value":458},{"type":413,"tag":448,"props":11519,"children":11520},{"style":461},[11521],{"type":418,"value":1183},{"type":413,"tag":448,"props":11523,"children":11524},{"style":461},[11525],{"type":418,"value":464},{"type":413,"tag":448,"props":11527,"children":11528},{"style":461},[11529],{"type":418,"value":995},{"type":413,"tag":448,"props":11531,"children":11532},{"style":467},[11533],{"type":418,"value":11534},"MyApp1ResourceGroup",{"type":413,"tag":448,"props":11536,"children":11537},{"style":461},[11538],{"type":418,"value":1183},{"type":413,"tag":448,"props":11540,"children":11541},{"style":461},[11542],{"type":418,"value":4117},{"type":413,"tag":448,"props":11544,"children":11545},{"class":450,"line":772},[11546,11550,11554,11558,11562],{"type":413,"tag":448,"props":11547,"children":11548},{"style":461},[11549],{"type":418,"value":4086},{"type":413,"tag":448,"props":11551,"children":11552},{"style":4059},[11553],{"type":418,"value":11253},{"type":413,"tag":448,"props":11555,"children":11556},{"style":461},[11557],{"type":418,"value":1183},{"type":413,"tag":448,"props":11559,"children":11560},{"style":461},[11561],{"type":418,"value":464},{"type":413,"tag":448,"props":11563,"children":11564},{"style":461},[11565],{"type":418,"value":11266},{"type":413,"tag":448,"props":11567,"children":11568},{"class":450,"line":791},[11569,11573,11577,11581,11585,11589,11593],{"type":413,"tag":448,"props":11570,"children":11571},{"style":461},[11572],{"type":418,"value":11274},{"type":413,"tag":448,"props":11574,"children":11575},{"style":949},[11576],{"type":418,"value":11279},{"type":413,"tag":448,"props":11578,"children":11579},{"style":461},[11580],{"type":418,"value":1183},{"type":413,"tag":448,"props":11582,"children":11583},{"style":461},[11584],{"type":418,"value":464},{"type":413,"tag":448,"props":11586,"children":11587},{"style":461},[11588],{"type":418,"value":995},{"type":413,"tag":448,"props":11590,"children":11591},{"style":467},[11592],{"type":418,"value":11296},{"type":413,"tag":448,"props":11594,"children":11595},{"style":461},[11596],{"type":418,"value":1005},{"type":413,"tag":448,"props":11598,"children":11599},{"class":450,"line":800},[11600],{"type":413,"tag":448,"props":11601,"children":11602},{"style":461},[11603],{"type":418,"value":11308},{"type":413,"tag":448,"props":11605,"children":11606},{"class":450,"line":2909},[11607,11611,11615,11619,11623],{"type":413,"tag":448,"props":11608,"children":11609},{"style":461},[11610],{"type":418,"value":4086},{"type":413,"tag":448,"props":11612,"children":11613},{"style":4059},[11614],{"type":418,"value":11320},{"type":413,"tag":448,"props":11616,"children":11617},{"style":461},[11618],{"type":418,"value":1183},{"type":413,"tag":448,"props":11620,"children":11621},{"style":461},[11622],{"type":418,"value":464},{"type":413,"tag":448,"props":11624,"children":11625},{"style":461},[11626],{"type":418,"value":11266},{"type":413,"tag":448,"props":11628,"children":11629},{"class":450,"line":3021},[11630,11634,11639,11643,11647,11651,11656,11660],{"type":413,"tag":448,"props":11631,"children":11632},{"style":461},[11633],{"type":418,"value":11274},{"type":413,"tag":448,"props":11635,"children":11636},{"style":949},[11637],{"type":418,"value":11638},"Department",{"type":413,"tag":448,"props":11640,"children":11641},{"style":461},[11642],{"type":418,"value":1183},{"type":413,"tag":448,"props":11644,"children":11645},{"style":461},[11646],{"type":418,"value":464},{"type":413,"tag":448,"props":11648,"children":11649},{"style":461},[11650],{"type":418,"value":995},{"type":413,"tag":448,"props":11652,"children":11653},{"style":467},[11654],{"type":418,"value":11655},"RH",{"type":413,"tag":448,"props":11657,"children":11658},{"style":461},[11659],{"type":418,"value":1183},{"type":413,"tag":448,"props":11661,"children":11662},{"style":461},[11663],{"type":418,"value":4117},{"type":413,"tag":448,"props":11665,"children":11666},{"class":450,"line":3029},[11667,11671,11675,11679,11683,11687,11692],{"type":413,"tag":448,"props":11668,"children":11669},{"style":461},[11670],{"type":418,"value":11274},{"type":413,"tag":448,"props":11672,"children":11673},{"style":949},[11674],{"type":418,"value":9520},{"type":413,"tag":448,"props":11676,"children":11677},{"style":461},[11678],{"type":418,"value":1183},{"type":413,"tag":448,"props":11680,"children":11681},{"style":461},[11682],{"type":418,"value":464},{"type":413,"tag":448,"props":11684,"children":11685},{"style":461},[11686],{"type":418,"value":995},{"type":413,"tag":448,"props":11688,"children":11689},{"style":467},[11690],{"type":418,"value":11691},"Dev",{"type":413,"tag":448,"props":11693,"children":11694},{"style":461},[11695],{"type":418,"value":1005},{"type":413,"tag":448,"props":11697,"children":11698},{"class":450,"line":3038},[11699],{"type":413,"tag":448,"props":11700,"children":11701},{"style":461},[11702],{"type":418,"value":11308},{"type":413,"tag":448,"props":11704,"children":11705},{"class":450,"line":3062},[11706,11710,11714,11718,11722],{"type":413,"tag":448,"props":11707,"children":11708},{"style":461},[11709],{"type":418,"value":4086},{"type":413,"tag":448,"props":11711,"children":11712},{"style":4059},[11713],{"type":418,"value":11383},{"type":413,"tag":448,"props":11715,"children":11716},{"style":461},[11717],{"type":418,"value":1183},{"type":413,"tag":448,"props":11719,"children":11720},{"style":461},[11721],{"type":418,"value":464},{"type":413,"tag":448,"props":11723,"children":11724},{"style":461},[11725],{"type":418,"value":11396},{"type":413,"tag":448,"props":11727,"children":11728},{"class":450,"line":3086},[11729],{"type":413,"tag":448,"props":11730,"children":11731},{"style":461},[11732],{"type":418,"value":11404},{"type":413,"tag":448,"props":11734,"children":11735},{"class":450,"line":3110},[11736],{"type":413,"tag":448,"props":11737,"children":11738},{"style":461},[11739],{"type":418,"value":4078},{"type":413,"tag":448,"props":11741,"children":11742},{"class":450,"line":3150},[11743,11747,11751,11755,11759,11763,11768,11772],{"type":413,"tag":448,"props":11744,"children":11745},{"style":461},[11746],{"type":418,"value":4086},{"type":413,"tag":448,"props":11748,"children":11749},{"style":4059},[11750],{"type":418,"value":1285},{"type":413,"tag":448,"props":11752,"children":11753},{"style":461},[11754],{"type":418,"value":1183},{"type":413,"tag":448,"props":11756,"children":11757},{"style":461},[11758],{"type":418,"value":464},{"type":413,"tag":448,"props":11760,"children":11761},{"style":461},[11762],{"type":418,"value":995},{"type":413,"tag":448,"props":11764,"children":11765},{"style":467},[11766],{"type":418,"value":11767},"/subscriptions/********-****-****-****-************/resourceGroups/TestingAzureCLI",{"type":413,"tag":448,"props":11769,"children":11770},{"style":461},[11771],{"type":418,"value":1183},{"type":413,"tag":448,"props":11773,"children":11774},{"style":461},[11775],{"type":418,"value":4117},{"type":413,"tag":448,"props":11777,"children":11778},{"class":450,"line":3182},[11779,11783,11787,11791,11795,11799,11803,11807],{"type":413,"tag":448,"props":11780,"children":11781},{"style":461},[11782],{"type":418,"value":4086},{"type":413,"tag":448,"props":11784,"children":11785},{"style":4059},[11786],{"type":418,"value":5320},{"type":413,"tag":448,"props":11788,"children":11789},{"style":461},[11790],{"type":418,"value":1183},{"type":413,"tag":448,"props":11792,"children":11793},{"style":461},[11794],{"type":418,"value":464},{"type":413,"tag":448,"props":11796,"children":11797},{"style":461},[11798],{"type":418,"value":995},{"type":413,"tag":448,"props":11800,"children":11801},{"style":467},[11802],{"type":418,"value":11172},{"type":413,"tag":448,"props":11804,"children":11805},{"style":461},[11806],{"type":418,"value":1183},{"type":413,"tag":448,"props":11808,"children":11809},{"style":461},[11810],{"type":418,"value":4117},{"type":413,"tag":448,"props":11812,"children":11813},{"class":450,"line":3202},[11814,11818,11822,11826,11830],{"type":413,"tag":448,"props":11815,"children":11816},{"style":461},[11817],{"type":418,"value":4086},{"type":413,"tag":448,"props":11819,"children":11820},{"style":4059},[11821],{"type":418,"value":11192},{"type":413,"tag":448,"props":11823,"children":11824},{"style":461},[11825],{"type":418,"value":1183},{"type":413,"tag":448,"props":11827,"children":11828},{"style":461},[11829],{"type":418,"value":464},{"type":413,"tag":448,"props":11831,"children":11832},{"style":461},[11833],{"type":418,"value":11205},{"type":413,"tag":448,"props":11835,"children":11836},{"class":450,"line":3218},[11837,11841,11845,11849,11853,11857,11861,11865],{"type":413,"tag":448,"props":11838,"children":11839},{"style":461},[11840],{"type":418,"value":4086},{"type":413,"tag":448,"props":11842,"children":11843},{"style":4059},[11844],{"type":418,"value":458},{"type":413,"tag":448,"props":11846,"children":11847},{"style":461},[11848],{"type":418,"value":1183},{"type":413,"tag":448,"props":11850,"children":11851},{"style":461},[11852],{"type":418,"value":464},{"type":413,"tag":448,"props":11854,"children":11855},{"style":461},[11856],{"type":418,"value":995},{"type":413,"tag":448,"props":11858,"children":11859},{"style":467},[11860],{"type":418,"value":10801},{"type":413,"tag":448,"props":11862,"children":11863},{"style":461},[11864],{"type":418,"value":1183},{"type":413,"tag":448,"props":11866,"children":11867},{"style":461},[11868],{"type":418,"value":4117},{"type":413,"tag":448,"props":11870,"children":11871},{"class":450,"line":3226},[11872,11876,11880,11884,11888],{"type":413,"tag":448,"props":11873,"children":11874},{"style":461},[11875],{"type":418,"value":4086},{"type":413,"tag":448,"props":11877,"children":11878},{"style":4059},[11879],{"type":418,"value":11253},{"type":413,"tag":448,"props":11881,"children":11882},{"style":461},[11883],{"type":418,"value":1183},{"type":413,"tag":448,"props":11885,"children":11886},{"style":461},[11887],{"type":418,"value":464},{"type":413,"tag":448,"props":11889,"children":11890},{"style":461},[11891],{"type":418,"value":11266},{"type":413,"tag":448,"props":11893,"children":11894},{"class":450,"line":3234},[11895,11899,11903,11907,11911,11915,11919],{"type":413,"tag":448,"props":11896,"children":11897},{"style":461},[11898],{"type":418,"value":11274},{"type":413,"tag":448,"props":11900,"children":11901},{"style":949},[11902],{"type":418,"value":11279},{"type":413,"tag":448,"props":11904,"children":11905},{"style":461},[11906],{"type":418,"value":1183},{"type":413,"tag":448,"props":11908,"children":11909},{"style":461},[11910],{"type":418,"value":464},{"type":413,"tag":448,"props":11912,"children":11913},{"style":461},[11914],{"type":418,"value":995},{"type":413,"tag":448,"props":11916,"children":11917},{"style":467},[11918],{"type":418,"value":11296},{"type":413,"tag":448,"props":11920,"children":11921},{"style":461},[11922],{"type":418,"value":1005},{"type":413,"tag":448,"props":11924,"children":11925},{"class":450,"line":3242},[11926],{"type":413,"tag":448,"props":11927,"children":11928},{"style":461},[11929],{"type":418,"value":11308},{"type":413,"tag":448,"props":11931,"children":11932},{"class":450,"line":3251},[11933,11937,11941,11945,11949],{"type":413,"tag":448,"props":11934,"children":11935},{"style":461},[11936],{"type":418,"value":4086},{"type":413,"tag":448,"props":11938,"children":11939},{"style":4059},[11940],{"type":418,"value":11320},{"type":413,"tag":448,"props":11942,"children":11943},{"style":461},[11944],{"type":418,"value":1183},{"type":413,"tag":448,"props":11946,"children":11947},{"style":461},[11948],{"type":418,"value":464},{"type":413,"tag":448,"props":11950,"children":11951},{"style":461},[11952],{"type":418,"value":11266},{"type":413,"tag":448,"props":11954,"children":11955},{"class":450,"line":3260},[11956,11960,11964,11968,11972,11976,11980,11984],{"type":413,"tag":448,"props":11957,"children":11958},{"style":461},[11959],{"type":418,"value":11274},{"type":413,"tag":448,"props":11961,"children":11962},{"style":949},[11963],{"type":418,"value":11638},{"type":413,"tag":448,"props":11965,"children":11966},{"style":461},[11967],{"type":418,"value":1183},{"type":413,"tag":448,"props":11969,"children":11970},{"style":461},[11971],{"type":418,"value":464},{"type":413,"tag":448,"props":11973,"children":11974},{"style":461},[11975],{"type":418,"value":995},{"type":413,"tag":448,"props":11977,"children":11978},{"style":467},[11979],{"type":418,"value":269},{"type":413,"tag":448,"props":11981,"children":11982},{"style":461},[11983],{"type":418,"value":1183},{"type":413,"tag":448,"props":11985,"children":11986},{"style":461},[11987],{"type":418,"value":4117},{"type":413,"tag":448,"props":11989,"children":11990},{"class":450,"line":3360},[11991,11995,11999,12003,12007,12011,12015],{"type":413,"tag":448,"props":11992,"children":11993},{"style":461},[11994],{"type":418,"value":11274},{"type":413,"tag":448,"props":11996,"children":11997},{"style":949},[11998],{"type":418,"value":9520},{"type":413,"tag":448,"props":12000,"children":12001},{"style":461},[12002],{"type":418,"value":1183},{"type":413,"tag":448,"props":12004,"children":12005},{"style":461},[12006],{"type":418,"value":464},{"type":413,"tag":448,"props":12008,"children":12009},{"style":461},[12010],{"type":418,"value":995},{"type":413,"tag":448,"props":12012,"children":12013},{"style":467},[12014],{"type":418,"value":11360},{"type":413,"tag":448,"props":12016,"children":12017},{"style":461},[12018],{"type":418,"value":1005},{"type":413,"tag":448,"props":12020,"children":12021},{"class":450,"line":3368},[12022],{"type":413,"tag":448,"props":12023,"children":12024},{"style":461},[12025],{"type":418,"value":11308},{"type":413,"tag":448,"props":12027,"children":12028},{"class":450,"line":3377},[12029,12033,12037,12041,12045],{"type":413,"tag":448,"props":12030,"children":12031},{"style":461},[12032],{"type":418,"value":4086},{"type":413,"tag":448,"props":12034,"children":12035},{"style":4059},[12036],{"type":418,"value":11383},{"type":413,"tag":448,"props":12038,"children":12039},{"style":461},[12040],{"type":418,"value":1183},{"type":413,"tag":448,"props":12042,"children":12043},{"style":461},[12044],{"type":418,"value":464},{"type":413,"tag":448,"props":12046,"children":12047},{"style":461},[12048],{"type":418,"value":11396},{"type":413,"tag":448,"props":12050,"children":12051},{"class":450,"line":3425},[12052],{"type":413,"tag":448,"props":12053,"children":12054},{"style":461},[12055],{"type":418,"value":4195},{"type":413,"tag":448,"props":12057,"children":12058},{"class":450,"line":3433},[12059],{"type":413,"tag":448,"props":12060,"children":12061},{"style":461},[12062],{"type":418,"value":12063},"]\n",{"type":413,"tag":414,"props":12065,"children":12066},{},[12067],{"type":418,"value":12068},"Here are some CLI commands that query more precisely the resource groups:",{"type":413,"tag":5031,"props":12070,"children":12071},{},[12072],{"type":413,"tag":2159,"props":12073,"children":12074},{},[12075,12077],{"type":418,"value":12076},"Select only the resource groups names with ",{"type":413,"tag":444,"props":12078,"children":12080},{"className":12079},[],[12081],{"type":418,"value":12082},"az group list --query '[].name'",{"type":413,"tag":414,"props":12084,"children":12085},{},[12086],{"type":413,"tag":832,"props":12087,"children":12092},{"alt":12088,"className":12089,"src":12090,"width":12091},"az group command output using JMESPath property selection.",[836,837],"/posts/images/azurecli_jmespath_2.png",1000,[],{"type":413,"tag":5031,"props":12094,"children":12095},{},[12096],{"type":413,"tag":2159,"props":12097,"children":12098},{},[12099,12101],{"type":418,"value":12100},"Filter on resource groups in West Europe with ",{"type":413,"tag":444,"props":12102,"children":12104},{"className":12103},[],[12105],{"type":418,"value":12106},"az group list --query \"[?location=='westeurope']\"",{"type":413,"tag":414,"props":12108,"children":12109},{},[12110],{"type":413,"tag":832,"props":12111,"children":12115},{"alt":12112,"className":12113,"src":12114,"width":12091},"az group command output using JMESPath property filter.",[836,837],"/posts/images/azurecli_jmespath_1.png",[],{"type":413,"tag":5031,"props":12117,"children":12118},{},[12119],{"type":413,"tag":2159,"props":12120,"children":12121},{},[12122,12124],{"type":418,"value":12123},"Filter on resource groups with an Environment tag with the value Production, select and rename name and tags properties with ",{"type":413,"tag":444,"props":12125,"children":12127},{"className":12126},[],[12128],{"type":418,"value":12129},"az group list --query \"[?tags.Environment=='Production'].{RGName:name, RGTags:tags}\"",{"type":413,"tag":414,"props":12131,"children":12132},{},[12133],{"type":413,"tag":832,"props":12134,"children":12138},{"alt":12135,"className":12136,"src":12137,"width":12091},"az group command output using JMESPath property filter and selection.",[836,837],"/posts/images/azurecli_jmespath_3.png",[],{"type":413,"tag":841,"props":12140,"children":12141},{"icon":10737},[12142],{"type":413,"tag":414,"props":12143,"children":12144},{},[12145,12147,12154],{"type":418,"value":12146},"JMESPath is not an Azure CLI only thing, it is used in different other projects or tools like the ",{"type":413,"tag":813,"props":12148,"children":12151},{"href":12149,"rel":12150},"https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-output.html#controlling-output-filter",[817],[12152],{"type":418,"value":12153},"AWS CLI",{"type":418,"value":898},{"type":413,"tag":866,"props":12156,"children":12158},{"id":12157},"mixing-output-variables-and-jmespath",[12159],{"type":418,"value":12160},"Mixing output, variables, and JMESPath",{"type":413,"tag":414,"props":12162,"children":12163},{},[12164],{"type":418,"value":12165},"Once you have understood how to use variables, commands output, and JMESPath with Azure CLI you can mix everything to manage Azure resources with CLI commands that use results of previous CLI commands, which can make powerful scripts 😀.",{"type":413,"tag":414,"props":12167,"children":12168},{},[12169],{"type":418,"value":12170},"Let's presume that we want to create a Web App for the IT Department in an existing App Service Plan of our subscription located in West Europe.\nWe can do the following:",{"type":413,"tag":437,"props":12172,"children":12174},{"className":1013,"code":12173,"language":248,"meta":401,"style":401},"# Retrieve resource group name of IT Department in West Europe\n$itRgName = az group list --query \"[?tags.Department=='IT' && location=='westeurope'].name\" -o tsv\n\n# Retrieve app service plan name in this resource group\n$appServicePlan = az appservice plan list -g $itRgName --query \"[0].name\" -o tsv\n\n# Create a new Web App on this app service plan\naz webapp create -n \"MyNewWebAp\" -g $itRgName --plan $appServicePlan\n\n# List all Web App in this resource group\naz webapp list -g $itRgName --query \"[].name\"\n",[12175],{"type":413,"tag":444,"props":12176,"children":12177},{"__ignoreMap":401},[12178,12186,12236,12243,12251,12317,12324,12332,12395,12402,12410],{"type":413,"tag":448,"props":12179,"children":12180},{"class":450,"line":451},[12181],{"type":413,"tag":448,"props":12182,"children":12183},{"style":2393},[12184],{"type":418,"value":12185},"# Retrieve resource group name of IT Department in West Europe\n",{"type":413,"tag":448,"props":12187,"children":12188},{"class":450,"line":473},[12189,12193,12198,12202,12207,12211,12215,12219,12224,12228,12232],{"type":413,"tag":448,"props":12190,"children":12191},{"style":461},[12192],{"type":418,"value":1026},{"type":413,"tag":448,"props":12194,"children":12195},{"style":1029},[12196],{"type":418,"value":12197},"itRgName ",{"type":413,"tag":448,"props":12199,"children":12200},{"style":461},[12201],{"type":418,"value":1037},{"type":413,"tag":448,"props":12203,"children":12204},{"style":1029},[12205],{"type":418,"value":12206}," az group list ",{"type":413,"tag":448,"props":12208,"children":12209},{"style":461},[12210],{"type":418,"value":1071},{"type":413,"tag":448,"props":12212,"children":12213},{"style":1029},[12214],{"type":418,"value":1276},{"type":413,"tag":448,"props":12216,"children":12217},{"style":461},[12218],{"type":418,"value":1183},{"type":413,"tag":448,"props":12220,"children":12221},{"style":467},[12222],{"type":418,"value":12223},"[?tags.Department=='IT' && location=='westeurope'].name",{"type":413,"tag":448,"props":12225,"children":12226},{"style":461},[12227],{"type":418,"value":1183},{"type":413,"tag":448,"props":12229,"children":12230},{"style":461},[12231],{"type":418,"value":1294},{"type":413,"tag":448,"props":12233,"children":12234},{"style":1029},[12235],{"type":418,"value":6259},{"type":413,"tag":448,"props":12237,"children":12238},{"class":450,"line":488},[12239],{"type":413,"tag":448,"props":12240,"children":12241},{"emptyLinePlaceholder":505},[12242],{"type":418,"value":508},{"type":413,"tag":448,"props":12244,"children":12245},{"class":450,"line":501},[12246],{"type":413,"tag":448,"props":12247,"children":12248},{"style":2393},[12249],{"type":418,"value":12250},"# Retrieve app service plan name in this resource group\n",{"type":413,"tag":448,"props":12252,"children":12253},{"class":450,"line":511},[12254,12258,12263,12267,12272,12276,12280,12284,12288,12292,12296,12300,12305,12309,12313],{"type":413,"tag":448,"props":12255,"children":12256},{"style":461},[12257],{"type":418,"value":1026},{"type":413,"tag":448,"props":12259,"children":12260},{"style":1029},[12261],{"type":418,"value":12262},"appServicePlan ",{"type":413,"tag":448,"props":12264,"children":12265},{"style":461},[12266],{"type":418,"value":1037},{"type":413,"tag":448,"props":12268,"children":12269},{"style":1029},[12270],{"type":418,"value":12271}," az appservice plan list ",{"type":413,"tag":448,"props":12273,"children":12274},{"style":461},[12275],{"type":418,"value":1173},{"type":413,"tag":448,"props":12277,"children":12278},{"style":1029},[12279],{"type":418,"value":5661},{"type":413,"tag":448,"props":12281,"children":12282},{"style":461},[12283],{"type":418,"value":1026},{"type":413,"tag":448,"props":12285,"children":12286},{"style":1029},[12287],{"type":418,"value":12197},{"type":413,"tag":448,"props":12289,"children":12290},{"style":461},[12291],{"type":418,"value":1071},{"type":413,"tag":448,"props":12293,"children":12294},{"style":1029},[12295],{"type":418,"value":1276},{"type":413,"tag":448,"props":12297,"children":12298},{"style":461},[12299],{"type":418,"value":1183},{"type":413,"tag":448,"props":12301,"children":12302},{"style":467},[12303],{"type":418,"value":12304},"[0].name",{"type":413,"tag":448,"props":12306,"children":12307},{"style":461},[12308],{"type":418,"value":1183},{"type":413,"tag":448,"props":12310,"children":12311},{"style":461},[12312],{"type":418,"value":1294},{"type":413,"tag":448,"props":12314,"children":12315},{"style":1029},[12316],{"type":418,"value":6259},{"type":413,"tag":448,"props":12318,"children":12319},{"class":450,"line":524},[12320],{"type":413,"tag":448,"props":12321,"children":12322},{"emptyLinePlaceholder":505},[12323],{"type":418,"value":508},{"type":413,"tag":448,"props":12325,"children":12326},{"class":450,"line":542},[12327],{"type":413,"tag":448,"props":12328,"children":12329},{"style":2393},[12330],{"type":418,"value":12331},"# Create a new Web App on this app service plan\n",{"type":413,"tag":448,"props":12333,"children":12334},{"class":450,"line":560},[12335,12340,12344,12348,12352,12357,12361,12365,12369,12373,12377,12381,12386,12390],{"type":413,"tag":448,"props":12336,"children":12337},{"style":1029},[12338],{"type":418,"value":12339},"az webapp create ",{"type":413,"tag":448,"props":12341,"children":12342},{"style":461},[12343],{"type":418,"value":1173},{"type":413,"tag":448,"props":12345,"children":12346},{"style":1029},[12347],{"type":418,"value":5643},{"type":413,"tag":448,"props":12349,"children":12350},{"style":461},[12351],{"type":418,"value":1183},{"type":413,"tag":448,"props":12353,"children":12354},{"style":467},[12355],{"type":418,"value":12356},"MyNewWebAp",{"type":413,"tag":448,"props":12358,"children":12359},{"style":461},[12360],{"type":418,"value":1183},{"type":413,"tag":448,"props":12362,"children":12363},{"style":461},[12364],{"type":418,"value":1294},{"type":413,"tag":448,"props":12366,"children":12367},{"style":1029},[12368],{"type":418,"value":5661},{"type":413,"tag":448,"props":12370,"children":12371},{"style":461},[12372],{"type":418,"value":1026},{"type":413,"tag":448,"props":12374,"children":12375},{"style":1029},[12376],{"type":418,"value":12197},{"type":413,"tag":448,"props":12378,"children":12379},{"style":461},[12380],{"type":418,"value":1071},{"type":413,"tag":448,"props":12382,"children":12383},{"style":1029},[12384],{"type":418,"value":12385},"plan ",{"type":413,"tag":448,"props":12387,"children":12388},{"style":461},[12389],{"type":418,"value":1026},{"type":413,"tag":448,"props":12391,"children":12392},{"style":1029},[12393],{"type":418,"value":12394},"appServicePlan\n",{"type":413,"tag":448,"props":12396,"children":12397},{"class":450,"line":573},[12398],{"type":413,"tag":448,"props":12399,"children":12400},{"emptyLinePlaceholder":505},[12401],{"type":418,"value":508},{"type":413,"tag":448,"props":12403,"children":12404},{"class":450,"line":586},[12405],{"type":413,"tag":448,"props":12406,"children":12407},{"style":2393},[12408],{"type":418,"value":12409},"# List all Web App in this resource group\n",{"type":413,"tag":448,"props":12411,"children":12412},{"class":450,"line":604},[12413,12418,12422,12426,12430,12434,12438,12442,12446,12451],{"type":413,"tag":448,"props":12414,"children":12415},{"style":1029},[12416],{"type":418,"value":12417},"az webapp list ",{"type":413,"tag":448,"props":12419,"children":12420},{"style":461},[12421],{"type":418,"value":1173},{"type":413,"tag":448,"props":12423,"children":12424},{"style":1029},[12425],{"type":418,"value":5661},{"type":413,"tag":448,"props":12427,"children":12428},{"style":461},[12429],{"type":418,"value":1026},{"type":413,"tag":448,"props":12431,"children":12432},{"style":1029},[12433],{"type":418,"value":12197},{"type":413,"tag":448,"props":12435,"children":12436},{"style":461},[12437],{"type":418,"value":1071},{"type":413,"tag":448,"props":12439,"children":12440},{"style":1029},[12441],{"type":418,"value":1276},{"type":413,"tag":448,"props":12443,"children":12444},{"style":461},[12445],{"type":418,"value":1183},{"type":413,"tag":448,"props":12447,"children":12448},{"style":467},[12449],{"type":418,"value":12450},"[].name",{"type":413,"tag":448,"props":12452,"children":12453},{"style":461},[12454],{"type":418,"value":1005},{"type":413,"tag":414,"props":12456,"children":12457},{},[12458],{"type":418,"value":12459},"This is just a quick example but you can easily imagine all the possibilities that Azure CLI offers you.",{"type":413,"tag":420,"props":12461,"children":12463},{"id":12462},"_4-where-to-use-azure-cli",[12464],{"type":418,"value":12465},"4 - Where to use Azure CLI",{"type":413,"tag":414,"props":12467,"children":12468},{},[12469],{"type":418,"value":12470},"All that is great but we haven't talked about where we can use Azure CLI, let's do that now!",{"type":413,"tag":866,"props":12472,"children":12474},{"id":12473},"bash-vs-powershell",[12475],{"type":418,"value":12476},"Bash vs PowerShell",{"type":413,"tag":414,"props":12478,"children":12479},{},[12480],{"type":418,"value":12481},"We briefly mentioned that you can run Azure CLI in Bash or PowerShell, and as a matter of fact you can also run it in Windows Command Prompt.\nAlthough Azure CLI is originally designed to be bash-oriented, it works fine in PowerShell so it's a perfectly valid choice too. What command line shell you choose is up to you!",{"type":413,"tag":414,"props":12483,"children":12484},{},[12485],{"type":418,"value":12486},"And don't think that you will be limited to using one or the other shell depending on the platform you are working on, because both PowerShell and Bash are available whatever your platform (PowerShell Core is cross-platform and Bash is available in Windows through Windows Subsystem for Linux). Therefore I would just suggest you use Azure CLI with the shell you are most familiar with.",{"type":413,"tag":414,"props":12488,"children":12489},{},[12490,12492,12499,12501,12508],{"type":418,"value":12491},"Just a quick note about autocompletion: at this time tab completion is only supported in bash and Microsoft currently does not plan to add support for PowerShell but is open to contributions from the community. That's not a big deal but that's good to know, there is a ",{"type":413,"tag":813,"props":12493,"children":12496},{"href":12494,"rel":12495},"https://github.com/Azure/azure-cli/issues/2324",[817],[12497],{"type":418,"value":12498},"GitHub issue",{"type":418,"value":12500}," on this matter. If you are not using bash and that tab completion is important for you, ",{"type":413,"tag":813,"props":12502,"children":12505},{"href":12503,"rel":12504},"https://docs.microsoft.com/en-us/cli/azure/interactive-azure-cli?view=azure-cli-latest",[817],[12506],{"type":418,"value":12507},"Azure CLI interactive mode",{"type":418,"value":12509}," is what you are looking for (we will talk about it later in the article)!",{"type":413,"tag":866,"props":12511,"children":12513},{"id":12512},"azure-cli-in-visual-studio-code",[12514],{"type":418,"value":12515},"Azure CLI in Visual Studio Code",{"type":413,"tag":414,"props":12517,"children":12518},{},[12519],{"type":418,"value":12520},"As for most of Azure components, there is an extension in vs code for Azure CLI: Azure CLI Tools.",{"type":413,"tag":414,"props":12522,"children":12523},{},[12524],{"type":413,"tag":832,"props":12525,"children":12529},{"alt":12526,"className":12527,"src":12528},"Azure CLI Tools vscode extension.",[836,837],"/posts/images/azurecli_vscode_1.png",[],{"type":413,"tag":414,"props":12531,"children":12532},{},[12533,12535,12540],{"type":418,"value":12534},"With this extension you can create Azure CLI Scrapbooks which are files with an ",{"type":413,"tag":444,"props":12536,"children":12538},{"className":12537},[],[12539],{"type":418,"value":5236},{"type":418,"value":12541}," extension where you have IntelliSense on CLI commands you write.",{"type":413,"tag":414,"props":12543,"children":12544},{},[12545],{"type":413,"tag":832,"props":12546,"children":12550},{"alt":12547,"className":12548,"src":12549,"width":12091},"Intellisense with Azure CLI vscode extension.",[836,837],"/posts/images/azurecli_vscode_3.png",[],{"type":413,"tag":414,"props":12552,"children":12553},{},[12554],{"type":418,"value":12555},"It also allows you to run commands in the integrated terminal or run them and show their output in a side-by-side editor as showN in the screenshot below.",{"type":413,"tag":414,"props":12557,"children":12558},{},[12559],{"type":413,"tag":832,"props":12560,"children":12564},{"alt":12561,"className":12562,"src":12563,"width":12091},"Azcli file with integrated integrated terminal.",[836,837],"/posts/images/azurecli_vscode_2.png",[],{"type":413,"tag":866,"props":12566,"children":12568},{"id":12567},"azure-cloud-shell",[12569],{"type":418,"value":12570},"Azure Cloud Shell",{"type":413,"tag":414,"props":12572,"children":12573},{},[12574,12576,12582],{"type":418,"value":12575},"I did not talk about Azure CLI installation but you can find everything you need in ",{"type":413,"tag":813,"props":12577,"children":12579},{"href":10402,"rel":12578},[817],[12580],{"type":418,"value":12581},"Microsoft documentation",{"type":418,"value":12583},". Actually, Azure Cloud Shell provides you with a way to use Azure CLI without installing anything.",{"type":413,"tag":414,"props":12585,"children":12586},{},[12587],{"type":418,"value":12588},"If we quote the documentation:",{"type":413,"tag":12590,"props":12591,"children":12592},"blockquote",{},[12593],{"type":413,"tag":414,"props":12594,"children":12595},{},[12596],{"type":418,"value":12597},"Azure Cloud Shell is an interactive, browser-accessible shell for managing Azure resources",{"type":413,"tag":414,"props":12599,"children":12600},{},[12601,12603,12609],{"type":418,"value":12602},"In concrete terms, you open a browser, go to ",{"type":413,"tag":813,"props":12604,"children":12607},{"href":12605,"rel":12606},"https://shell.azure.com",[817],[12608],{"type":418,"value":12605},{"type":418,"value":12610},", log in to your Azure subscription and you have access to a shell (PowerShell or Bash) that can interact with all the resources of your subscription through Azure CLI.",{"type":413,"tag":414,"props":12612,"children":12613},{},[12614],{"type":413,"tag":832,"props":12615,"children":12619},{"alt":12616,"className":12617,"src":12618,"width":12091},"Azure cloud shell in browser.",[836,837],"/posts/images/azurecli_cloudshell_1.png",[],{"type":413,"tag":414,"props":12621,"children":12622},{},[12623],{"type":418,"value":12624},"Cloud Shell in itself is free but requires an Azure file share to be mounted so you will have regular storage costs (which are low).",{"type":413,"tag":414,"props":12626,"children":12627},{},[12628,12630,12637],{"type":418,"value":12629},"Azure Cloud Shell is also available in the Azure Portal or directly in your vs code integrated terminal through the ",{"type":413,"tag":813,"props":12631,"children":12634},{"href":12632,"rel":12633},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account",[817],[12635],{"type":418,"value":12636},"Azure Account extension",{"type":418,"value":898},{"type":413,"tag":420,"props":12639,"children":12641},{"id":12640},"_5-azure-cli-interactive-mode",[12642],{"type":418,"value":12643},"5 - Azure CLI Interactive mode",{"type":413,"tag":414,"props":12645,"children":12646},{},[12647],{"type":418,"value":12648},"I mentioned Azure CLI interactive mode as a way to have auto-completion. In fact, it is much more than that as it also provides you with command descriptions, examples, completion on resources names, JMESPath on the previous command...",{"type":413,"tag":414,"props":12650,"children":12651},{},[12652,12654,12660],{"type":418,"value":12653},"To enter in interactive mode, you have to type ",{"type":413,"tag":444,"props":12655,"children":12657},{"className":12656},[],[12658],{"type":418,"value":12659},"az interactive",{"type":418,"value":12661}," in your terminal.\nThen you can type your CLI commands with autocompletion, a description of the command you are using, and examples for it. Moreover, while you are typing a command you will see help about the arguments for this command.",{"type":413,"tag":414,"props":12663,"children":12664},{},[12665],{"type":413,"tag":832,"props":12666,"children":12670},{"alt":12667,"className":12668,"src":12669,"width":12091},"Azure CLI interactive mode display.",[836,837],"/posts/images/azurecli_interactive_1.png",[],{"type":413,"tag":414,"props":12672,"children":12673},{},[12674,12676,12681,12683,12688,12690,12696,12698,12703],{"type":418,"value":12675},"One thing to notice is that commands you type are scoped to a command group. By default, it's scoped to ",{"type":413,"tag":444,"props":12677,"children":12679},{"className":12678},[],[12680],{"type":418,"value":4560},{"type":418,"value":12682}," group so you don't have to type the ",{"type":413,"tag":444,"props":12684,"children":12686},{"className":12685},[],[12687],{"type":418,"value":4560},{"type":418,"value":12689}," keyword before your commands. So by default, it only saves you two characters as you will write ",{"type":413,"tag":444,"props":12691,"children":12693},{"className":12692},[],[12694],{"type":418,"value":12695},"group list",{"type":418,"value":12697}," instead of ",{"type":413,"tag":444,"props":12699,"children":12701},{"className":12700},[],[12702],{"type":418,"value":11084},{"type":418,"value":12704},". But you can set the scope to any subgroup as you can see in the following example.",{"type":413,"tag":414,"props":12706,"children":12707},{},[12708],{"type":413,"tag":832,"props":12709,"children":12713},{"alt":12710,"className":12711,"src":12712},"Scoped commands in Azure CLI interactive mode.",[836,837],"/posts/images/azurecli_interactive_2.png",[],{"type":413,"tag":414,"props":12715,"children":12716},{},[12717,12719,12724,12726,12732],{"type":418,"value":12718},"Another nice thing you can do with the interactive mode is to query the results of your previous command using the JMESPath syntax.\nImagine I just have executed the command ",{"type":413,"tag":444,"props":12720,"children":12722},{"className":12721},[],[12723],{"type":418,"value":12695},{"type":418,"value":12725}," in interactive mode. If I want to select only the names in the results of this command, I can just type ",{"type":413,"tag":444,"props":12727,"children":12729},{"className":12728},[],[12730],{"type":418,"value":12731},"\"?? [*].name\"",{"type":418,"value":898},{"type":413,"tag":414,"props":12734,"children":12735},{},[12736],{"type":413,"tag":832,"props":12737,"children":12741},{"alt":12738,"className":12739,"src":12740},"JMESPath examples to filter Azure CLI interactive output.",[836,837],"/posts/images/azurecli_interactive_3.png",[],{"type":413,"tag":414,"props":12743,"children":12744},{},[12745],{"type":418,"value":12746},"As you can see in the example above, you can even use a JMESPath query on the previous command as an argument for your next command. Here we are listing all resources on the TestingAzureCLI group.",{"type":413,"tag":841,"props":12748,"children":12749},{"icon":10737},[12750],{"type":413,"tag":414,"props":12751,"children":12752},{},[12753,12755,12761],{"type":418,"value":12754},"It can sometimes be a little slow to use Azure interactive mode on ",{"type":413,"tag":813,"props":12756,"children":12759},{"href":12757,"rel":12758},"https://shell.azure.com/",[817],[12760],{"type":418,"value":12757},{"type":418,"value":12762},", so if it happens to you I suggest you use the vs code integrated terminal (if you want to use Azure Cloud Shell) or any terminal you want (if you have the Azure CLI installed) instead of the browser.",{"type":413,"tag":841,"props":12764,"children":12765},{"icon":10737},[12766],{"type":413,"tag":414,"props":12767,"children":12768},{},[12769,12771,12778],{"type":418,"value":12770},"If you like interactive CLI, you can also have a look at ",{"type":413,"tag":813,"props":12772,"children":12775},{"href":12773,"rel":12774},"https://github.com/lawrencegripper/azbrowse",[817],[12776],{"type":418,"value":12777},"AzBrowse",{"type":418,"value":12779}," which is a nice community project.",{"type":413,"tag":420,"props":12781,"children":12782},{"id":6607},[12783],{"type":418,"value":6610},{"type":413,"tag":414,"props":12785,"children":12786},{},[12787],{"type":418,"value":12788},"Even if the title of this article suggests saying goodbye to Azure Portal, when you start using Azure CLI you are not going to stop completely using Azure Portal. You will always need a GUI for some tasks or to better visualize things. However, you will probably Azure Portal use less often as you are going to find yourself more productive with Azure CLI and will enjoy being able to script everything ✨.",{"type":413,"tag":414,"props":12790,"children":12791},{},[12792],{"type":418,"value":12793},"There is still much to say about Azure CLI but that's already a long article so the best thing is that you try it by yourself!",{"type":413,"tag":3710,"props":12795,"children":12796},{},[12797],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":12799},[12800,12801,12802,12808,12813,12814],{"id":10410,"depth":473,"text":10413},{"id":10466,"depth":473,"text":10469},{"id":10681,"depth":473,"text":10684,"children":12803},[12804,12805,12806,12807],{"id":10687,"depth":488,"text":10690},{"id":10754,"depth":488,"text":10757},{"id":11045,"depth":488,"text":11048},{"id":12157,"depth":488,"text":12160},{"id":12462,"depth":473,"text":12465,"children":12809},[12810,12811,12812],{"id":12473,"depth":488,"text":12476},{"id":12512,"depth":488,"text":12515},{"id":12567,"depth":488,"text":12570},{"id":12640,"depth":473,"text":12643},{"id":6607,"depth":473,"text":6610},"content:1.posts:3.welcome-azure-cli.md","1.posts/3.welcome-azure-cli.md",1716749600615]