[{"data":1,"prerenderedAt":38187},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-Azure":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,3488,6758,10956,18336,22680,25552,28105,28477,30475,32412,34782,35137,35316,35704],{"_path":184,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":183,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":409,"ImageAttribution":410,"body":411,"_type":3483,"_id":3484,"_source":3485,"_file":3486,"_extension":3487},"posts",false,"","I love how the Azure SDKs have evolved over the years. In the past, there was no consistency between the various Azure SDKs. However, that's not longer the case (at least for most Azure libraries), as they now adhere to the same principles and follow a set of well-defined guidelines.","Register your Azure clients the proper way","2024-02-19T00:00:00.000Z",{"src":406},"/images/apple-di.webp",{"label":408},"Development",[228,302,239],"Picture of \u003Ca href=\"https://unsplash.com/fr/@sarabakhshi\">Sara Bakhshi\u003C/a> on \u003Ca href=\"https://unsplash.com/fr/photos/pomme-fruit-avec-des-seringues-en-plastique-MfnX4XtGnvU\">Unsplash\u003C/a>",{"type":412,"children":413,"toc":3475},"root",[414,433,452,457,476,481,488,502,507,522,922,942,1380,1419,1425,1439,1719,1724,1749,1755,1767,2037,2050,2476,2487,2501,2507,2520,2525,2767,2772,2942,2948,2970,3014,3430,3442,3448,3464,3469],{"type":415,"tag":416,"props":417,"children":418},"element","p",{},[419,422,431],{"type":420,"value":421},"text","I love how the Azure SDKs have evolved over the years. In the past, there was no consistency between the various Azure SDKs. However, that's not longer the case (at least for most Azure libraries), as they now adhere to the same principles and follow a set of well-defined ",{"type":415,"tag":423,"props":424,"children":428},"a",{"href":425,"rel":426},"https://azure.github.io/azure-sdk/general_introduction.html",[427],"nofollow",[429],{"type":420,"value":430},"guidelines",{"type":420,"value":432},".",{"type":415,"tag":434,"props":435,"children":437},"callout",{"icon":436},"i-heroicons-light-bulb",[438],{"type":415,"tag":416,"props":439,"children":440},{},[441,443,450],{"type":420,"value":442},"You can learn more about these guidelines and how the Azure .NET SDKs work in this ",{"type":415,"tag":423,"props":444,"children":447},{"href":445,"rel":446},"https://youtu.be/v36NXLU3TLY?si=L8e1ic898kDCisJ7",[427],[448],{"type":420,"value":449},"video",{"type":420,"value":451}," from 2021 which is I think still relevant today.",{"type":415,"tag":416,"props":453,"children":454},{},[455],{"type":420,"value":456},"Having consistency between libraries, it's easier to handle things like authentication and dependency injection consistently when you are using multiple Azure SDKs in your project.",{"type":415,"tag":416,"props":458,"children":459},{},[460,462,474],{"type":420,"value":461},"One aspect often overlooked by people using Azure SDKs is the use of ",{"type":415,"tag":423,"props":463,"children":466},{"href":464,"rel":465},"https://www.nuget.org/packages/Microsoft.Extensions.Azure",[427],[467],{"type":415,"tag":468,"props":469,"children":471},"code",{"className":470},[],[472],{"type":420,"value":473},"Microsoft.Extensions.Azure",{"type":420,"value":475},". This package facilitates registering and configuring the service clients for interacting with Azure APIs.",{"type":415,"tag":416,"props":477,"children":478},{},[479],{"type":420,"value":480},"Let's see why using this package could be beneficial for your project.",{"type":415,"tag":482,"props":483,"children":485},"h2",{"id":484},"avoid-making-mistakes-when-registering-service-clients",[486],{"type":420,"value":487},"Avoid making mistakes when registering service clients",{"type":415,"tag":416,"props":489,"children":490},{},[491,493,500],{"type":420,"value":492},"It's mentioned in the ",{"type":415,"tag":423,"props":494,"children":497},{"href":495,"rel":496},"https://learn.microsoft.com/en-us/dotnet/azure/sdk/dependency-injection?view=azure-dotnet&tabs=web-app-builder",[427],[498],{"type":420,"value":499},"documentation",{"type":420,"value":501}," to use this package for dependency injection with the Azure SDK for .NET. Still, many people don't read the documentation and manually register the Azure service clients.",{"type":415,"tag":416,"props":503,"children":504},{},[505],{"type":420,"value":506},"It's not a problem in itself if you know what you are doing. Otherwise,",{"type":415,"tag":508,"props":509,"children":510},"ul",{},[511,517],{"type":415,"tag":512,"props":513,"children":514},"li",{},[515],{"type":420,"value":516},"you might choose the wrong lifetime for the Azure service clients, they must be singleton",{"type":415,"tag":512,"props":518,"children":519},{},[520],{"type":420,"value":521},"you may forget to register a dependency that is needed for your use of the SDK",{"type":415,"tag":523,"props":524,"children":527},"pre",{"className":525,"code":526,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","using Azure.Identity;\nusing DIWithAzureSDK;\nusing Microsoft.Extensions.Azure;\n\nvar builder = Host.CreateApplicationBuilder(args);\nbuilder.Services.AddHostedService\u003CWorker>();\nbuilder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"));\n    clientBuilder.UseCredential(new DefaultAzureCredential());\n});\n\nvar host = builder.Build();\nhost.Run();\n",[528],{"type":415,"tag":468,"props":529,"children":530},{"__ignoreMap":401},[531,564,581,615,625,675,717,756,765,817,848,857,865,900],{"type":415,"tag":532,"props":533,"children":536},"span",{"class":534,"line":535},"line",1,[537,543,549,554,559],{"type":415,"tag":532,"props":538,"children":540},{"style":539},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[541],{"type":420,"value":542},"using",{"type":415,"tag":532,"props":544,"children":546},{"style":545},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[547],{"type":420,"value":548}," Azure",{"type":415,"tag":532,"props":550,"children":552},{"style":551},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[553],{"type":420,"value":432},{"type":415,"tag":532,"props":555,"children":556},{"style":545},[557],{"type":420,"value":558},"Identity",{"type":415,"tag":532,"props":560,"children":561},{"style":551},[562],{"type":420,"value":563},";\n",{"type":415,"tag":532,"props":565,"children":567},{"class":534,"line":566},2,[568,572,577],{"type":415,"tag":532,"props":569,"children":570},{"style":539},[571],{"type":420,"value":542},{"type":415,"tag":532,"props":573,"children":574},{"style":545},[575],{"type":420,"value":576}," DIWithAzureSDK",{"type":415,"tag":532,"props":578,"children":579},{"style":551},[580],{"type":420,"value":563},{"type":415,"tag":532,"props":582,"children":584},{"class":534,"line":583},3,[585,589,594,598,603,607,611],{"type":415,"tag":532,"props":586,"children":587},{"style":539},[588],{"type":420,"value":542},{"type":415,"tag":532,"props":590,"children":591},{"style":545},[592],{"type":420,"value":593}," Microsoft",{"type":415,"tag":532,"props":595,"children":596},{"style":551},[597],{"type":420,"value":432},{"type":415,"tag":532,"props":599,"children":600},{"style":545},[601],{"type":420,"value":602},"Extensions",{"type":415,"tag":532,"props":604,"children":605},{"style":551},[606],{"type":420,"value":432},{"type":415,"tag":532,"props":608,"children":609},{"style":545},[610],{"type":420,"value":228},{"type":415,"tag":532,"props":612,"children":613},{"style":551},[614],{"type":420,"value":563},{"type":415,"tag":532,"props":616,"children":618},{"class":534,"line":617},4,[619],{"type":415,"tag":532,"props":620,"children":622},{"emptyLinePlaceholder":621},true,[623],{"type":420,"value":624},"\n",{"type":415,"tag":532,"props":626,"children":628},{"class":534,"line":627},5,[629,635,640,645,650,654,660,665,670],{"type":415,"tag":532,"props":630,"children":632},{"style":631},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[633],{"type":420,"value":634},"var",{"type":415,"tag":532,"props":636,"children":637},{"style":631},[638],{"type":420,"value":639}," builder",{"type":415,"tag":532,"props":641,"children":642},{"style":551},[643],{"type":420,"value":644}," =",{"type":415,"tag":532,"props":646,"children":647},{"style":545},[648],{"type":420,"value":649}," Host",{"type":415,"tag":532,"props":651,"children":652},{"style":551},[653],{"type":420,"value":432},{"type":415,"tag":532,"props":655,"children":657},{"style":656},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[658],{"type":420,"value":659},"CreateApplicationBuilder",{"type":415,"tag":532,"props":661,"children":662},{"style":551},[663],{"type":420,"value":664},"(",{"type":415,"tag":532,"props":666,"children":667},{"style":545},[668],{"type":420,"value":669},"args",{"type":415,"tag":532,"props":671,"children":672},{"style":551},[673],{"type":420,"value":674},");\n",{"type":415,"tag":532,"props":676,"children":678},{"class":534,"line":677},6,[679,684,688,693,697,702,707,712],{"type":415,"tag":532,"props":680,"children":681},{"style":545},[682],{"type":420,"value":683},"builder",{"type":415,"tag":532,"props":685,"children":686},{"style":551},[687],{"type":420,"value":432},{"type":415,"tag":532,"props":689,"children":690},{"style":545},[691],{"type":420,"value":692},"Services",{"type":415,"tag":532,"props":694,"children":695},{"style":551},[696],{"type":420,"value":432},{"type":415,"tag":532,"props":698,"children":699},{"style":656},[700],{"type":420,"value":701},"AddHostedService",{"type":415,"tag":532,"props":703,"children":704},{"style":551},[705],{"type":420,"value":706},"\u003C",{"type":415,"tag":532,"props":708,"children":709},{"style":631},[710],{"type":420,"value":711},"Worker",{"type":415,"tag":532,"props":713,"children":714},{"style":551},[715],{"type":420,"value":716},">();\n",{"type":415,"tag":532,"props":718,"children":720},{"class":534,"line":719},7,[721,725,729,733,737,742,746,751],{"type":415,"tag":532,"props":722,"children":723},{"style":545},[724],{"type":420,"value":683},{"type":415,"tag":532,"props":726,"children":727},{"style":551},[728],{"type":420,"value":432},{"type":415,"tag":532,"props":730,"children":731},{"style":545},[732],{"type":420,"value":692},{"type":415,"tag":532,"props":734,"children":735},{"style":551},[736],{"type":420,"value":432},{"type":415,"tag":532,"props":738,"children":739},{"style":656},[740],{"type":420,"value":741},"AddAzureClients",{"type":415,"tag":532,"props":743,"children":744},{"style":551},[745],{"type":420,"value":664},{"type":415,"tag":532,"props":747,"children":748},{"style":631},[749],{"type":420,"value":750},"clientBuilder",{"type":415,"tag":532,"props":752,"children":753},{"style":551},[754],{"type":420,"value":755}," =>\n",{"type":415,"tag":532,"props":757,"children":759},{"class":534,"line":758},8,[760],{"type":415,"tag":532,"props":761,"children":762},{"style":551},[763],{"type":420,"value":764},"{\n",{"type":415,"tag":532,"props":766,"children":768},{"class":534,"line":767},9,[769,774,778,783,788,793,797,802,808,812],{"type":415,"tag":532,"props":770,"children":771},{"style":545},[772],{"type":420,"value":773},"    clientBuilder",{"type":415,"tag":532,"props":775,"children":776},{"style":551},[777],{"type":420,"value":432},{"type":415,"tag":532,"props":779,"children":780},{"style":656},[781],{"type":420,"value":782},"AddBlobServiceClient",{"type":415,"tag":532,"props":784,"children":785},{"style":551},[786],{"type":420,"value":787},"(new",{"type":415,"tag":532,"props":789,"children":790},{"style":631},[791],{"type":420,"value":792}," Uri",{"type":415,"tag":532,"props":794,"children":795},{"style":551},[796],{"type":420,"value":664},{"type":415,"tag":532,"props":798,"children":799},{"style":551},[800],{"type":420,"value":801},"\"",{"type":415,"tag":532,"props":803,"children":805},{"style":804},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[806],{"type":420,"value":807},"https://stdiwithazuresdk.blob.core.windows.net/",{"type":415,"tag":532,"props":809,"children":810},{"style":551},[811],{"type":420,"value":801},{"type":415,"tag":532,"props":813,"children":814},{"style":551},[815],{"type":420,"value":816},"));\n",{"type":415,"tag":532,"props":818,"children":820},{"class":534,"line":819},10,[821,825,829,834,838,843],{"type":415,"tag":532,"props":822,"children":823},{"style":545},[824],{"type":420,"value":773},{"type":415,"tag":532,"props":826,"children":827},{"style":551},[828],{"type":420,"value":432},{"type":415,"tag":532,"props":830,"children":831},{"style":656},[832],{"type":420,"value":833},"UseCredential",{"type":415,"tag":532,"props":835,"children":836},{"style":551},[837],{"type":420,"value":787},{"type":415,"tag":532,"props":839,"children":840},{"style":631},[841],{"type":420,"value":842}," DefaultAzureCredential",{"type":415,"tag":532,"props":844,"children":845},{"style":551},[846],{"type":420,"value":847},"());\n",{"type":415,"tag":532,"props":849,"children":851},{"class":534,"line":850},11,[852],{"type":415,"tag":532,"props":853,"children":854},{"style":551},[855],{"type":420,"value":856},"});\n",{"type":415,"tag":532,"props":858,"children":860},{"class":534,"line":859},12,[861],{"type":415,"tag":532,"props":862,"children":863},{"emptyLinePlaceholder":621},[864],{"type":420,"value":624},{"type":415,"tag":532,"props":866,"children":868},{"class":534,"line":867},13,[869,873,878,882,886,890,895],{"type":415,"tag":532,"props":870,"children":871},{"style":631},[872],{"type":420,"value":634},{"type":415,"tag":532,"props":874,"children":875},{"style":631},[876],{"type":420,"value":877}," host",{"type":415,"tag":532,"props":879,"children":880},{"style":551},[881],{"type":420,"value":644},{"type":415,"tag":532,"props":883,"children":884},{"style":545},[885],{"type":420,"value":639},{"type":415,"tag":532,"props":887,"children":888},{"style":551},[889],{"type":420,"value":432},{"type":415,"tag":532,"props":891,"children":892},{"style":656},[893],{"type":420,"value":894},"Build",{"type":415,"tag":532,"props":896,"children":897},{"style":551},[898],{"type":420,"value":899},"();\n",{"type":415,"tag":532,"props":901,"children":903},{"class":534,"line":902},14,[904,909,913,918],{"type":415,"tag":532,"props":905,"children":906},{"style":545},[907],{"type":420,"value":908},"host",{"type":415,"tag":532,"props":910,"children":911},{"style":551},[912],{"type":420,"value":432},{"type":415,"tag":532,"props":914,"children":915},{"style":656},[916],{"type":420,"value":917},"Run",{"type":415,"tag":532,"props":919,"children":920},{"style":551},[921],{"type":420,"value":899},{"type":415,"tag":416,"props":923,"children":924},{},[925,927,932,934,940],{"type":420,"value":926},"In this sample, the ",{"type":415,"tag":468,"props":928,"children":930},{"className":929},[],[931],{"type":420,"value":782},{"type":420,"value":933}," handles the registration of all dependencies for us so that the ",{"type":415,"tag":468,"props":935,"children":937},{"className":936},[],[938],{"type":420,"value":939},"BlobServiceClient",{"type":420,"value":941}," can then be injected directly where needed.",{"type":415,"tag":523,"props":943,"children":945},{"className":525,"code":944,"language":326,"meta":401,"style":401},"public class Worker : BackgroundService\n{\n    private readonly ILogger\u003CWorker> _logger;\n    private readonly BlobServiceClient _blobServiceClient;\n\n    public Worker(ILogger\u003CWorker> logger, BlobServiceClient blobServiceClient)\n    {\n        _logger = logger;\n        _blobServiceClient = blobServiceClient;\n    }\n\n    protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n    {\n        await foreach (var blobContainer in _blobServiceClient.GetBlobContainersAsync(cancellationToken: stoppingToken))\n        {\n            _logger.LogInformation(blobContainer.Name);\n        }\n    }\n}\n",[946],{"type":415,"tag":468,"props":947,"children":948},{"__ignoreMap":401},[949,978,985,1025,1050,1057,1114,1122,1143,1163,1171,1178,1224,1231,1300,1309,1354,1363,1371],{"type":415,"tag":532,"props":950,"children":951},{"class":534,"line":535},[952,958,963,968,973],{"type":415,"tag":532,"props":953,"children":955},{"style":954},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[956],{"type":420,"value":957},"public",{"type":415,"tag":532,"props":959,"children":960},{"style":631},[961],{"type":420,"value":962}," class",{"type":415,"tag":532,"props":964,"children":965},{"style":631},[966],{"type":420,"value":967}," Worker",{"type":415,"tag":532,"props":969,"children":970},{"style":551},[971],{"type":420,"value":972}," :",{"type":415,"tag":532,"props":974,"children":975},{"style":631},[976],{"type":420,"value":977}," BackgroundService\n",{"type":415,"tag":532,"props":979,"children":980},{"class":534,"line":566},[981],{"type":415,"tag":532,"props":982,"children":983},{"style":551},[984],{"type":420,"value":764},{"type":415,"tag":532,"props":986,"children":987},{"class":534,"line":583},[988,993,998,1003,1007,1011,1016,1021],{"type":415,"tag":532,"props":989,"children":990},{"style":954},[991],{"type":420,"value":992},"    private",{"type":415,"tag":532,"props":994,"children":995},{"style":954},[996],{"type":420,"value":997}," readonly",{"type":415,"tag":532,"props":999,"children":1000},{"style":631},[1001],{"type":420,"value":1002}," ILogger",{"type":415,"tag":532,"props":1004,"children":1005},{"style":551},[1006],{"type":420,"value":706},{"type":415,"tag":532,"props":1008,"children":1009},{"style":631},[1010],{"type":420,"value":711},{"type":415,"tag":532,"props":1012,"children":1013},{"style":551},[1014],{"type":420,"value":1015},">",{"type":415,"tag":532,"props":1017,"children":1018},{"style":631},[1019],{"type":420,"value":1020}," _logger",{"type":415,"tag":532,"props":1022,"children":1023},{"style":551},[1024],{"type":420,"value":563},{"type":415,"tag":532,"props":1026,"children":1027},{"class":534,"line":617},[1028,1032,1036,1041,1046],{"type":415,"tag":532,"props":1029,"children":1030},{"style":954},[1031],{"type":420,"value":992},{"type":415,"tag":532,"props":1033,"children":1034},{"style":954},[1035],{"type":420,"value":997},{"type":415,"tag":532,"props":1037,"children":1038},{"style":631},[1039],{"type":420,"value":1040}," BlobServiceClient",{"type":415,"tag":532,"props":1042,"children":1043},{"style":631},[1044],{"type":420,"value":1045}," _blobServiceClient",{"type":415,"tag":532,"props":1047,"children":1048},{"style":551},[1049],{"type":420,"value":563},{"type":415,"tag":532,"props":1051,"children":1052},{"class":534,"line":627},[1053],{"type":415,"tag":532,"props":1054,"children":1055},{"emptyLinePlaceholder":621},[1056],{"type":420,"value":624},{"type":415,"tag":532,"props":1058,"children":1059},{"class":534,"line":677},[1060,1065,1069,1073,1078,1082,1086,1090,1095,1100,1104,1109],{"type":415,"tag":532,"props":1061,"children":1062},{"style":954},[1063],{"type":420,"value":1064},"    public",{"type":415,"tag":532,"props":1066,"children":1067},{"style":656},[1068],{"type":420,"value":967},{"type":415,"tag":532,"props":1070,"children":1071},{"style":551},[1072],{"type":420,"value":664},{"type":415,"tag":532,"props":1074,"children":1075},{"style":631},[1076],{"type":420,"value":1077},"ILogger",{"type":415,"tag":532,"props":1079,"children":1080},{"style":551},[1081],{"type":420,"value":706},{"type":415,"tag":532,"props":1083,"children":1084},{"style":631},[1085],{"type":420,"value":711},{"type":415,"tag":532,"props":1087,"children":1088},{"style":551},[1089],{"type":420,"value":1015},{"type":415,"tag":532,"props":1091,"children":1092},{"style":631},[1093],{"type":420,"value":1094}," logger",{"type":415,"tag":532,"props":1096,"children":1097},{"style":551},[1098],{"type":420,"value":1099},",",{"type":415,"tag":532,"props":1101,"children":1102},{"style":631},[1103],{"type":420,"value":1040},{"type":415,"tag":532,"props":1105,"children":1106},{"style":631},[1107],{"type":420,"value":1108}," blobServiceClient",{"type":415,"tag":532,"props":1110,"children":1111},{"style":551},[1112],{"type":420,"value":1113},")\n",{"type":415,"tag":532,"props":1115,"children":1116},{"class":534,"line":719},[1117],{"type":415,"tag":532,"props":1118,"children":1119},{"style":551},[1120],{"type":420,"value":1121},"    {\n",{"type":415,"tag":532,"props":1123,"children":1124},{"class":534,"line":758},[1125,1130,1135,1139],{"type":415,"tag":532,"props":1126,"children":1127},{"style":545},[1128],{"type":420,"value":1129},"        _logger ",{"type":415,"tag":532,"props":1131,"children":1132},{"style":551},[1133],{"type":420,"value":1134},"=",{"type":415,"tag":532,"props":1136,"children":1137},{"style":545},[1138],{"type":420,"value":1094},{"type":415,"tag":532,"props":1140,"children":1141},{"style":551},[1142],{"type":420,"value":563},{"type":415,"tag":532,"props":1144,"children":1145},{"class":534,"line":767},[1146,1151,1155,1159],{"type":415,"tag":532,"props":1147,"children":1148},{"style":545},[1149],{"type":420,"value":1150},"        _blobServiceClient ",{"type":415,"tag":532,"props":1152,"children":1153},{"style":551},[1154],{"type":420,"value":1134},{"type":415,"tag":532,"props":1156,"children":1157},{"style":545},[1158],{"type":420,"value":1108},{"type":415,"tag":532,"props":1160,"children":1161},{"style":551},[1162],{"type":420,"value":563},{"type":415,"tag":532,"props":1164,"children":1165},{"class":534,"line":819},[1166],{"type":415,"tag":532,"props":1167,"children":1168},{"style":551},[1169],{"type":420,"value":1170},"    }\n",{"type":415,"tag":532,"props":1172,"children":1173},{"class":534,"line":850},[1174],{"type":415,"tag":532,"props":1175,"children":1176},{"emptyLinePlaceholder":621},[1177],{"type":420,"value":624},{"type":415,"tag":532,"props":1179,"children":1180},{"class":534,"line":859},[1181,1186,1191,1196,1201,1206,1210,1215,1220],{"type":415,"tag":532,"props":1182,"children":1183},{"style":954},[1184],{"type":420,"value":1185},"    protected",{"type":415,"tag":532,"props":1187,"children":1188},{"style":954},[1189],{"type":420,"value":1190}," override",{"type":415,"tag":532,"props":1192,"children":1193},{"style":954},[1194],{"type":420,"value":1195}," async",{"type":415,"tag":532,"props":1197,"children":1198},{"style":631},[1199],{"type":420,"value":1200}," Task",{"type":415,"tag":532,"props":1202,"children":1203},{"style":656},[1204],{"type":420,"value":1205}," ExecuteAsync",{"type":415,"tag":532,"props":1207,"children":1208},{"style":551},[1209],{"type":420,"value":664},{"type":415,"tag":532,"props":1211,"children":1212},{"style":631},[1213],{"type":420,"value":1214},"CancellationToken",{"type":415,"tag":532,"props":1216,"children":1217},{"style":631},[1218],{"type":420,"value":1219}," stoppingToken",{"type":415,"tag":532,"props":1221,"children":1222},{"style":551},[1223],{"type":420,"value":1113},{"type":415,"tag":532,"props":1225,"children":1226},{"class":534,"line":867},[1227],{"type":415,"tag":532,"props":1228,"children":1229},{"style":551},[1230],{"type":420,"value":1121},{"type":415,"tag":532,"props":1232,"children":1233},{"class":534,"line":902},[1234,1239,1245,1250,1254,1259,1264,1268,1272,1277,1281,1286,1291,1295],{"type":415,"tag":532,"props":1235,"children":1236},{"style":551},[1237],{"type":420,"value":1238},"        await",{"type":415,"tag":532,"props":1240,"children":1242},{"style":1241},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[1243],{"type":420,"value":1244}," foreach",{"type":415,"tag":532,"props":1246,"children":1247},{"style":551},[1248],{"type":420,"value":1249}," (",{"type":415,"tag":532,"props":1251,"children":1252},{"style":631},[1253],{"type":420,"value":634},{"type":415,"tag":532,"props":1255,"children":1256},{"style":631},[1257],{"type":420,"value":1258}," blobContainer",{"type":415,"tag":532,"props":1260,"children":1261},{"style":1241},[1262],{"type":420,"value":1263}," in",{"type":415,"tag":532,"props":1265,"children":1266},{"style":545},[1267],{"type":420,"value":1045},{"type":415,"tag":532,"props":1269,"children":1270},{"style":551},[1271],{"type":420,"value":432},{"type":415,"tag":532,"props":1273,"children":1274},{"style":656},[1275],{"type":420,"value":1276},"GetBlobContainersAsync",{"type":415,"tag":532,"props":1278,"children":1279},{"style":551},[1280],{"type":420,"value":664},{"type":415,"tag":532,"props":1282,"children":1283},{"style":631},[1284],{"type":420,"value":1285},"cancellationToken",{"type":415,"tag":532,"props":1287,"children":1288},{"style":551},[1289],{"type":420,"value":1290},":",{"type":415,"tag":532,"props":1292,"children":1293},{"style":545},[1294],{"type":420,"value":1219},{"type":415,"tag":532,"props":1296,"children":1297},{"style":551},[1298],{"type":420,"value":1299},"))\n",{"type":415,"tag":532,"props":1301,"children":1303},{"class":534,"line":1302},15,[1304],{"type":415,"tag":532,"props":1305,"children":1306},{"style":551},[1307],{"type":420,"value":1308},"        {\n",{"type":415,"tag":532,"props":1310,"children":1312},{"class":534,"line":1311},16,[1313,1318,1322,1327,1331,1336,1340,1345,1350],{"type":415,"tag":532,"props":1314,"children":1315},{"style":545},[1316],{"type":420,"value":1317},"            _logger",{"type":415,"tag":532,"props":1319,"children":1320},{"style":551},[1321],{"type":420,"value":432},{"type":415,"tag":532,"props":1323,"children":1324},{"style":656},[1325],{"type":420,"value":1326},"LogInformation",{"type":415,"tag":532,"props":1328,"children":1329},{"style":551},[1330],{"type":420,"value":664},{"type":415,"tag":532,"props":1332,"children":1333},{"style":545},[1334],{"type":420,"value":1335},"blobContainer",{"type":415,"tag":532,"props":1337,"children":1338},{"style":551},[1339],{"type":420,"value":432},{"type":415,"tag":532,"props":1341,"children":1342},{"style":545},[1343],{"type":420,"value":1344},"Name",{"type":415,"tag":532,"props":1346,"children":1347},{"style":551},[1348],{"type":420,"value":1349},")",{"type":415,"tag":532,"props":1351,"children":1352},{"style":545},[1353],{"type":420,"value":563},{"type":415,"tag":532,"props":1355,"children":1357},{"class":534,"line":1356},17,[1358],{"type":415,"tag":532,"props":1359,"children":1360},{"style":551},[1361],{"type":420,"value":1362},"        }\n",{"type":415,"tag":532,"props":1364,"children":1366},{"class":534,"line":1365},18,[1367],{"type":415,"tag":532,"props":1368,"children":1369},{"style":551},[1370],{"type":420,"value":1170},{"type":415,"tag":532,"props":1372,"children":1374},{"class":534,"line":1373},19,[1375],{"type":415,"tag":532,"props":1376,"children":1377},{"style":551},[1378],{"type":420,"value":1379},"}\n",{"type":415,"tag":434,"props":1381,"children":1383},{"icon":1382},"i-heroicons-chat-bubble-left-20-solid",[1384],{"type":415,"tag":416,"props":1385,"children":1386},{},[1387,1389,1394,1396,1402,1404,1410,1412,1417],{"type":420,"value":1388},"You may find it convenient to configure the dependency injection for all Azure service clients in a central place with the ",{"type":415,"tag":468,"props":1390,"children":1392},{"className":1391},[],[1393],{"type":420,"value":741},{"type":420,"value":1395}," method. When applications become larger with different ",{"type":415,"tag":468,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":420,"value":1401},"csproj,",{"type":420,"value":1403}," I often prefer to separate service registration by business domain/module so having everything in a central place does not always suit my needs. That's not a problem, as the internal methods of the library make use of the ",{"type":415,"tag":468,"props":1405,"children":1407},{"className":1406},[],[1408],{"type":420,"value":1409},"TryAddd",{"type":420,"value":1411}," methods for registering services, I can call ",{"type":415,"tag":468,"props":1413,"children":1415},{"className":1414},[],[1416],{"type":420,"value":741},{"type":420,"value":1418}," in multiple places with only the services I want to register.",{"type":415,"tag":482,"props":1420,"children":1422},{"id":1421},"easily-manage-the-authentication-to-azure-services",[1423],{"type":420,"value":1424},"Easily manage the authentication to Azure services",{"type":415,"tag":416,"props":1426,"children":1427},{},[1428,1430,1437],{"type":420,"value":1429},"All the SDKs use the ",{"type":415,"tag":423,"props":1431,"children":1434},{"href":1432,"rel":1433},"https://www.nuget.org/packages/Azure.Identity",[427],[1435],{"type":420,"value":1436},"Azure.Identity",{"type":420,"value":1438}," package to authenticate to Azure. There are different authentication methods available and you can easily specify which one to use with each client. Additionally, you can define a default authentication method for all clients, as demonstrated in the previous example.",{"type":415,"tag":523,"props":1440,"children":1442},{"className":525,"code":1441,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddServiceBusClient(\"https://sb-diwithazuresdk.servicebus.windows.net/\")\n        .WithCredential(new ManagedIdentityCredential());\n    \n    clientBuilder.AddTableServiceClient(new Uri(\"https://stdiwithazuresdk.table.core.windows.net\"))\n        .WithCredential(new EnvironmentCredential());\n\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"));\n    \n    clientBuilder.UseCredential(new DefaultAzureCredential());\n});\n",[1443],{"type":415,"tag":468,"props":1444,"children":1445},{"__ignoreMap":401},[1446,1481,1488,1525,1551,1559,1604,1628,1635,1678,1685,1712],{"type":415,"tag":532,"props":1447,"children":1448},{"class":534,"line":535},[1449,1453,1457,1461,1465,1469,1473,1477],{"type":415,"tag":532,"props":1450,"children":1451},{"style":545},[1452],{"type":420,"value":683},{"type":415,"tag":532,"props":1454,"children":1455},{"style":551},[1456],{"type":420,"value":432},{"type":415,"tag":532,"props":1458,"children":1459},{"style":545},[1460],{"type":420,"value":692},{"type":415,"tag":532,"props":1462,"children":1463},{"style":551},[1464],{"type":420,"value":432},{"type":415,"tag":532,"props":1466,"children":1467},{"style":656},[1468],{"type":420,"value":741},{"type":415,"tag":532,"props":1470,"children":1471},{"style":551},[1472],{"type":420,"value":664},{"type":415,"tag":532,"props":1474,"children":1475},{"style":631},[1476],{"type":420,"value":750},{"type":415,"tag":532,"props":1478,"children":1479},{"style":551},[1480],{"type":420,"value":755},{"type":415,"tag":532,"props":1482,"children":1483},{"class":534,"line":566},[1484],{"type":415,"tag":532,"props":1485,"children":1486},{"style":551},[1487],{"type":420,"value":764},{"type":415,"tag":532,"props":1489,"children":1490},{"class":534,"line":583},[1491,1495,1499,1504,1508,1512,1517,1521],{"type":415,"tag":532,"props":1492,"children":1493},{"style":545},[1494],{"type":420,"value":773},{"type":415,"tag":532,"props":1496,"children":1497},{"style":551},[1498],{"type":420,"value":432},{"type":415,"tag":532,"props":1500,"children":1501},{"style":656},[1502],{"type":420,"value":1503},"AddServiceBusClient",{"type":415,"tag":532,"props":1505,"children":1506},{"style":551},[1507],{"type":420,"value":664},{"type":415,"tag":532,"props":1509,"children":1510},{"style":551},[1511],{"type":420,"value":801},{"type":415,"tag":532,"props":1513,"children":1514},{"style":804},[1515],{"type":420,"value":1516},"https://sb-diwithazuresdk.servicebus.windows.net/",{"type":415,"tag":532,"props":1518,"children":1519},{"style":551},[1520],{"type":420,"value":801},{"type":415,"tag":532,"props":1522,"children":1523},{"style":551},[1524],{"type":420,"value":1113},{"type":415,"tag":532,"props":1526,"children":1527},{"class":534,"line":617},[1528,1533,1538,1542,1547],{"type":415,"tag":532,"props":1529,"children":1530},{"style":551},[1531],{"type":420,"value":1532},"        .",{"type":415,"tag":532,"props":1534,"children":1535},{"style":656},[1536],{"type":420,"value":1537},"WithCredential",{"type":415,"tag":532,"props":1539,"children":1540},{"style":551},[1541],{"type":420,"value":787},{"type":415,"tag":532,"props":1543,"children":1544},{"style":631},[1545],{"type":420,"value":1546}," ManagedIdentityCredential",{"type":415,"tag":532,"props":1548,"children":1549},{"style":551},[1550],{"type":420,"value":847},{"type":415,"tag":532,"props":1552,"children":1553},{"class":534,"line":627},[1554],{"type":415,"tag":532,"props":1555,"children":1556},{"style":545},[1557],{"type":420,"value":1558},"    \n",{"type":415,"tag":532,"props":1560,"children":1561},{"class":534,"line":677},[1562,1566,1570,1575,1579,1583,1587,1591,1596,1600],{"type":415,"tag":532,"props":1563,"children":1564},{"style":545},[1565],{"type":420,"value":773},{"type":415,"tag":532,"props":1567,"children":1568},{"style":551},[1569],{"type":420,"value":432},{"type":415,"tag":532,"props":1571,"children":1572},{"style":656},[1573],{"type":420,"value":1574},"AddTableServiceClient",{"type":415,"tag":532,"props":1576,"children":1577},{"style":551},[1578],{"type":420,"value":787},{"type":415,"tag":532,"props":1580,"children":1581},{"style":631},[1582],{"type":420,"value":792},{"type":415,"tag":532,"props":1584,"children":1585},{"style":551},[1586],{"type":420,"value":664},{"type":415,"tag":532,"props":1588,"children":1589},{"style":551},[1590],{"type":420,"value":801},{"type":415,"tag":532,"props":1592,"children":1593},{"style":804},[1594],{"type":420,"value":1595},"https://stdiwithazuresdk.table.core.windows.net",{"type":415,"tag":532,"props":1597,"children":1598},{"style":551},[1599],{"type":420,"value":801},{"type":415,"tag":532,"props":1601,"children":1602},{"style":551},[1603],{"type":420,"value":1299},{"type":415,"tag":532,"props":1605,"children":1606},{"class":534,"line":719},[1607,1611,1615,1619,1624],{"type":415,"tag":532,"props":1608,"children":1609},{"style":551},[1610],{"type":420,"value":1532},{"type":415,"tag":532,"props":1612,"children":1613},{"style":656},[1614],{"type":420,"value":1537},{"type":415,"tag":532,"props":1616,"children":1617},{"style":551},[1618],{"type":420,"value":787},{"type":415,"tag":532,"props":1620,"children":1621},{"style":631},[1622],{"type":420,"value":1623}," EnvironmentCredential",{"type":415,"tag":532,"props":1625,"children":1626},{"style":551},[1627],{"type":420,"value":847},{"type":415,"tag":532,"props":1629,"children":1630},{"class":534,"line":758},[1631],{"type":415,"tag":532,"props":1632,"children":1633},{"emptyLinePlaceholder":621},[1634],{"type":420,"value":624},{"type":415,"tag":532,"props":1636,"children":1637},{"class":534,"line":767},[1638,1642,1646,1650,1654,1658,1662,1666,1670,1674],{"type":415,"tag":532,"props":1639,"children":1640},{"style":545},[1641],{"type":420,"value":773},{"type":415,"tag":532,"props":1643,"children":1644},{"style":551},[1645],{"type":420,"value":432},{"type":415,"tag":532,"props":1647,"children":1648},{"style":656},[1649],{"type":420,"value":782},{"type":415,"tag":532,"props":1651,"children":1652},{"style":551},[1653],{"type":420,"value":787},{"type":415,"tag":532,"props":1655,"children":1656},{"style":631},[1657],{"type":420,"value":792},{"type":415,"tag":532,"props":1659,"children":1660},{"style":551},[1661],{"type":420,"value":664},{"type":415,"tag":532,"props":1663,"children":1664},{"style":551},[1665],{"type":420,"value":801},{"type":415,"tag":532,"props":1667,"children":1668},{"style":804},[1669],{"type":420,"value":807},{"type":415,"tag":532,"props":1671,"children":1672},{"style":551},[1673],{"type":420,"value":801},{"type":415,"tag":532,"props":1675,"children":1676},{"style":551},[1677],{"type":420,"value":816},{"type":415,"tag":532,"props":1679,"children":1680},{"class":534,"line":819},[1681],{"type":415,"tag":532,"props":1682,"children":1683},{"style":545},[1684],{"type":420,"value":1558},{"type":415,"tag":532,"props":1686,"children":1687},{"class":534,"line":850},[1688,1692,1696,1700,1704,1708],{"type":415,"tag":532,"props":1689,"children":1690},{"style":545},[1691],{"type":420,"value":773},{"type":415,"tag":532,"props":1693,"children":1694},{"style":551},[1695],{"type":420,"value":432},{"type":415,"tag":532,"props":1697,"children":1698},{"style":656},[1699],{"type":420,"value":833},{"type":415,"tag":532,"props":1701,"children":1702},{"style":551},[1703],{"type":420,"value":787},{"type":415,"tag":532,"props":1705,"children":1706},{"style":631},[1707],{"type":420,"value":842},{"type":415,"tag":532,"props":1709,"children":1710},{"style":551},[1711],{"type":420,"value":847},{"type":415,"tag":532,"props":1713,"children":1714},{"class":534,"line":859},[1715],{"type":415,"tag":532,"props":1716,"children":1717},{"style":551},[1718],{"type":420,"value":856},{"type":415,"tag":416,"props":1720,"children":1721},{},[1722],{"type":420,"value":1723},"In the example above, we configured:",{"type":415,"tag":508,"props":1725,"children":1726},{},[1727,1732,1737],{"type":415,"tag":512,"props":1728,"children":1729},{},[1730],{"type":420,"value":1731},"the service bus client to use the managed identity of the application to obtain a valid token for the service bus",{"type":415,"tag":512,"props":1733,"children":1734},{},[1735],{"type":420,"value":1736},"the table client to use environment variables to obtain a valid token for the storage table",{"type":415,"tag":512,"props":1738,"children":1739},{},[1740,1742,1747],{"type":420,"value":1741},"the blob client without any credentials so that it will use the one that we configured by default (with the ",{"type":415,"tag":468,"props":1743,"children":1745},{"className":1744},[],[1746],{"type":420,"value":833},{"type":420,"value":1748}," method)",{"type":415,"tag":482,"props":1750,"children":1752},{"id":1751},"effortlessly-configure-the-azure-clients-options",[1753],{"type":420,"value":1754},"Effortlessly configure the Azure clients' options",{"type":415,"tag":416,"props":1756,"children":1757},{},[1758,1760,1765],{"type":420,"value":1759},"All Azure clients have options that can be effortlessly configured when registering them in the ",{"type":415,"tag":468,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":420,"value":741},{"type":420,"value":1766}," method.",{"type":415,"tag":523,"props":1768,"children":1770},{"className":525,"code":1769,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"))\n        .WithCredential(new DefaultAzureCredential())\n        .ConfigureOptions(options =>\n        {\n            options.TrimBlobNameSlashes = true;\n            options.Retry.MaxRetries = 10;\n            options.Diagnostics.IsLoggingEnabled = false;\n        });\n});\n",[1771],{"type":415,"tag":468,"props":1772,"children":1773},{"__ignoreMap":401},[1774,1809,1816,1859,1883,1908,1915,1946,1984,2022,2030],{"type":415,"tag":532,"props":1775,"children":1776},{"class":534,"line":535},[1777,1781,1785,1789,1793,1797,1801,1805],{"type":415,"tag":532,"props":1778,"children":1779},{"style":545},[1780],{"type":420,"value":683},{"type":415,"tag":532,"props":1782,"children":1783},{"style":551},[1784],{"type":420,"value":432},{"type":415,"tag":532,"props":1786,"children":1787},{"style":545},[1788],{"type":420,"value":692},{"type":415,"tag":532,"props":1790,"children":1791},{"style":551},[1792],{"type":420,"value":432},{"type":415,"tag":532,"props":1794,"children":1795},{"style":656},[1796],{"type":420,"value":741},{"type":415,"tag":532,"props":1798,"children":1799},{"style":551},[1800],{"type":420,"value":664},{"type":415,"tag":532,"props":1802,"children":1803},{"style":631},[1804],{"type":420,"value":750},{"type":415,"tag":532,"props":1806,"children":1807},{"style":551},[1808],{"type":420,"value":755},{"type":415,"tag":532,"props":1810,"children":1811},{"class":534,"line":566},[1812],{"type":415,"tag":532,"props":1813,"children":1814},{"style":551},[1815],{"type":420,"value":764},{"type":415,"tag":532,"props":1817,"children":1818},{"class":534,"line":583},[1819,1823,1827,1831,1835,1839,1843,1847,1851,1855],{"type":415,"tag":532,"props":1820,"children":1821},{"style":545},[1822],{"type":420,"value":773},{"type":415,"tag":532,"props":1824,"children":1825},{"style":551},[1826],{"type":420,"value":432},{"type":415,"tag":532,"props":1828,"children":1829},{"style":656},[1830],{"type":420,"value":782},{"type":415,"tag":532,"props":1832,"children":1833},{"style":551},[1834],{"type":420,"value":787},{"type":415,"tag":532,"props":1836,"children":1837},{"style":631},[1838],{"type":420,"value":792},{"type":415,"tag":532,"props":1840,"children":1841},{"style":551},[1842],{"type":420,"value":664},{"type":415,"tag":532,"props":1844,"children":1845},{"style":551},[1846],{"type":420,"value":801},{"type":415,"tag":532,"props":1848,"children":1849},{"style":804},[1850],{"type":420,"value":807},{"type":415,"tag":532,"props":1852,"children":1853},{"style":551},[1854],{"type":420,"value":801},{"type":415,"tag":532,"props":1856,"children":1857},{"style":551},[1858],{"type":420,"value":1299},{"type":415,"tag":532,"props":1860,"children":1861},{"class":534,"line":617},[1862,1866,1870,1874,1878],{"type":415,"tag":532,"props":1863,"children":1864},{"style":551},[1865],{"type":420,"value":1532},{"type":415,"tag":532,"props":1867,"children":1868},{"style":656},[1869],{"type":420,"value":1537},{"type":415,"tag":532,"props":1871,"children":1872},{"style":551},[1873],{"type":420,"value":787},{"type":415,"tag":532,"props":1875,"children":1876},{"style":631},[1877],{"type":420,"value":842},{"type":415,"tag":532,"props":1879,"children":1880},{"style":551},[1881],{"type":420,"value":1882},"())\n",{"type":415,"tag":532,"props":1884,"children":1885},{"class":534,"line":627},[1886,1890,1895,1899,1904],{"type":415,"tag":532,"props":1887,"children":1888},{"style":551},[1889],{"type":420,"value":1532},{"type":415,"tag":532,"props":1891,"children":1892},{"style":656},[1893],{"type":420,"value":1894},"ConfigureOptions",{"type":415,"tag":532,"props":1896,"children":1897},{"style":551},[1898],{"type":420,"value":664},{"type":415,"tag":532,"props":1900,"children":1901},{"style":631},[1902],{"type":420,"value":1903},"options",{"type":415,"tag":532,"props":1905,"children":1906},{"style":551},[1907],{"type":420,"value":755},{"type":415,"tag":532,"props":1909,"children":1910},{"class":534,"line":677},[1911],{"type":415,"tag":532,"props":1912,"children":1913},{"style":551},[1914],{"type":420,"value":1308},{"type":415,"tag":532,"props":1916,"children":1917},{"class":534,"line":719},[1918,1923,1927,1932,1936,1942],{"type":415,"tag":532,"props":1919,"children":1920},{"style":545},[1921],{"type":420,"value":1922},"            options",{"type":415,"tag":532,"props":1924,"children":1925},{"style":551},[1926],{"type":420,"value":432},{"type":415,"tag":532,"props":1928,"children":1929},{"style":545},[1930],{"type":420,"value":1931},"TrimBlobNameSlashes ",{"type":415,"tag":532,"props":1933,"children":1934},{"style":551},[1935],{"type":420,"value":1134},{"type":415,"tag":532,"props":1937,"children":1939},{"style":1938},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[1940],{"type":420,"value":1941}," true",{"type":415,"tag":532,"props":1943,"children":1944},{"style":551},[1945],{"type":420,"value":563},{"type":415,"tag":532,"props":1947,"children":1948},{"class":534,"line":758},[1949,1953,1957,1962,1966,1971,1975,1980],{"type":415,"tag":532,"props":1950,"children":1951},{"style":545},[1952],{"type":420,"value":1922},{"type":415,"tag":532,"props":1954,"children":1955},{"style":551},[1956],{"type":420,"value":432},{"type":415,"tag":532,"props":1958,"children":1959},{"style":545},[1960],{"type":420,"value":1961},"Retry",{"type":415,"tag":532,"props":1963,"children":1964},{"style":551},[1965],{"type":420,"value":432},{"type":415,"tag":532,"props":1967,"children":1968},{"style":545},[1969],{"type":420,"value":1970},"MaxRetries ",{"type":415,"tag":532,"props":1972,"children":1973},{"style":551},[1974],{"type":420,"value":1134},{"type":415,"tag":532,"props":1976,"children":1977},{"style":539},[1978],{"type":420,"value":1979}," 10",{"type":415,"tag":532,"props":1981,"children":1982},{"style":551},[1983],{"type":420,"value":563},{"type":415,"tag":532,"props":1985,"children":1986},{"class":534,"line":767},[1987,1991,1995,2000,2004,2009,2013,2018],{"type":415,"tag":532,"props":1988,"children":1989},{"style":545},[1990],{"type":420,"value":1922},{"type":415,"tag":532,"props":1992,"children":1993},{"style":551},[1994],{"type":420,"value":432},{"type":415,"tag":532,"props":1996,"children":1997},{"style":545},[1998],{"type":420,"value":1999},"Diagnostics",{"type":415,"tag":532,"props":2001,"children":2002},{"style":551},[2003],{"type":420,"value":432},{"type":415,"tag":532,"props":2005,"children":2006},{"style":545},[2007],{"type":420,"value":2008},"IsLoggingEnabled ",{"type":415,"tag":532,"props":2010,"children":2011},{"style":551},[2012],{"type":420,"value":1134},{"type":415,"tag":532,"props":2014,"children":2015},{"style":1938},[2016],{"type":420,"value":2017}," false",{"type":415,"tag":532,"props":2019,"children":2020},{"style":551},[2021],{"type":420,"value":563},{"type":415,"tag":532,"props":2023,"children":2024},{"class":534,"line":819},[2025],{"type":415,"tag":532,"props":2026,"children":2027},{"style":551},[2028],{"type":420,"value":2029},"        });\n",{"type":415,"tag":532,"props":2031,"children":2032},{"class":534,"line":850},[2033],{"type":415,"tag":532,"props":2034,"children":2035},{"style":551},[2036],{"type":420,"value":856},{"type":415,"tag":416,"props":2038,"children":2039},{},[2040,2042,2048],{"type":420,"value":2041},"Some options are specific to the client (like the ",{"type":415,"tag":468,"props":2043,"children":2045},{"className":2044},[],[2046],{"type":420,"value":2047},"TrimBlobNameSlashes",{"type":420,"value":2049}," here for Blob client). Others can be configured globally and overridden on a client if necessary.",{"type":415,"tag":523,"props":2051,"children":2053},{"className":525,"code":2052,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n   clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"))\n        .WithCredential(new DefaultAzureCredential())\n        .ConfigureOptions(options =>\n        {\n            options.TrimBlobNameSlashes = true;\n            options.Retry.MaxRetries = 10;\n            options.Diagnostics.IsLoggingEnabled = false;\n        });\n    \n    clientBuilder.ConfigureDefaults(options =>\n    {\n        options.Retry.MaxRetries = 5;\n        options.Retry.Mode = RetryMode.Exponential;\n        options.Diagnostics.IsDistributedTracingEnabled = true;\n    });\n});\n",[2054],{"type":415,"tag":468,"props":2055,"children":2056},{"__ignoreMap":401},[2057,2092,2099,2143,2166,2189,2196,2223,2258,2293,2300,2307,2335,2342,2379,2425,2461,2469],{"type":415,"tag":532,"props":2058,"children":2059},{"class":534,"line":535},[2060,2064,2068,2072,2076,2080,2084,2088],{"type":415,"tag":532,"props":2061,"children":2062},{"style":545},[2063],{"type":420,"value":683},{"type":415,"tag":532,"props":2065,"children":2066},{"style":551},[2067],{"type":420,"value":432},{"type":415,"tag":532,"props":2069,"children":2070},{"style":545},[2071],{"type":420,"value":692},{"type":415,"tag":532,"props":2073,"children":2074},{"style":551},[2075],{"type":420,"value":432},{"type":415,"tag":532,"props":2077,"children":2078},{"style":656},[2079],{"type":420,"value":741},{"type":415,"tag":532,"props":2081,"children":2082},{"style":551},[2083],{"type":420,"value":664},{"type":415,"tag":532,"props":2085,"children":2086},{"style":631},[2087],{"type":420,"value":750},{"type":415,"tag":532,"props":2089,"children":2090},{"style":551},[2091],{"type":420,"value":755},{"type":415,"tag":532,"props":2093,"children":2094},{"class":534,"line":566},[2095],{"type":415,"tag":532,"props":2096,"children":2097},{"style":551},[2098],{"type":420,"value":764},{"type":415,"tag":532,"props":2100,"children":2101},{"class":534,"line":583},[2102,2107,2111,2115,2119,2123,2127,2131,2135,2139],{"type":415,"tag":532,"props":2103,"children":2104},{"style":545},[2105],{"type":420,"value":2106},"   clientBuilder",{"type":415,"tag":532,"props":2108,"children":2109},{"style":551},[2110],{"type":420,"value":432},{"type":415,"tag":532,"props":2112,"children":2113},{"style":656},[2114],{"type":420,"value":782},{"type":415,"tag":532,"props":2116,"children":2117},{"style":551},[2118],{"type":420,"value":787},{"type":415,"tag":532,"props":2120,"children":2121},{"style":631},[2122],{"type":420,"value":792},{"type":415,"tag":532,"props":2124,"children":2125},{"style":551},[2126],{"type":420,"value":664},{"type":415,"tag":532,"props":2128,"children":2129},{"style":551},[2130],{"type":420,"value":801},{"type":415,"tag":532,"props":2132,"children":2133},{"style":804},[2134],{"type":420,"value":807},{"type":415,"tag":532,"props":2136,"children":2137},{"style":551},[2138],{"type":420,"value":801},{"type":415,"tag":532,"props":2140,"children":2141},{"style":551},[2142],{"type":420,"value":1299},{"type":415,"tag":532,"props":2144,"children":2145},{"class":534,"line":617},[2146,2150,2154,2158,2162],{"type":415,"tag":532,"props":2147,"children":2148},{"style":551},[2149],{"type":420,"value":1532},{"type":415,"tag":532,"props":2151,"children":2152},{"style":656},[2153],{"type":420,"value":1537},{"type":415,"tag":532,"props":2155,"children":2156},{"style":551},[2157],{"type":420,"value":787},{"type":415,"tag":532,"props":2159,"children":2160},{"style":631},[2161],{"type":420,"value":842},{"type":415,"tag":532,"props":2163,"children":2164},{"style":551},[2165],{"type":420,"value":1882},{"type":415,"tag":532,"props":2167,"children":2168},{"class":534,"line":627},[2169,2173,2177,2181,2185],{"type":415,"tag":532,"props":2170,"children":2171},{"style":551},[2172],{"type":420,"value":1532},{"type":415,"tag":532,"props":2174,"children":2175},{"style":656},[2176],{"type":420,"value":1894},{"type":415,"tag":532,"props":2178,"children":2179},{"style":551},[2180],{"type":420,"value":664},{"type":415,"tag":532,"props":2182,"children":2183},{"style":631},[2184],{"type":420,"value":1903},{"type":415,"tag":532,"props":2186,"children":2187},{"style":551},[2188],{"type":420,"value":755},{"type":415,"tag":532,"props":2190,"children":2191},{"class":534,"line":677},[2192],{"type":415,"tag":532,"props":2193,"children":2194},{"style":551},[2195],{"type":420,"value":1308},{"type":415,"tag":532,"props":2197,"children":2198},{"class":534,"line":719},[2199,2203,2207,2211,2215,2219],{"type":415,"tag":532,"props":2200,"children":2201},{"style":545},[2202],{"type":420,"value":1922},{"type":415,"tag":532,"props":2204,"children":2205},{"style":551},[2206],{"type":420,"value":432},{"type":415,"tag":532,"props":2208,"children":2209},{"style":545},[2210],{"type":420,"value":1931},{"type":415,"tag":532,"props":2212,"children":2213},{"style":551},[2214],{"type":420,"value":1134},{"type":415,"tag":532,"props":2216,"children":2217},{"style":1938},[2218],{"type":420,"value":1941},{"type":415,"tag":532,"props":2220,"children":2221},{"style":551},[2222],{"type":420,"value":563},{"type":415,"tag":532,"props":2224,"children":2225},{"class":534,"line":758},[2226,2230,2234,2238,2242,2246,2250,2254],{"type":415,"tag":532,"props":2227,"children":2228},{"style":545},[2229],{"type":420,"value":1922},{"type":415,"tag":532,"props":2231,"children":2232},{"style":551},[2233],{"type":420,"value":432},{"type":415,"tag":532,"props":2235,"children":2236},{"style":545},[2237],{"type":420,"value":1961},{"type":415,"tag":532,"props":2239,"children":2240},{"style":551},[2241],{"type":420,"value":432},{"type":415,"tag":532,"props":2243,"children":2244},{"style":545},[2245],{"type":420,"value":1970},{"type":415,"tag":532,"props":2247,"children":2248},{"style":551},[2249],{"type":420,"value":1134},{"type":415,"tag":532,"props":2251,"children":2252},{"style":539},[2253],{"type":420,"value":1979},{"type":415,"tag":532,"props":2255,"children":2256},{"style":551},[2257],{"type":420,"value":563},{"type":415,"tag":532,"props":2259,"children":2260},{"class":534,"line":767},[2261,2265,2269,2273,2277,2281,2285,2289],{"type":415,"tag":532,"props":2262,"children":2263},{"style":545},[2264],{"type":420,"value":1922},{"type":415,"tag":532,"props":2266,"children":2267},{"style":551},[2268],{"type":420,"value":432},{"type":415,"tag":532,"props":2270,"children":2271},{"style":545},[2272],{"type":420,"value":1999},{"type":415,"tag":532,"props":2274,"children":2275},{"style":551},[2276],{"type":420,"value":432},{"type":415,"tag":532,"props":2278,"children":2279},{"style":545},[2280],{"type":420,"value":2008},{"type":415,"tag":532,"props":2282,"children":2283},{"style":551},[2284],{"type":420,"value":1134},{"type":415,"tag":532,"props":2286,"children":2287},{"style":1938},[2288],{"type":420,"value":2017},{"type":415,"tag":532,"props":2290,"children":2291},{"style":551},[2292],{"type":420,"value":563},{"type":415,"tag":532,"props":2294,"children":2295},{"class":534,"line":819},[2296],{"type":415,"tag":532,"props":2297,"children":2298},{"style":551},[2299],{"type":420,"value":2029},{"type":415,"tag":532,"props":2301,"children":2302},{"class":534,"line":850},[2303],{"type":415,"tag":532,"props":2304,"children":2305},{"style":545},[2306],{"type":420,"value":1558},{"type":415,"tag":532,"props":2308,"children":2309},{"class":534,"line":859},[2310,2314,2318,2323,2327,2331],{"type":415,"tag":532,"props":2311,"children":2312},{"style":545},[2313],{"type":420,"value":773},{"type":415,"tag":532,"props":2315,"children":2316},{"style":551},[2317],{"type":420,"value":432},{"type":415,"tag":532,"props":2319,"children":2320},{"style":656},[2321],{"type":420,"value":2322},"ConfigureDefaults",{"type":415,"tag":532,"props":2324,"children":2325},{"style":551},[2326],{"type":420,"value":664},{"type":415,"tag":532,"props":2328,"children":2329},{"style":631},[2330],{"type":420,"value":1903},{"type":415,"tag":532,"props":2332,"children":2333},{"style":551},[2334],{"type":420,"value":755},{"type":415,"tag":532,"props":2336,"children":2337},{"class":534,"line":867},[2338],{"type":415,"tag":532,"props":2339,"children":2340},{"style":551},[2341],{"type":420,"value":1121},{"type":415,"tag":532,"props":2343,"children":2344},{"class":534,"line":902},[2345,2350,2354,2358,2362,2366,2370,2375],{"type":415,"tag":532,"props":2346,"children":2347},{"style":545},[2348],{"type":420,"value":2349},"        options",{"type":415,"tag":532,"props":2351,"children":2352},{"style":551},[2353],{"type":420,"value":432},{"type":415,"tag":532,"props":2355,"children":2356},{"style":545},[2357],{"type":420,"value":1961},{"type":415,"tag":532,"props":2359,"children":2360},{"style":551},[2361],{"type":420,"value":432},{"type":415,"tag":532,"props":2363,"children":2364},{"style":545},[2365],{"type":420,"value":1970},{"type":415,"tag":532,"props":2367,"children":2368},{"style":551},[2369],{"type":420,"value":1134},{"type":415,"tag":532,"props":2371,"children":2372},{"style":539},[2373],{"type":420,"value":2374}," 5",{"type":415,"tag":532,"props":2376,"children":2377},{"style":551},[2378],{"type":420,"value":563},{"type":415,"tag":532,"props":2380,"children":2381},{"class":534,"line":1302},[2382,2386,2390,2394,2398,2403,2407,2412,2416,2421],{"type":415,"tag":532,"props":2383,"children":2384},{"style":545},[2385],{"type":420,"value":2349},{"type":415,"tag":532,"props":2387,"children":2388},{"style":551},[2389],{"type":420,"value":432},{"type":415,"tag":532,"props":2391,"children":2392},{"style":545},[2393],{"type":420,"value":1961},{"type":415,"tag":532,"props":2395,"children":2396},{"style":551},[2397],{"type":420,"value":432},{"type":415,"tag":532,"props":2399,"children":2400},{"style":545},[2401],{"type":420,"value":2402},"Mode ",{"type":415,"tag":532,"props":2404,"children":2405},{"style":551},[2406],{"type":420,"value":1134},{"type":415,"tag":532,"props":2408,"children":2409},{"style":545},[2410],{"type":420,"value":2411}," RetryMode",{"type":415,"tag":532,"props":2413,"children":2414},{"style":551},[2415],{"type":420,"value":432},{"type":415,"tag":532,"props":2417,"children":2418},{"style":545},[2419],{"type":420,"value":2420},"Exponential",{"type":415,"tag":532,"props":2422,"children":2423},{"style":551},[2424],{"type":420,"value":563},{"type":415,"tag":532,"props":2426,"children":2427},{"class":534,"line":1311},[2428,2432,2436,2440,2444,2449,2453,2457],{"type":415,"tag":532,"props":2429,"children":2430},{"style":545},[2431],{"type":420,"value":2349},{"type":415,"tag":532,"props":2433,"children":2434},{"style":551},[2435],{"type":420,"value":432},{"type":415,"tag":532,"props":2437,"children":2438},{"style":545},[2439],{"type":420,"value":1999},{"type":415,"tag":532,"props":2441,"children":2442},{"style":551},[2443],{"type":420,"value":432},{"type":415,"tag":532,"props":2445,"children":2446},{"style":545},[2447],{"type":420,"value":2448},"IsDistributedTracingEnabled ",{"type":415,"tag":532,"props":2450,"children":2451},{"style":551},[2452],{"type":420,"value":1134},{"type":415,"tag":532,"props":2454,"children":2455},{"style":1938},[2456],{"type":420,"value":1941},{"type":415,"tag":532,"props":2458,"children":2459},{"style":551},[2460],{"type":420,"value":563},{"type":415,"tag":532,"props":2462,"children":2463},{"class":534,"line":1356},[2464],{"type":415,"tag":532,"props":2465,"children":2466},{"style":551},[2467],{"type":420,"value":2468},"    });\n",{"type":415,"tag":532,"props":2470,"children":2471},{"class":534,"line":1365},[2472],{"type":415,"tag":532,"props":2473,"children":2474},{"style":551},[2475],{"type":420,"value":856},{"type":415,"tag":416,"props":2477,"children":2478},{},[2479,2481,2486],{"type":420,"value":2480},"That's the purpose of the ",{"type":415,"tag":468,"props":2482,"children":2484},{"className":2483},[],[2485],{"type":420,"value":2322},{"type":420,"value":1766},{"type":415,"tag":434,"props":2488,"children":2489},{"icon":436},[2490],{"type":415,"tag":416,"props":2491,"children":2492},{},[2493,2495],{"type":420,"value":2494},"Please note that all this configuration (as well as the Uris of each client) can be loaded from the configuration like this ",{"type":415,"tag":468,"props":2496,"children":2498},{"className":2497},[],[2499],{"type":420,"value":2500},"clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Inventory:Tables\"));",{"type":415,"tag":482,"props":2502,"children":2504},{"id":2503},"use-named-clients-for-different-azure-resources",[2505],{"type":420,"value":2506},"Use named clients for different Azure resources",{"type":415,"tag":416,"props":2508,"children":2509},{},[2510,2512,2518],{"type":420,"value":2511},"Usually, you only need one client of each SDK in your application. Let's say you have multiple Azure Storage tables that are used in your application, you will only need to have one ",{"type":415,"tag":468,"props":2513,"children":2515},{"className":2514},[],[2516],{"type":420,"value":2517},"TableServiceClient",{"type":420,"value":2519},". However, if you are interacting with tables in two different storage accounts, you will need multiple table clients.",{"type":415,"tag":416,"props":2521,"children":2522},{},[2523],{"type":420,"value":2524},"To do that you can register your clients with a specific name:",{"type":415,"tag":523,"props":2526,"children":2528},{"className":525,"code":2527,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Shop:Inventory\"))\n        .WithName(\"Shop\");\n    clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Warehouse:Inventory\"))\n        .WithName(\"Warehouse\");\n}\n",[2529],{"type":415,"tag":468,"props":2530,"children":2531},{"__ignoreMap":401},[2532,2567,2574,2635,2668,2728,2760],{"type":415,"tag":532,"props":2533,"children":2534},{"class":534,"line":535},[2535,2539,2543,2547,2551,2555,2559,2563],{"type":415,"tag":532,"props":2536,"children":2537},{"style":545},[2538],{"type":420,"value":683},{"type":415,"tag":532,"props":2540,"children":2541},{"style":551},[2542],{"type":420,"value":432},{"type":415,"tag":532,"props":2544,"children":2545},{"style":545},[2546],{"type":420,"value":692},{"type":415,"tag":532,"props":2548,"children":2549},{"style":551},[2550],{"type":420,"value":432},{"type":415,"tag":532,"props":2552,"children":2553},{"style":656},[2554],{"type":420,"value":741},{"type":415,"tag":532,"props":2556,"children":2557},{"style":551},[2558],{"type":420,"value":664},{"type":415,"tag":532,"props":2560,"children":2561},{"style":631},[2562],{"type":420,"value":750},{"type":415,"tag":532,"props":2564,"children":2565},{"style":551},[2566],{"type":420,"value":755},{"type":415,"tag":532,"props":2568,"children":2569},{"class":534,"line":566},[2570],{"type":415,"tag":532,"props":2571,"children":2572},{"style":551},[2573],{"type":420,"value":764},{"type":415,"tag":532,"props":2575,"children":2576},{"class":534,"line":583},[2577,2581,2585,2589,2593,2597,2601,2605,2609,2614,2618,2622,2627,2631],{"type":415,"tag":532,"props":2578,"children":2579},{"style":545},[2580],{"type":420,"value":773},{"type":415,"tag":532,"props":2582,"children":2583},{"style":551},[2584],{"type":420,"value":432},{"type":415,"tag":532,"props":2586,"children":2587},{"style":656},[2588],{"type":420,"value":1574},{"type":415,"tag":532,"props":2590,"children":2591},{"style":551},[2592],{"type":420,"value":664},{"type":415,"tag":532,"props":2594,"children":2595},{"style":545},[2596],{"type":420,"value":683},{"type":415,"tag":532,"props":2598,"children":2599},{"style":551},[2600],{"type":420,"value":432},{"type":415,"tag":532,"props":2602,"children":2603},{"style":545},[2604],{"type":420,"value":263},{"type":415,"tag":532,"props":2606,"children":2607},{"style":551},[2608],{"type":420,"value":432},{"type":415,"tag":532,"props":2610,"children":2611},{"style":656},[2612],{"type":420,"value":2613},"GetSection",{"type":415,"tag":532,"props":2615,"children":2616},{"style":551},[2617],{"type":420,"value":664},{"type":415,"tag":532,"props":2619,"children":2620},{"style":551},[2621],{"type":420,"value":801},{"type":415,"tag":532,"props":2623,"children":2624},{"style":804},[2625],{"type":420,"value":2626},"Shop:Inventory",{"type":415,"tag":532,"props":2628,"children":2629},{"style":551},[2630],{"type":420,"value":801},{"type":415,"tag":532,"props":2632,"children":2633},{"style":551},[2634],{"type":420,"value":1299},{"type":415,"tag":532,"props":2636,"children":2637},{"class":534,"line":617},[2638,2642,2647,2651,2655,2660,2664],{"type":415,"tag":532,"props":2639,"children":2640},{"style":551},[2641],{"type":420,"value":1532},{"type":415,"tag":532,"props":2643,"children":2644},{"style":656},[2645],{"type":420,"value":2646},"WithName",{"type":415,"tag":532,"props":2648,"children":2649},{"style":551},[2650],{"type":420,"value":664},{"type":415,"tag":532,"props":2652,"children":2653},{"style":551},[2654],{"type":420,"value":801},{"type":415,"tag":532,"props":2656,"children":2657},{"style":804},[2658],{"type":420,"value":2659},"Shop",{"type":415,"tag":532,"props":2661,"children":2662},{"style":551},[2663],{"type":420,"value":801},{"type":415,"tag":532,"props":2665,"children":2666},{"style":551},[2667],{"type":420,"value":674},{"type":415,"tag":532,"props":2669,"children":2670},{"class":534,"line":627},[2671,2675,2679,2683,2687,2691,2695,2699,2703,2707,2711,2715,2720,2724],{"type":415,"tag":532,"props":2672,"children":2673},{"style":545},[2674],{"type":420,"value":773},{"type":415,"tag":532,"props":2676,"children":2677},{"style":551},[2678],{"type":420,"value":432},{"type":415,"tag":532,"props":2680,"children":2681},{"style":656},[2682],{"type":420,"value":1574},{"type":415,"tag":532,"props":2684,"children":2685},{"style":551},[2686],{"type":420,"value":664},{"type":415,"tag":532,"props":2688,"children":2689},{"style":545},[2690],{"type":420,"value":683},{"type":415,"tag":532,"props":2692,"children":2693},{"style":551},[2694],{"type":420,"value":432},{"type":415,"tag":532,"props":2696,"children":2697},{"style":545},[2698],{"type":420,"value":263},{"type":415,"tag":532,"props":2700,"children":2701},{"style":551},[2702],{"type":420,"value":432},{"type":415,"tag":532,"props":2704,"children":2705},{"style":656},[2706],{"type":420,"value":2613},{"type":415,"tag":532,"props":2708,"children":2709},{"style":551},[2710],{"type":420,"value":664},{"type":415,"tag":532,"props":2712,"children":2713},{"style":551},[2714],{"type":420,"value":801},{"type":415,"tag":532,"props":2716,"children":2717},{"style":804},[2718],{"type":420,"value":2719},"Warehouse:Inventory",{"type":415,"tag":532,"props":2721,"children":2722},{"style":551},[2723],{"type":420,"value":801},{"type":415,"tag":532,"props":2725,"children":2726},{"style":551},[2727],{"type":420,"value":1299},{"type":415,"tag":532,"props":2729,"children":2730},{"class":534,"line":677},[2731,2735,2739,2743,2747,2752,2756],{"type":415,"tag":532,"props":2732,"children":2733},{"style":551},[2734],{"type":420,"value":1532},{"type":415,"tag":532,"props":2736,"children":2737},{"style":656},[2738],{"type":420,"value":2646},{"type":415,"tag":532,"props":2740,"children":2741},{"style":551},[2742],{"type":420,"value":664},{"type":415,"tag":532,"props":2744,"children":2745},{"style":551},[2746],{"type":420,"value":801},{"type":415,"tag":532,"props":2748,"children":2749},{"style":804},[2750],{"type":420,"value":2751},"Warehouse",{"type":415,"tag":532,"props":2753,"children":2754},{"style":551},[2755],{"type":420,"value":801},{"type":415,"tag":532,"props":2757,"children":2758},{"style":551},[2759],{"type":420,"value":674},{"type":415,"tag":532,"props":2761,"children":2762},{"class":534,"line":719},[2763],{"type":415,"tag":532,"props":2764,"children":2765},{"style":551},[2766],{"type":420,"value":1379},{"type":415,"tag":416,"props":2768,"children":2769},{},[2770],{"type":420,"value":2771},"This way, you will be able to retrieve the specific client you need in your code:",{"type":415,"tag":523,"props":2773,"children":2775},{"className":525,"code":2774,"language":326,"meta":401,"style":401},"public class WarehouseDeliveryService\n{\n    private readonly TableServiceClient _tableServiceClient;\n\n    public WarehouseDeliveryService(IAzureClientFactory\u003CTableServiceClient> azureClientFactory)\n    {\n        _tableServiceClient = azureClientFactory.CreateClient(\"Warehouse\");\n    }\n}\n",[2776],{"type":415,"tag":468,"props":2777,"children":2778},{"__ignoreMap":401},[2779,2795,2802,2827,2834,2876,2883,2928,2935],{"type":415,"tag":532,"props":2780,"children":2781},{"class":534,"line":535},[2782,2786,2790],{"type":415,"tag":532,"props":2783,"children":2784},{"style":954},[2785],{"type":420,"value":957},{"type":415,"tag":532,"props":2787,"children":2788},{"style":631},[2789],{"type":420,"value":962},{"type":415,"tag":532,"props":2791,"children":2792},{"style":631},[2793],{"type":420,"value":2794}," WarehouseDeliveryService\n",{"type":415,"tag":532,"props":2796,"children":2797},{"class":534,"line":566},[2798],{"type":415,"tag":532,"props":2799,"children":2800},{"style":551},[2801],{"type":420,"value":764},{"type":415,"tag":532,"props":2803,"children":2804},{"class":534,"line":583},[2805,2809,2813,2818,2823],{"type":415,"tag":532,"props":2806,"children":2807},{"style":954},[2808],{"type":420,"value":992},{"type":415,"tag":532,"props":2810,"children":2811},{"style":954},[2812],{"type":420,"value":997},{"type":415,"tag":532,"props":2814,"children":2815},{"style":631},[2816],{"type":420,"value":2817}," TableServiceClient",{"type":415,"tag":532,"props":2819,"children":2820},{"style":631},[2821],{"type":420,"value":2822}," _tableServiceClient",{"type":415,"tag":532,"props":2824,"children":2825},{"style":551},[2826],{"type":420,"value":563},{"type":415,"tag":532,"props":2828,"children":2829},{"class":534,"line":617},[2830],{"type":415,"tag":532,"props":2831,"children":2832},{"emptyLinePlaceholder":621},[2833],{"type":420,"value":624},{"type":415,"tag":532,"props":2835,"children":2836},{"class":534,"line":627},[2837,2841,2846,2850,2855,2859,2863,2867,2872],{"type":415,"tag":532,"props":2838,"children":2839},{"style":954},[2840],{"type":420,"value":1064},{"type":415,"tag":532,"props":2842,"children":2843},{"style":656},[2844],{"type":420,"value":2845}," WarehouseDeliveryService",{"type":415,"tag":532,"props":2847,"children":2848},{"style":551},[2849],{"type":420,"value":664},{"type":415,"tag":532,"props":2851,"children":2852},{"style":631},[2853],{"type":420,"value":2854},"IAzureClientFactory",{"type":415,"tag":532,"props":2856,"children":2857},{"style":551},[2858],{"type":420,"value":706},{"type":415,"tag":532,"props":2860,"children":2861},{"style":631},[2862],{"type":420,"value":2517},{"type":415,"tag":532,"props":2864,"children":2865},{"style":551},[2866],{"type":420,"value":1015},{"type":415,"tag":532,"props":2868,"children":2869},{"style":631},[2870],{"type":420,"value":2871}," azureClientFactory",{"type":415,"tag":532,"props":2873,"children":2874},{"style":551},[2875],{"type":420,"value":1113},{"type":415,"tag":532,"props":2877,"children":2878},{"class":534,"line":677},[2879],{"type":415,"tag":532,"props":2880,"children":2881},{"style":551},[2882],{"type":420,"value":1121},{"type":415,"tag":532,"props":2884,"children":2885},{"class":534,"line":719},[2886,2891,2895,2899,2903,2908,2912,2916,2920,2924],{"type":415,"tag":532,"props":2887,"children":2888},{"style":545},[2889],{"type":420,"value":2890},"        _tableServiceClient ",{"type":415,"tag":532,"props":2892,"children":2893},{"style":551},[2894],{"type":420,"value":1134},{"type":415,"tag":532,"props":2896,"children":2897},{"style":545},[2898],{"type":420,"value":2871},{"type":415,"tag":532,"props":2900,"children":2901},{"style":551},[2902],{"type":420,"value":432},{"type":415,"tag":532,"props":2904,"children":2905},{"style":656},[2906],{"type":420,"value":2907},"CreateClient",{"type":415,"tag":532,"props":2909,"children":2910},{"style":551},[2911],{"type":420,"value":664},{"type":415,"tag":532,"props":2913,"children":2914},{"style":551},[2915],{"type":420,"value":801},{"type":415,"tag":532,"props":2917,"children":2918},{"style":804},[2919],{"type":420,"value":2751},{"type":415,"tag":532,"props":2921,"children":2922},{"style":551},[2923],{"type":420,"value":801},{"type":415,"tag":532,"props":2925,"children":2926},{"style":551},[2927],{"type":420,"value":674},{"type":415,"tag":532,"props":2929,"children":2930},{"class":534,"line":758},[2931],{"type":415,"tag":532,"props":2932,"children":2933},{"style":551},[2934],{"type":420,"value":1170},{"type":415,"tag":532,"props":2936,"children":2937},{"class":534,"line":767},[2938],{"type":415,"tag":532,"props":2939,"children":2940},{"style":551},[2941],{"type":420,"value":1379},{"type":415,"tag":482,"props":2943,"children":2945},{"id":2944},"register-a-custom-client-factory",[2946],{"type":420,"value":2947},"Register a custom client factory",{"type":415,"tag":416,"props":2949,"children":2950},{},[2951,2953,2960,2962,2968],{"type":420,"value":2952},"If you have ",{"type":415,"tag":423,"props":2954,"children":2957},{"href":2955,"rel":2956},"https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/extensions/Microsoft.Extensions.Azure/README.md#registering-a-custom-client-factory",[427],[2958],{"type":420,"value":2959},"specific needs",{"type":420,"value":2961},", the ",{"type":415,"tag":468,"props":2963,"children":2965},{"className":2964},[],[2966],{"type":420,"value":2967},"AddClient",{"type":420,"value":2969}," method can help you register your Azure client while letting you control how you instantiate the client.",{"type":415,"tag":416,"props":2971,"children":2972},{},[2973,2975,2981,2983,2989,2991,2996,2998,3005,3007,3012],{"type":420,"value":2974},"For instance, the Azure Cosmos Db .NET SDK is not built on the same foundation (",{"type":415,"tag":468,"props":2976,"children":2978},{"className":2977},[],[2979],{"type":420,"value":2980},"Azure.Core",{"type":420,"value":2982},") as the other SDKs. So at the time of writing, there is no ",{"type":415,"tag":468,"props":2984,"children":2986},{"className":2985},[],[2987],{"type":420,"value":2988},"AddCosmosServiceClient",{"type":420,"value":2990}," you can use in the ",{"type":415,"tag":468,"props":2992,"children":2994},{"className":2993},[],[2995],{"type":420,"value":741},{"type":420,"value":2997}," (there is an ",{"type":415,"tag":423,"props":2999,"children":3002},{"href":3000,"rel":3001},"https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4002",[427],[3003],{"type":420,"value":3004},"issue",{"type":420,"value":3006}," about that though). However, you can use the ",{"type":415,"tag":468,"props":3008,"children":3010},{"className":3009},[],[3011],{"type":420,"value":2967},{"type":420,"value":3013}," I've just mentioned.",{"type":415,"tag":523,"props":3015,"children":3017},{"className":525,"code":3016,"language":326,"meta":401,"style":401},"builder.Services.AddOptions\u003CCosmosDbConfiguration>().BindConfiguration(\"Warehouse:CosmosDb\");\nbuilder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddClient\u003CCosmosClient, CosmosClientOptions>((_, _, serviceProvider) =>\n    {\n        var cosmosConfiguration = serviceProvider.GetRequiredService\u003CIOptions\u003CCosmosDbConfiguration>>().Value;\n        return new CosmosClientBuilder(cosmosConfiguration.Endpoint, cosmosConfiguration.AuthKey)\n            .WithSerializerOptions(new () { PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase })\n            .Build();\n    }).WithName(\"Warehouse\");\n}\n",[3018],{"type":415,"tag":468,"props":3019,"children":3020},{"__ignoreMap":401},[3021,3085,3120,3127,3196,3203,3264,3321,3376,3391,3423],{"type":415,"tag":532,"props":3022,"children":3023},{"class":534,"line":535},[3024,3028,3032,3036,3040,3045,3049,3054,3059,3064,3068,3072,3077,3081],{"type":415,"tag":532,"props":3025,"children":3026},{"style":545},[3027],{"type":420,"value":683},{"type":415,"tag":532,"props":3029,"children":3030},{"style":551},[3031],{"type":420,"value":432},{"type":415,"tag":532,"props":3033,"children":3034},{"style":545},[3035],{"type":420,"value":692},{"type":415,"tag":532,"props":3037,"children":3038},{"style":551},[3039],{"type":420,"value":432},{"type":415,"tag":532,"props":3041,"children":3042},{"style":656},[3043],{"type":420,"value":3044},"AddOptions",{"type":415,"tag":532,"props":3046,"children":3047},{"style":551},[3048],{"type":420,"value":706},{"type":415,"tag":532,"props":3050,"children":3051},{"style":631},[3052],{"type":420,"value":3053},"CosmosDbConfiguration",{"type":415,"tag":532,"props":3055,"children":3056},{"style":551},[3057],{"type":420,"value":3058},">().",{"type":415,"tag":532,"props":3060,"children":3061},{"style":656},[3062],{"type":420,"value":3063},"BindConfiguration",{"type":415,"tag":532,"props":3065,"children":3066},{"style":551},[3067],{"type":420,"value":664},{"type":415,"tag":532,"props":3069,"children":3070},{"style":551},[3071],{"type":420,"value":801},{"type":415,"tag":532,"props":3073,"children":3074},{"style":804},[3075],{"type":420,"value":3076},"Warehouse:CosmosDb",{"type":415,"tag":532,"props":3078,"children":3079},{"style":551},[3080],{"type":420,"value":801},{"type":415,"tag":532,"props":3082,"children":3083},{"style":551},[3084],{"type":420,"value":674},{"type":415,"tag":532,"props":3086,"children":3087},{"class":534,"line":566},[3088,3092,3096,3100,3104,3108,3112,3116],{"type":415,"tag":532,"props":3089,"children":3090},{"style":545},[3091],{"type":420,"value":683},{"type":415,"tag":532,"props":3093,"children":3094},{"style":551},[3095],{"type":420,"value":432},{"type":415,"tag":532,"props":3097,"children":3098},{"style":545},[3099],{"type":420,"value":692},{"type":415,"tag":532,"props":3101,"children":3102},{"style":551},[3103],{"type":420,"value":432},{"type":415,"tag":532,"props":3105,"children":3106},{"style":656},[3107],{"type":420,"value":741},{"type":415,"tag":532,"props":3109,"children":3110},{"style":551},[3111],{"type":420,"value":664},{"type":415,"tag":532,"props":3113,"children":3114},{"style":631},[3115],{"type":420,"value":750},{"type":415,"tag":532,"props":3117,"children":3118},{"style":551},[3119],{"type":420,"value":755},{"type":415,"tag":532,"props":3121,"children":3122},{"class":534,"line":583},[3123],{"type":415,"tag":532,"props":3124,"children":3125},{"style":551},[3126],{"type":420,"value":764},{"type":415,"tag":532,"props":3128,"children":3129},{"class":534,"line":617},[3130,3134,3138,3142,3146,3151,3155,3160,3165,3170,3174,3179,3183,3188,3192],{"type":415,"tag":532,"props":3131,"children":3132},{"style":545},[3133],{"type":420,"value":773},{"type":415,"tag":532,"props":3135,"children":3136},{"style":551},[3137],{"type":420,"value":432},{"type":415,"tag":532,"props":3139,"children":3140},{"style":656},[3141],{"type":420,"value":2967},{"type":415,"tag":532,"props":3143,"children":3144},{"style":551},[3145],{"type":420,"value":706},{"type":415,"tag":532,"props":3147,"children":3148},{"style":631},[3149],{"type":420,"value":3150},"CosmosClient",{"type":415,"tag":532,"props":3152,"children":3153},{"style":551},[3154],{"type":420,"value":1099},{"type":415,"tag":532,"props":3156,"children":3157},{"style":631},[3158],{"type":420,"value":3159}," CosmosClientOptions",{"type":415,"tag":532,"props":3161,"children":3162},{"style":551},[3163],{"type":420,"value":3164},">((",{"type":415,"tag":532,"props":3166,"children":3167},{"style":631},[3168],{"type":420,"value":3169},"_",{"type":415,"tag":532,"props":3171,"children":3172},{"style":551},[3173],{"type":420,"value":1099},{"type":415,"tag":532,"props":3175,"children":3176},{"style":631},[3177],{"type":420,"value":3178}," _",{"type":415,"tag":532,"props":3180,"children":3181},{"style":551},[3182],{"type":420,"value":1099},{"type":415,"tag":532,"props":3184,"children":3185},{"style":631},[3186],{"type":420,"value":3187}," serviceProvider",{"type":415,"tag":532,"props":3189,"children":3190},{"style":551},[3191],{"type":420,"value":1349},{"type":415,"tag":532,"props":3193,"children":3194},{"style":551},[3195],{"type":420,"value":755},{"type":415,"tag":532,"props":3197,"children":3198},{"class":534,"line":627},[3199],{"type":415,"tag":532,"props":3200,"children":3201},{"style":551},[3202],{"type":420,"value":1121},{"type":415,"tag":532,"props":3204,"children":3205},{"class":534,"line":677},[3206,3211,3216,3220,3224,3228,3233,3237,3242,3246,3250,3255,3260],{"type":415,"tag":532,"props":3207,"children":3208},{"style":631},[3209],{"type":420,"value":3210},"        var",{"type":415,"tag":532,"props":3212,"children":3213},{"style":631},[3214],{"type":420,"value":3215}," cosmosConfiguration",{"type":415,"tag":532,"props":3217,"children":3218},{"style":551},[3219],{"type":420,"value":644},{"type":415,"tag":532,"props":3221,"children":3222},{"style":545},[3223],{"type":420,"value":3187},{"type":415,"tag":532,"props":3225,"children":3226},{"style":551},[3227],{"type":420,"value":432},{"type":415,"tag":532,"props":3229,"children":3230},{"style":656},[3231],{"type":420,"value":3232},"GetRequiredService",{"type":415,"tag":532,"props":3234,"children":3235},{"style":551},[3236],{"type":420,"value":706},{"type":415,"tag":532,"props":3238,"children":3239},{"style":631},[3240],{"type":420,"value":3241},"IOptions",{"type":415,"tag":532,"props":3243,"children":3244},{"style":551},[3245],{"type":420,"value":706},{"type":415,"tag":532,"props":3247,"children":3248},{"style":631},[3249],{"type":420,"value":3053},{"type":415,"tag":532,"props":3251,"children":3252},{"style":551},[3253],{"type":420,"value":3254},">>().",{"type":415,"tag":532,"props":3256,"children":3257},{"style":545},[3258],{"type":420,"value":3259},"Value",{"type":415,"tag":532,"props":3261,"children":3262},{"style":551},[3263],{"type":420,"value":563},{"type":415,"tag":532,"props":3265,"children":3266},{"class":534,"line":719},[3267,3272,3277,3282,3286,3291,3295,3300,3304,3308,3312,3317],{"type":415,"tag":532,"props":3268,"children":3269},{"style":1241},[3270],{"type":420,"value":3271},"        return",{"type":415,"tag":532,"props":3273,"children":3274},{"style":551},[3275],{"type":420,"value":3276}," new",{"type":415,"tag":532,"props":3278,"children":3279},{"style":631},[3280],{"type":420,"value":3281}," CosmosClientBuilder",{"type":415,"tag":532,"props":3283,"children":3284},{"style":551},[3285],{"type":420,"value":664},{"type":415,"tag":532,"props":3287,"children":3288},{"style":545},[3289],{"type":420,"value":3290},"cosmosConfiguration",{"type":415,"tag":532,"props":3292,"children":3293},{"style":551},[3294],{"type":420,"value":432},{"type":415,"tag":532,"props":3296,"children":3297},{"style":545},[3298],{"type":420,"value":3299},"Endpoint",{"type":415,"tag":532,"props":3301,"children":3302},{"style":551},[3303],{"type":420,"value":1099},{"type":415,"tag":532,"props":3305,"children":3306},{"style":545},[3307],{"type":420,"value":3215},{"type":415,"tag":532,"props":3309,"children":3310},{"style":551},[3311],{"type":420,"value":432},{"type":415,"tag":532,"props":3313,"children":3314},{"style":545},[3315],{"type":420,"value":3316},"AuthKey",{"type":415,"tag":532,"props":3318,"children":3319},{"style":551},[3320],{"type":420,"value":1113},{"type":415,"tag":532,"props":3322,"children":3323},{"class":534,"line":758},[3324,3329,3334,3338,3343,3348,3353,3357,3362,3366,3371],{"type":415,"tag":532,"props":3325,"children":3326},{"style":551},[3327],{"type":420,"value":3328},"            .",{"type":415,"tag":532,"props":3330,"children":3331},{"style":656},[3332],{"type":420,"value":3333},"WithSerializerOptions",{"type":415,"tag":532,"props":3335,"children":3336},{"style":551},[3337],{"type":420,"value":787},{"type":415,"tag":532,"props":3339,"children":3340},{"style":551},[3341],{"type":420,"value":3342}," ()",{"type":415,"tag":532,"props":3344,"children":3345},{"style":551},[3346],{"type":420,"value":3347}," {",{"type":415,"tag":532,"props":3349,"children":3350},{"style":545},[3351],{"type":420,"value":3352}," PropertyNamingPolicy ",{"type":415,"tag":532,"props":3354,"children":3355},{"style":551},[3356],{"type":420,"value":1134},{"type":415,"tag":532,"props":3358,"children":3359},{"style":545},[3360],{"type":420,"value":3361}," CosmosPropertyNamingPolicy",{"type":415,"tag":532,"props":3363,"children":3364},{"style":551},[3365],{"type":420,"value":432},{"type":415,"tag":532,"props":3367,"children":3368},{"style":545},[3369],{"type":420,"value":3370},"CamelCase ",{"type":415,"tag":532,"props":3372,"children":3373},{"style":551},[3374],{"type":420,"value":3375},"})\n",{"type":415,"tag":532,"props":3377,"children":3378},{"class":534,"line":767},[3379,3383,3387],{"type":415,"tag":532,"props":3380,"children":3381},{"style":551},[3382],{"type":420,"value":3328},{"type":415,"tag":532,"props":3384,"children":3385},{"style":656},[3386],{"type":420,"value":894},{"type":415,"tag":532,"props":3388,"children":3389},{"style":551},[3390],{"type":420,"value":899},{"type":415,"tag":532,"props":3392,"children":3393},{"class":534,"line":819},[3394,3399,3403,3407,3411,3415,3419],{"type":415,"tag":532,"props":3395,"children":3396},{"style":551},[3397],{"type":420,"value":3398},"    }).",{"type":415,"tag":532,"props":3400,"children":3401},{"style":656},[3402],{"type":420,"value":2646},{"type":415,"tag":532,"props":3404,"children":3405},{"style":551},[3406],{"type":420,"value":664},{"type":415,"tag":532,"props":3408,"children":3409},{"style":551},[3410],{"type":420,"value":801},{"type":415,"tag":532,"props":3412,"children":3413},{"style":804},[3414],{"type":420,"value":2751},{"type":415,"tag":532,"props":3416,"children":3417},{"style":551},[3418],{"type":420,"value":801},{"type":415,"tag":532,"props":3420,"children":3421},{"style":551},[3422],{"type":420,"value":674},{"type":415,"tag":532,"props":3424,"children":3425},{"class":534,"line":850},[3426],{"type":415,"tag":532,"props":3427,"children":3428},{"style":551},[3429],{"type":420,"value":1379},{"type":415,"tag":416,"props":3431,"children":3432},{},[3433,3435,3440],{"type":420,"value":3434},"You can note that using the ",{"type":415,"tag":468,"props":3436,"children":3438},{"className":3437},[],[3439],{"type":420,"value":2967},{"type":420,"value":3441}," method allows us to take profit from the named clients' feature.",{"type":415,"tag":482,"props":3443,"children":3445},{"id":3444},"wrapping-up",[3446],{"type":420,"value":3447},"Wrapping up",{"type":415,"tag":416,"props":3449,"children":3450},{},[3451,3453,3462],{"type":420,"value":3452},"As you have seen, the use of the ",{"type":415,"tag":423,"props":3454,"children":3456},{"href":464,"rel":3455},[427],[3457],{"type":415,"tag":468,"props":3458,"children":3460},{"className":3459},[],[3461],{"type":420,"value":473},{"type":420,"value":3463}," package simplifies the registration and configuration of Azure clients. While providing you with a consistent way of handling the dependency injection for Azure SDKs, it also allows you to easily customize the authentication and other options available.",{"type":415,"tag":416,"props":3465,"children":3466},{},[3467],{"type":420,"value":3468},"I hope you learned something. Don't hesitate to share your tips or what you like about the Azure SDKs in the comments.",{"type":415,"tag":3470,"props":3471,"children":3472},"style",{},[3473],{"type":420,"value":3474},"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":566,"depth":566,"links":3476},[3477,3478,3479,3480,3481,3482],{"id":484,"depth":566,"text":487},{"id":1421,"depth":566,"text":1424},{"id":1751,"depth":566,"text":1754},{"id":2503,"depth":566,"text":2506},{"id":2944,"depth":566,"text":2947},{"id":3444,"depth":566,"text":3447},"markdown","content:1.posts:59.azure-sdk-di.md","content","1.posts/59.azure-sdk-di.md","md",{"_path":172,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":171,"description":3489,"lead":3490,"date":3491,"image":3492,"badge":3494,"tags":3495,"body":3496,"_type":3483,"_id":6756,"_source":3485,"_file":6757,"_extension":3487},"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":3493},"/images/azureOIDC_2.webp",{"label":266},[228,225,233,379,307,374,382],{"type":412,"children":3497,"toc":6745},[3498,3502,3508,3513,3518,3859,3873,3878,3890,3907,3913,3920,3934,3946,3958,3964,3977,3982,4052,4057,4145,4169,4174,4239,4270,4276,4281,4397,4429,4434,4606,4611,4744,4749,4961,4985,4998,5114,5119,5176,5182,5187,5206,5288,5293,5398,5407,5413,6687,6693,6706,6711,6731,6736,6741],{"type":415,"tag":416,"props":3499,"children":3500},{},[3501],{"type":420,"value":3489},{"type":415,"tag":482,"props":3503,"children":3505},{"id":3504},"the-objective",[3506],{"type":420,"value":3507},"The Objective",{"type":415,"tag":416,"props":3509,"children":3510},{},[3511],{"type":420,"value":3512},"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":415,"tag":416,"props":3514,"children":3515},{},[3516],{"type":420,"value":3517},"The workflow we plan to run is as follows:",{"type":415,"tag":523,"props":3519,"children":3523},{"className":3520,"code":3521,"language":3522,"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",[3524],{"type":415,"tag":468,"props":3525,"children":3526},{"__ignoreMap":401},[3527,3545,3558,3570,3577,3589,3606,3623,3635,3647,3664,3676,3708,3725,3737,3754,3771,3788,3795,3823,3841,3850],{"type":415,"tag":532,"props":3528,"children":3529},{"class":534,"line":535},[3530,3536,3540],{"type":415,"tag":532,"props":3531,"children":3533},{"style":3532},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[3534],{"type":420,"value":3535},"name",{"type":415,"tag":532,"props":3537,"children":3538},{"style":551},[3539],{"type":420,"value":1290},{"type":415,"tag":532,"props":3541,"children":3542},{"style":804},[3543],{"type":420,"value":3544}," Run Azure Login with OIDC\n",{"type":415,"tag":532,"props":3546,"children":3547},{"class":534,"line":566},[3548,3553],{"type":415,"tag":532,"props":3549,"children":3550},{"style":1938},[3551],{"type":420,"value":3552},"on",{"type":415,"tag":532,"props":3554,"children":3555},{"style":551},[3556],{"type":420,"value":3557},":\n",{"type":415,"tag":532,"props":3559,"children":3560},{"class":534,"line":583},[3561,3566],{"type":415,"tag":532,"props":3562,"children":3563},{"style":3532},[3564],{"type":420,"value":3565},"  workflow_dispatch",{"type":415,"tag":532,"props":3567,"children":3568},{"style":551},[3569],{"type":420,"value":3557},{"type":415,"tag":532,"props":3571,"children":3572},{"class":534,"line":617},[3573],{"type":415,"tag":532,"props":3574,"children":3575},{"emptyLinePlaceholder":621},[3576],{"type":420,"value":624},{"type":415,"tag":532,"props":3578,"children":3579},{"class":534,"line":627},[3580,3585],{"type":415,"tag":532,"props":3581,"children":3582},{"style":3532},[3583],{"type":420,"value":3584},"permissions",{"type":415,"tag":532,"props":3586,"children":3587},{"style":551},[3588],{"type":420,"value":3557},{"type":415,"tag":532,"props":3590,"children":3591},{"class":534,"line":677},[3592,3597,3601],{"type":415,"tag":532,"props":3593,"children":3594},{"style":3532},[3595],{"type":420,"value":3596},"  id-token",{"type":415,"tag":532,"props":3598,"children":3599},{"style":551},[3600],{"type":420,"value":1290},{"type":415,"tag":532,"props":3602,"children":3603},{"style":804},[3604],{"type":420,"value":3605}," write\n",{"type":415,"tag":532,"props":3607,"children":3608},{"class":534,"line":719},[3609,3614,3618],{"type":415,"tag":532,"props":3610,"children":3611},{"style":3532},[3612],{"type":420,"value":3613},"  contents",{"type":415,"tag":532,"props":3615,"children":3616},{"style":551},[3617],{"type":420,"value":1290},{"type":415,"tag":532,"props":3619,"children":3620},{"style":804},[3621],{"type":420,"value":3622}," read\n",{"type":415,"tag":532,"props":3624,"children":3625},{"class":534,"line":758},[3626,3631],{"type":415,"tag":532,"props":3627,"children":3628},{"style":3532},[3629],{"type":420,"value":3630},"jobs",{"type":415,"tag":532,"props":3632,"children":3633},{"style":551},[3634],{"type":420,"value":3557},{"type":415,"tag":532,"props":3636,"children":3637},{"class":534,"line":767},[3638,3643],{"type":415,"tag":532,"props":3639,"children":3640},{"style":3532},[3641],{"type":420,"value":3642},"  build-and-deploy",{"type":415,"tag":532,"props":3644,"children":3645},{"style":551},[3646],{"type":420,"value":3557},{"type":415,"tag":532,"props":3648,"children":3649},{"class":534,"line":819},[3650,3655,3659],{"type":415,"tag":532,"props":3651,"children":3652},{"style":3532},[3653],{"type":420,"value":3654},"    runs-on",{"type":415,"tag":532,"props":3656,"children":3657},{"style":551},[3658],{"type":420,"value":1290},{"type":415,"tag":532,"props":3660,"children":3661},{"style":804},[3662],{"type":420,"value":3663}," ubuntu-latest\n",{"type":415,"tag":532,"props":3665,"children":3666},{"class":534,"line":850},[3667,3672],{"type":415,"tag":532,"props":3668,"children":3669},{"style":3532},[3670],{"type":420,"value":3671},"    steps",{"type":415,"tag":532,"props":3673,"children":3674},{"style":551},[3675],{"type":420,"value":3557},{"type":415,"tag":532,"props":3677,"children":3678},{"class":534,"line":859},[3679,3684,3689,3693,3698,3703],{"type":415,"tag":532,"props":3680,"children":3681},{"style":551},[3682],{"type":420,"value":3683},"      -",{"type":415,"tag":532,"props":3685,"children":3686},{"style":3532},[3687],{"type":420,"value":3688}," name",{"type":415,"tag":532,"props":3690,"children":3691},{"style":551},[3692],{"type":420,"value":1290},{"type":415,"tag":532,"props":3694,"children":3695},{"style":551},[3696],{"type":420,"value":3697}," '",{"type":415,"tag":532,"props":3699,"children":3700},{"style":804},[3701],{"type":420,"value":3702},"Az CLI login",{"type":415,"tag":532,"props":3704,"children":3705},{"style":551},[3706],{"type":420,"value":3707},"'\n",{"type":415,"tag":532,"props":3709,"children":3710},{"class":534,"line":867},[3711,3716,3720],{"type":415,"tag":532,"props":3712,"children":3713},{"style":3532},[3714],{"type":420,"value":3715},"        uses",{"type":415,"tag":532,"props":3717,"children":3718},{"style":551},[3719],{"type":420,"value":1290},{"type":415,"tag":532,"props":3721,"children":3722},{"style":804},[3723],{"type":420,"value":3724}," azure/login@v1\n",{"type":415,"tag":532,"props":3726,"children":3727},{"class":534,"line":902},[3728,3733],{"type":415,"tag":532,"props":3729,"children":3730},{"style":3532},[3731],{"type":420,"value":3732},"        with",{"type":415,"tag":532,"props":3734,"children":3735},{"style":551},[3736],{"type":420,"value":3557},{"type":415,"tag":532,"props":3738,"children":3739},{"class":534,"line":1302},[3740,3745,3749],{"type":415,"tag":532,"props":3741,"children":3742},{"style":3532},[3743],{"type":420,"value":3744},"          client-id",{"type":415,"tag":532,"props":3746,"children":3747},{"style":551},[3748],{"type":420,"value":1290},{"type":415,"tag":532,"props":3750,"children":3751},{"style":804},[3752],{"type":420,"value":3753}," ${{ secrets.AZURE_CLIENT_ID }}\n",{"type":415,"tag":532,"props":3755,"children":3756},{"class":534,"line":1311},[3757,3762,3766],{"type":415,"tag":532,"props":3758,"children":3759},{"style":3532},[3760],{"type":420,"value":3761},"          tenant-id",{"type":415,"tag":532,"props":3763,"children":3764},{"style":551},[3765],{"type":420,"value":1290},{"type":415,"tag":532,"props":3767,"children":3768},{"style":804},[3769],{"type":420,"value":3770}," ${{ secrets.AZURE_TENANT_ID }}\n",{"type":415,"tag":532,"props":3772,"children":3773},{"class":534,"line":1356},[3774,3779,3783],{"type":415,"tag":532,"props":3775,"children":3776},{"style":3532},[3777],{"type":420,"value":3778},"          subscription-id",{"type":415,"tag":532,"props":3780,"children":3781},{"style":551},[3782],{"type":420,"value":1290},{"type":415,"tag":532,"props":3784,"children":3785},{"style":804},[3786],{"type":420,"value":3787}," ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n",{"type":415,"tag":532,"props":3789,"children":3790},{"class":534,"line":1365},[3791],{"type":415,"tag":532,"props":3792,"children":3793},{"emptyLinePlaceholder":621},[3794],{"type":420,"value":624},{"type":415,"tag":532,"props":3796,"children":3797},{"class":534,"line":1373},[3798,3802,3806,3810,3814,3819],{"type":415,"tag":532,"props":3799,"children":3800},{"style":551},[3801],{"type":420,"value":3683},{"type":415,"tag":532,"props":3803,"children":3804},{"style":3532},[3805],{"type":420,"value":3688},{"type":415,"tag":532,"props":3807,"children":3808},{"style":551},[3809],{"type":420,"value":1290},{"type":415,"tag":532,"props":3811,"children":3812},{"style":551},[3813],{"type":420,"value":3697},{"type":415,"tag":532,"props":3815,"children":3816},{"style":804},[3817],{"type":420,"value":3818},"Run az commands",{"type":415,"tag":532,"props":3820,"children":3821},{"style":551},[3822],{"type":420,"value":3707},{"type":415,"tag":532,"props":3824,"children":3826},{"class":534,"line":3825},20,[3827,3832,3836],{"type":415,"tag":532,"props":3828,"children":3829},{"style":3532},[3830],{"type":420,"value":3831},"        run",{"type":415,"tag":532,"props":3833,"children":3834},{"style":551},[3835],{"type":420,"value":1290},{"type":415,"tag":532,"props":3837,"children":3838},{"style":1241},[3839],{"type":420,"value":3840}," |\n",{"type":415,"tag":532,"props":3842,"children":3844},{"class":534,"line":3843},21,[3845],{"type":415,"tag":532,"props":3846,"children":3847},{"style":804},[3848],{"type":420,"value":3849},"          az account show\n",{"type":415,"tag":532,"props":3851,"children":3853},{"class":534,"line":3852},22,[3854],{"type":415,"tag":532,"props":3855,"children":3856},{"style":804},[3857],{"type":420,"value":3858},"          az group list\n",{"type":415,"tag":416,"props":3860,"children":3861},{},[3862,3864,3871],{"type":420,"value":3863},"This workflow is an example coming from ",{"type":415,"tag":423,"props":3865,"children":3868},{"href":3866,"rel":3867},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure",[427],[3869],{"type":420,"value":3870},"the GitHub documentation",{"type":420,"value":3872}," showing how to configure GitHub Actions workflow to access Azure resources protected by Microsoft Entra.",{"type":415,"tag":416,"props":3874,"children":3875},{},[3876],{"type":420,"value":3877},"To run this workflow we will need to automate the configuration of these resources:",{"type":415,"tag":416,"props":3879,"children":3880},{},[3881],{"type":415,"tag":3882,"props":3883,"children":3889},"img",{"alt":3884,"className":3885,"src":3888},"A diagram showing the interactions between Azure and GitHub.",[3886,3887],"rounded-lg","mx-auto","/posts/images/scripting_azurereadygithub_azure_1.webp",[],{"type":415,"tag":434,"props":3891,"children":3892},{"icon":1382},[3893],{"type":415,"tag":416,"props":3894,"children":3895},{},[3896,3898,3905],{"type":420,"value":3897},"Looks familiar? That's the same diagram from my article about ",{"type":415,"tag":423,"props":3899,"children":3902},{"href":3900,"rel":3901},"https://www.techwatching.dev/posts/azure-ready-github-repository",[427],[3903],{"type":420,"value":3904},"creating an Azure-Ready GitHub Repository using Pulumi",{"type":420,"value":3906},". 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":415,"tag":482,"props":3908,"children":3910},{"id":3909},"the-script",[3911],{"type":420,"value":3912},"The Script",{"type":415,"tag":3914,"props":3915,"children":3917},"h3",{"id":3916},"a-word-about-the-tools-used",[3918],{"type":420,"value":3919},"A word about the tools used",{"type":415,"tag":416,"props":3921,"children":3922},{},[3923,3925,3932],{"type":420,"value":3924},"I will be using ",{"type":415,"tag":423,"props":3926,"children":3929},{"href":3927,"rel":3928},"https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3",[427],[3930],{"type":420,"value":3931},"PowerShell which is cross-platform",{"type":420,"value":3933},". 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":415,"tag":416,"props":3935,"children":3936},{},[3937,3939,3945],{"type":420,"value":3938},"To create and configure the Microsoft Entra ID resources, we will need the ",{"type":415,"tag":423,"props":3940,"children":3943},{"href":3941,"rel":3942},"https://learn.microsoft.com/en-us/cli/azure/install-azure-cli",[427],[3944],{"type":420,"value":225},{"type":420,"value":432},{"type":415,"tag":416,"props":3947,"children":3948},{},[3949,3951,3957],{"type":420,"value":3950},"To create and configure the GitHub repository, we will need the ",{"type":415,"tag":423,"props":3952,"children":3955},{"href":3953,"rel":3954},"https://cli.github.com/",[427],[3956],{"type":420,"value":379},{"type":420,"value":432},{"type":415,"tag":3914,"props":3959,"children":3961},{"id":3960},"create-the-repository-on-github",[3962],{"type":420,"value":3963},"Create the repository on GitHub",{"type":415,"tag":416,"props":3965,"children":3966},{},[3967,3969,3975],{"type":420,"value":3968},"Let's assume we are already in a new directory with the YAML workflow file ",{"type":415,"tag":468,"props":3970,"children":3972},{"className":3971},[],[3973],{"type":420,"value":3974},".github\\workflows\\main.yml",{"type":420,"value":3976}," in it.",{"type":415,"tag":416,"props":3978,"children":3979},{},[3980],{"type":420,"value":3981},"First, we can initialize the git repository.",{"type":415,"tag":523,"props":3983,"children":3987},{"className":3984,"code":3985,"language":3986,"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",[3988],{"type":415,"tag":468,"props":3989,"children":3990},{"__ignoreMap":401},[3991,4003,4020],{"type":415,"tag":532,"props":3992,"children":3993},{"class":534,"line":535},[3994,3998],{"type":415,"tag":532,"props":3995,"children":3996},{"style":631},[3997],{"type":420,"value":241},{"type":415,"tag":532,"props":3999,"children":4000},{"style":804},[4001],{"type":420,"value":4002}," init\n",{"type":415,"tag":532,"props":4004,"children":4005},{"class":534,"line":566},[4006,4010,4015],{"type":415,"tag":532,"props":4007,"children":4008},{"style":631},[4009],{"type":420,"value":241},{"type":415,"tag":532,"props":4011,"children":4012},{"style":804},[4013],{"type":420,"value":4014}," add",{"type":415,"tag":532,"props":4016,"children":4017},{"style":804},[4018],{"type":420,"value":4019}," .\n",{"type":415,"tag":532,"props":4021,"children":4022},{"class":534,"line":583},[4023,4027,4032,4037,4042,4047],{"type":415,"tag":532,"props":4024,"children":4025},{"style":631},[4026],{"type":420,"value":241},{"type":415,"tag":532,"props":4028,"children":4029},{"style":804},[4030],{"type":420,"value":4031}," commit",{"type":415,"tag":532,"props":4033,"children":4034},{"style":804},[4035],{"type":420,"value":4036}," -m",{"type":415,"tag":532,"props":4038,"children":4039},{"style":551},[4040],{"type":420,"value":4041}," \"",{"type":415,"tag":532,"props":4043,"children":4044},{"style":804},[4045],{"type":420,"value":4046},"Intialize repository with the GitHub Actions workflow file",{"type":415,"tag":532,"props":4048,"children":4049},{"style":551},[4050],{"type":420,"value":4051},"\"\n",{"type":415,"tag":416,"props":4053,"children":4054},{},[4055],{"type":420,"value":4056},"Second, we can create the GitHub repository and push the git repository we just initialized in it.",{"type":415,"tag":523,"props":4058,"children":4061},{"className":4059,"code":4060,"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",[4062],{"type":415,"tag":468,"props":4063,"children":4064},{"__ignoreMap":401},[4065,4095],{"type":415,"tag":532,"props":4066,"children":4067},{"class":534,"line":535},[4068,4073,4078,4082,4086,4091],{"type":415,"tag":532,"props":4069,"children":4070},{"style":551},[4071],{"type":420,"value":4072},"$",{"type":415,"tag":532,"props":4074,"children":4075},{"style":545},[4076],{"type":420,"value":4077},"repositoryName ",{"type":415,"tag":532,"props":4079,"children":4080},{"style":551},[4081],{"type":420,"value":1134},{"type":415,"tag":532,"props":4083,"children":4084},{"style":551},[4085],{"type":420,"value":4041},{"type":415,"tag":532,"props":4087,"children":4088},{"style":804},[4089],{"type":420,"value":4090},"MyAzureReadyRepository",{"type":415,"tag":532,"props":4092,"children":4093},{"style":551},[4094],{"type":420,"value":4051},{"type":415,"tag":532,"props":4096,"children":4097},{"class":534,"line":566},[4098,4103,4107,4111,4116,4121,4125,4130,4135,4140],{"type":415,"tag":532,"props":4099,"children":4100},{"style":545},[4101],{"type":420,"value":4102},"gh repo create ",{"type":415,"tag":532,"props":4104,"children":4105},{"style":551},[4106],{"type":420,"value":4072},{"type":415,"tag":532,"props":4108,"children":4109},{"style":545},[4110],{"type":420,"value":4077},{"type":415,"tag":532,"props":4112,"children":4113},{"style":551},[4114],{"type":420,"value":4115},"--",{"type":415,"tag":532,"props":4117,"children":4118},{"style":545},[4119],{"type":420,"value":4120},"private ",{"type":415,"tag":532,"props":4122,"children":4123},{"style":551},[4124],{"type":420,"value":4115},{"type":415,"tag":532,"props":4126,"children":4127},{"style":545},[4128],{"type":420,"value":4129},"source",{"type":415,"tag":532,"props":4131,"children":4132},{"style":551},[4133],{"type":420,"value":4134},"=.",{"type":415,"tag":532,"props":4136,"children":4137},{"style":551},[4138],{"type":420,"value":4139}," --",{"type":415,"tag":532,"props":4141,"children":4142},{"style":545},[4143],{"type":420,"value":4144},"push\n",{"type":415,"tag":434,"props":4146,"children":4147},{"icon":436},[4148],{"type":415,"tag":416,"props":4149,"children":4150},{},[4151,4153,4159,4161,4167],{"type":420,"value":4152},"You can use the ",{"type":415,"tag":468,"props":4154,"children":4156},{"className":4155},[],[4157],{"type":420,"value":4158},"--public",{"type":420,"value":4160}," flag instead of the ",{"type":415,"tag":468,"props":4162,"children":4164},{"className":4163},[],[4165],{"type":420,"value":4166},"--private",{"type":420,"value":4168}," one if you want your GitHub repository to be public.",{"type":415,"tag":416,"props":4170,"children":4171},{},[4172],{"type":420,"value":4173},"The repository's full name (containing the organization name) can be retrieved like this:",{"type":415,"tag":523,"props":4175,"children":4177},{"className":4059,"code":4176,"language":248,"meta":401,"style":401},"$repositoryFullName=$(gh repo view --json nameWithOwner -q \".nameWithOwner\")\n",[4178],{"type":415,"tag":468,"props":4179,"children":4180},{"__ignoreMap":401},[4181],{"type":415,"tag":532,"props":4182,"children":4183},{"class":534,"line":535},[4184,4188,4193,4198,4203,4207,4212,4217,4222,4226,4231,4235],{"type":415,"tag":532,"props":4185,"children":4186},{"style":551},[4187],{"type":420,"value":4072},{"type":415,"tag":532,"props":4189,"children":4190},{"style":545},[4191],{"type":420,"value":4192},"repositoryFullName",{"type":415,"tag":532,"props":4194,"children":4195},{"style":551},[4196],{"type":420,"value":4197},"=$(",{"type":415,"tag":532,"props":4199,"children":4200},{"style":545},[4201],{"type":420,"value":4202},"gh repo view ",{"type":415,"tag":532,"props":4204,"children":4205},{"style":551},[4206],{"type":420,"value":4115},{"type":415,"tag":532,"props":4208,"children":4209},{"style":545},[4210],{"type":420,"value":4211},"json nameWithOwner ",{"type":415,"tag":532,"props":4213,"children":4214},{"style":551},[4215],{"type":420,"value":4216},"-",{"type":415,"tag":532,"props":4218,"children":4219},{"style":545},[4220],{"type":420,"value":4221},"q ",{"type":415,"tag":532,"props":4223,"children":4224},{"style":551},[4225],{"type":420,"value":801},{"type":415,"tag":532,"props":4227,"children":4228},{"style":804},[4229],{"type":420,"value":4230},".nameWithOwner",{"type":415,"tag":532,"props":4232,"children":4233},{"style":551},[4234],{"type":420,"value":801},{"type":415,"tag":532,"props":4236,"children":4237},{"style":551},[4238],{"type":420,"value":1113},{"type":415,"tag":434,"props":4240,"children":4241},{"icon":436},[4242],{"type":415,"tag":416,"props":4243,"children":4244},{},[4245,4247,4253,4255,4261,4263],{"type":420,"value":4246},"Passing the ",{"type":415,"tag":468,"props":4248,"children":4250},{"className":4249},[],[4251],{"type":420,"value":4252},"--json",{"type":420,"value":4254}," flag converts the output format to JSON which, combined with the ",{"type":415,"tag":468,"props":4256,"children":4258},{"className":4257},[],[4259],{"type":420,"value":4260},"--q",{"type":420,"value":4262}," flag can be handy for filtering or formatting a command output. More on that ",{"type":415,"tag":423,"props":4264,"children":4267},{"href":4265,"rel":4266},"https://cli.github.com/manual/gh_help_formatting",[427],[4268],{"type":420,"value":4269},"in the documentation",{"type":415,"tag":3914,"props":4271,"children":4273},{"id":4272},"create-the-microsoft-entra-id-resources",[4274],{"type":420,"value":4275},"Create the Microsoft Entra ID resources",{"type":415,"tag":416,"props":4277,"children":4278},{},[4279],{"type":420,"value":4280},"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":415,"tag":523,"props":4282,"children":4284},{"className":4059,"code":4283,"language":248,"meta":401,"style":401},"$subscriptionId=$(az account show --query \"id\" -o tsv)\n$tenantId=$(az account show --query \"tenantId\" -o tsv)\n",[4285],{"type":415,"tag":468,"props":4286,"children":4287},{"__ignoreMap":401},[4288,4345],{"type":415,"tag":532,"props":4289,"children":4290},{"class":534,"line":535},[4291,4295,4300,4304,4309,4313,4318,4322,4327,4331,4336,4341],{"type":415,"tag":532,"props":4292,"children":4293},{"style":551},[4294],{"type":420,"value":4072},{"type":415,"tag":532,"props":4296,"children":4297},{"style":545},[4298],{"type":420,"value":4299},"subscriptionId",{"type":415,"tag":532,"props":4301,"children":4302},{"style":551},[4303],{"type":420,"value":4197},{"type":415,"tag":532,"props":4305,"children":4306},{"style":545},[4307],{"type":420,"value":4308},"az account show ",{"type":415,"tag":532,"props":4310,"children":4311},{"style":551},[4312],{"type":420,"value":4115},{"type":415,"tag":532,"props":4314,"children":4315},{"style":545},[4316],{"type":420,"value":4317},"query ",{"type":415,"tag":532,"props":4319,"children":4320},{"style":551},[4321],{"type":420,"value":801},{"type":415,"tag":532,"props":4323,"children":4324},{"style":804},[4325],{"type":420,"value":4326},"id",{"type":415,"tag":532,"props":4328,"children":4329},{"style":551},[4330],{"type":420,"value":801},{"type":415,"tag":532,"props":4332,"children":4333},{"style":551},[4334],{"type":420,"value":4335}," -",{"type":415,"tag":532,"props":4337,"children":4338},{"style":545},[4339],{"type":420,"value":4340},"o tsv",{"type":415,"tag":532,"props":4342,"children":4343},{"style":551},[4344],{"type":420,"value":1113},{"type":415,"tag":532,"props":4346,"children":4347},{"class":534,"line":566},[4348,4352,4357,4361,4365,4369,4373,4377,4381,4385,4389,4393],{"type":415,"tag":532,"props":4349,"children":4350},{"style":551},[4351],{"type":420,"value":4072},{"type":415,"tag":532,"props":4353,"children":4354},{"style":545},[4355],{"type":420,"value":4356},"tenantId",{"type":415,"tag":532,"props":4358,"children":4359},{"style":551},[4360],{"type":420,"value":4197},{"type":415,"tag":532,"props":4362,"children":4363},{"style":545},[4364],{"type":420,"value":4308},{"type":415,"tag":532,"props":4366,"children":4367},{"style":551},[4368],{"type":420,"value":4115},{"type":415,"tag":532,"props":4370,"children":4371},{"style":545},[4372],{"type":420,"value":4317},{"type":415,"tag":532,"props":4374,"children":4375},{"style":551},[4376],{"type":420,"value":801},{"type":415,"tag":532,"props":4378,"children":4379},{"style":804},[4380],{"type":420,"value":4356},{"type":415,"tag":532,"props":4382,"children":4383},{"style":551},[4384],{"type":420,"value":801},{"type":415,"tag":532,"props":4386,"children":4387},{"style":551},[4388],{"type":420,"value":4335},{"type":415,"tag":532,"props":4390,"children":4391},{"style":545},[4392],{"type":420,"value":4340},{"type":415,"tag":532,"props":4394,"children":4395},{"style":551},[4396],{"type":420,"value":1113},{"type":415,"tag":434,"props":4398,"children":4399},{"icon":1382},[4400],{"type":415,"tag":416,"props":4401,"children":4402},{},[4403,4405,4411,4413,4419,4421,4428],{"type":420,"value":4404},"Similar to the GitHub CLI, the Azure CLI has a ",{"type":415,"tag":468,"props":4406,"children":4408},{"className":4407},[],[4409],{"type":420,"value":4410},"--query",{"type":420,"value":4412}," flag to filter a command output. There are also different output formats. The ",{"type":415,"tag":468,"props":4414,"children":4416},{"className":4415},[],[4417],{"type":420,"value":4418},"tsv",{"type":420,"value":4420}," (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":415,"tag":423,"props":4422,"children":4425},{"href":4423,"rel":4424},"https://www.techwatching.dev/posts/welcome-azure-cli",[427],[4426],{"type":420,"value":4427},"here",{"type":420,"value":432},{"type":415,"tag":416,"props":4430,"children":4431},{},[4432],{"type":420,"value":4433},"To create the app registration and its associated service principal, we can execute the following commands:",{"type":415,"tag":523,"props":4435,"children":4437},{"className":4059,"code":4436,"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",[4438],{"type":415,"tag":468,"props":4439,"children":4440},{"__ignoreMap":401},[4441,4535],{"type":415,"tag":532,"props":4442,"children":4443},{"class":534,"line":535},[4444,4448,4453,4457,4462,4466,4471,4475,4480,4484,4489,4494,4498,4503,4507,4511,4515,4519,4523,4527,4531],{"type":415,"tag":532,"props":4445,"children":4446},{"style":551},[4447],{"type":420,"value":4072},{"type":415,"tag":532,"props":4449,"children":4450},{"style":545},[4451],{"type":420,"value":4452},"appId",{"type":415,"tag":532,"props":4454,"children":4455},{"style":551},[4456],{"type":420,"value":4197},{"type":415,"tag":532,"props":4458,"children":4459},{"style":545},[4460],{"type":420,"value":4461},"az ad app create ",{"type":415,"tag":532,"props":4463,"children":4464},{"style":551},[4465],{"type":420,"value":4115},{"type":415,"tag":532,"props":4467,"children":4468},{"style":545},[4469],{"type":420,"value":4470},"display",{"type":415,"tag":532,"props":4472,"children":4473},{"style":551},[4474],{"type":420,"value":4216},{"type":415,"tag":532,"props":4476,"children":4477},{"style":545},[4478],{"type":420,"value":4479},"name ",{"type":415,"tag":532,"props":4481,"children":4482},{"style":551},[4483],{"type":420,"value":801},{"type":415,"tag":532,"props":4485,"children":4486},{"style":804},[4487],{"type":420,"value":4488},"GitHub Action OIDC for ",{"type":415,"tag":532,"props":4490,"children":4491},{"style":551},[4492],{"type":420,"value":4493},"${",{"type":415,"tag":532,"props":4495,"children":4496},{"style":545},[4497],{"type":420,"value":4192},{"type":415,"tag":532,"props":4499,"children":4500},{"style":551},[4501],{"type":420,"value":4502},"}\"",{"type":415,"tag":532,"props":4504,"children":4505},{"style":551},[4506],{"type":420,"value":4139},{"type":415,"tag":532,"props":4508,"children":4509},{"style":545},[4510],{"type":420,"value":4317},{"type":415,"tag":532,"props":4512,"children":4513},{"style":551},[4514],{"type":420,"value":801},{"type":415,"tag":532,"props":4516,"children":4517},{"style":804},[4518],{"type":420,"value":4452},{"type":415,"tag":532,"props":4520,"children":4521},{"style":551},[4522],{"type":420,"value":801},{"type":415,"tag":532,"props":4524,"children":4525},{"style":551},[4526],{"type":420,"value":4335},{"type":415,"tag":532,"props":4528,"children":4529},{"style":545},[4530],{"type":420,"value":4340},{"type":415,"tag":532,"props":4532,"children":4533},{"style":551},[4534],{"type":420,"value":1113},{"type":415,"tag":532,"props":4536,"children":4537},{"class":534,"line":566},[4538,4542,4547,4551,4556,4560,4565,4569,4574,4578,4582,4586,4590,4594,4598,4602],{"type":415,"tag":532,"props":4539,"children":4540},{"style":551},[4541],{"type":420,"value":4072},{"type":415,"tag":532,"props":4543,"children":4544},{"style":545},[4545],{"type":420,"value":4546},"servicePrincipalId",{"type":415,"tag":532,"props":4548,"children":4549},{"style":551},[4550],{"type":420,"value":4197},{"type":415,"tag":532,"props":4552,"children":4553},{"style":545},[4554],{"type":420,"value":4555},"az ad sp create ",{"type":415,"tag":532,"props":4557,"children":4558},{"style":551},[4559],{"type":420,"value":4115},{"type":415,"tag":532,"props":4561,"children":4562},{"style":545},[4563],{"type":420,"value":4564},"id ",{"type":415,"tag":532,"props":4566,"children":4567},{"style":551},[4568],{"type":420,"value":4072},{"type":415,"tag":532,"props":4570,"children":4571},{"style":545},[4572],{"type":420,"value":4573},"appId ",{"type":415,"tag":532,"props":4575,"children":4576},{"style":551},[4577],{"type":420,"value":4115},{"type":415,"tag":532,"props":4579,"children":4580},{"style":545},[4581],{"type":420,"value":4317},{"type":415,"tag":532,"props":4583,"children":4584},{"style":551},[4585],{"type":420,"value":801},{"type":415,"tag":532,"props":4587,"children":4588},{"style":804},[4589],{"type":420,"value":4326},{"type":415,"tag":532,"props":4591,"children":4592},{"style":551},[4593],{"type":420,"value":801},{"type":415,"tag":532,"props":4595,"children":4596},{"style":551},[4597],{"type":420,"value":4335},{"type":415,"tag":532,"props":4599,"children":4600},{"style":545},[4601],{"type":420,"value":4340},{"type":415,"tag":532,"props":4603,"children":4604},{"style":551},[4605],{"type":420,"value":1113},{"type":415,"tag":416,"props":4607,"children":4608},{},[4609],{"type":420,"value":4610},"We can now assign the contributor role to the service principal on the subscription.",{"type":415,"tag":523,"props":4612,"children":4614},{"className":4059,"code":4613,"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",[4615],{"type":415,"tag":468,"props":4616,"children":4617},{"__ignoreMap":401},[4618],{"type":415,"tag":532,"props":4619,"children":4620},{"class":534,"line":535},[4621,4626,4630,4635,4639,4644,4648,4653,4657,4662,4666,4671,4675,4680,4684,4689,4693,4697,4701,4706,4710,4715,4719,4724,4729,4734,4739],{"type":415,"tag":532,"props":4622,"children":4623},{"style":545},[4624],{"type":420,"value":4625},"az role assignment create ",{"type":415,"tag":532,"props":4627,"children":4628},{"style":551},[4629],{"type":420,"value":4115},{"type":415,"tag":532,"props":4631,"children":4632},{"style":545},[4633],{"type":420,"value":4634},"role contributor ",{"type":415,"tag":532,"props":4636,"children":4637},{"style":551},[4638],{"type":420,"value":4115},{"type":415,"tag":532,"props":4640,"children":4641},{"style":545},[4642],{"type":420,"value":4643},"subscription ",{"type":415,"tag":532,"props":4645,"children":4646},{"style":551},[4647],{"type":420,"value":4072},{"type":415,"tag":532,"props":4649,"children":4650},{"style":545},[4651],{"type":420,"value":4652},"subscriptionId ",{"type":415,"tag":532,"props":4654,"children":4655},{"style":551},[4656],{"type":420,"value":4115},{"type":415,"tag":532,"props":4658,"children":4659},{"style":545},[4660],{"type":420,"value":4661},"assignee",{"type":415,"tag":532,"props":4663,"children":4664},{"style":551},[4665],{"type":420,"value":4216},{"type":415,"tag":532,"props":4667,"children":4668},{"style":545},[4669],{"type":420,"value":4670},"object",{"type":415,"tag":532,"props":4672,"children":4673},{"style":551},[4674],{"type":420,"value":4216},{"type":415,"tag":532,"props":4676,"children":4677},{"style":545},[4678],{"type":420,"value":4679},"id  ",{"type":415,"tag":532,"props":4681,"children":4682},{"style":551},[4683],{"type":420,"value":4072},{"type":415,"tag":532,"props":4685,"children":4686},{"style":545},[4687],{"type":420,"value":4688},"servicePrincipalId ",{"type":415,"tag":532,"props":4690,"children":4691},{"style":551},[4692],{"type":420,"value":4115},{"type":415,"tag":532,"props":4694,"children":4695},{"style":545},[4696],{"type":420,"value":4661},{"type":415,"tag":532,"props":4698,"children":4699},{"style":551},[4700],{"type":420,"value":4216},{"type":415,"tag":532,"props":4702,"children":4703},{"style":545},[4704],{"type":420,"value":4705},"principal",{"type":415,"tag":532,"props":4707,"children":4708},{"style":551},[4709],{"type":420,"value":4216},{"type":415,"tag":532,"props":4711,"children":4712},{"style":545},[4713],{"type":420,"value":4714},"type ServicePrincipal ",{"type":415,"tag":532,"props":4716,"children":4717},{"style":551},[4718],{"type":420,"value":4115},{"type":415,"tag":532,"props":4720,"children":4721},{"style":545},[4722],{"type":420,"value":4723},"scope ",{"type":415,"tag":532,"props":4725,"children":4726},{"style":551},[4727],{"type":420,"value":4728},"/",{"type":415,"tag":532,"props":4730,"children":4731},{"style":545},[4732],{"type":420,"value":4733},"subscriptions",{"type":415,"tag":532,"props":4735,"children":4736},{"style":551},[4737],{"type":420,"value":4738},"/$",{"type":415,"tag":532,"props":4740,"children":4741},{"style":545},[4742],{"type":420,"value":4743},"subscriptionId\n",{"type":415,"tag":416,"props":4745,"children":4746},{},[4747],{"type":420,"value":4748},"Creating federated credentials is a bit more complex as one of the arguments needs to be an in-line JSON string.",{"type":415,"tag":523,"props":4750,"children":4752},{"className":4059,"code":4751,"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",[4753],{"type":415,"tag":468,"props":4754,"children":4755},{"__ignoreMap":401},[4756,4781,4806,4831,4874,4908,4929,4946,4954],{"type":415,"tag":532,"props":4757,"children":4758},{"class":534,"line":535},[4759,4763,4768,4772,4777],{"type":415,"tag":532,"props":4760,"children":4761},{"style":551},[4762],{"type":420,"value":4072},{"type":415,"tag":532,"props":4764,"children":4765},{"style":545},[4766],{"type":420,"value":4767},"parametersJson ",{"type":415,"tag":532,"props":4769,"children":4770},{"style":551},[4771],{"type":420,"value":1134},{"type":415,"tag":532,"props":4773,"children":4774},{"style":539},[4775],{"type":420,"value":4776}," @",{"type":415,"tag":532,"props":4778,"children":4779},{"style":551},[4780],{"type":420,"value":764},{"type":415,"tag":532,"props":4782,"children":4783},{"class":534,"line":566},[4784,4789,4793,4797,4802],{"type":415,"tag":532,"props":4785,"children":4786},{"style":545},[4787],{"type":420,"value":4788},"    name ",{"type":415,"tag":532,"props":4790,"children":4791},{"style":551},[4792],{"type":420,"value":1134},{"type":415,"tag":532,"props":4794,"children":4795},{"style":551},[4796],{"type":420,"value":4041},{"type":415,"tag":532,"props":4798,"children":4799},{"style":804},[4800],{"type":420,"value":4801},"FederatedIdentityForWorkshop",{"type":415,"tag":532,"props":4803,"children":4804},{"style":551},[4805],{"type":420,"value":4051},{"type":415,"tag":532,"props":4807,"children":4808},{"class":534,"line":583},[4809,4814,4818,4822,4827],{"type":415,"tag":532,"props":4810,"children":4811},{"style":545},[4812],{"type":420,"value":4813},"    issuer ",{"type":415,"tag":532,"props":4815,"children":4816},{"style":551},[4817],{"type":420,"value":1134},{"type":415,"tag":532,"props":4819,"children":4820},{"style":551},[4821],{"type":420,"value":4041},{"type":415,"tag":532,"props":4823,"children":4824},{"style":804},[4825],{"type":420,"value":4826},"https://token.actions.githubusercontent.com",{"type":415,"tag":532,"props":4828,"children":4829},{"style":551},[4830],{"type":420,"value":4051},{"type":415,"tag":532,"props":4832,"children":4833},{"class":534,"line":617},[4834,4839,4843,4847,4852,4856,4860,4865,4870],{"type":415,"tag":532,"props":4835,"children":4836},{"style":545},[4837],{"type":420,"value":4838},"    subject ",{"type":415,"tag":532,"props":4840,"children":4841},{"style":551},[4842],{"type":420,"value":1134},{"type":415,"tag":532,"props":4844,"children":4845},{"style":551},[4846],{"type":420,"value":4041},{"type":415,"tag":532,"props":4848,"children":4849},{"style":804},[4850],{"type":420,"value":4851},"repo:",{"type":415,"tag":532,"props":4853,"children":4854},{"style":551},[4855],{"type":420,"value":4493},{"type":415,"tag":532,"props":4857,"children":4858},{"style":545},[4859],{"type":420,"value":4192},{"type":415,"tag":532,"props":4861,"children":4862},{"style":551},[4863],{"type":420,"value":4864},"}",{"type":415,"tag":532,"props":4866,"children":4867},{"style":804},[4868],{"type":420,"value":4869},":ref:refs/heads/main",{"type":415,"tag":532,"props":4871,"children":4872},{"style":551},[4873],{"type":420,"value":4051},{"type":415,"tag":532,"props":4875,"children":4876},{"class":534,"line":627},[4877,4882,4886,4890,4895,4899,4903],{"type":415,"tag":532,"props":4878,"children":4879},{"style":545},[4880],{"type":420,"value":4881},"    description ",{"type":415,"tag":532,"props":4883,"children":4884},{"style":551},[4885],{"type":420,"value":1134},{"type":415,"tag":532,"props":4887,"children":4888},{"style":551},[4889],{"type":420,"value":4041},{"type":415,"tag":532,"props":4891,"children":4892},{"style":804},[4893],{"type":420,"value":4894},"Deployments for ",{"type":415,"tag":532,"props":4896,"children":4897},{"style":551},[4898],{"type":420,"value":4493},{"type":415,"tag":532,"props":4900,"children":4901},{"style":545},[4902],{"type":420,"value":4192},{"type":415,"tag":532,"props":4904,"children":4905},{"style":551},[4906],{"type":420,"value":4907},"}\"\n",{"type":415,"tag":532,"props":4909,"children":4910},{"class":534,"line":677},[4911,4916,4920,4924],{"type":415,"tag":532,"props":4912,"children":4913},{"style":545},[4914],{"type":420,"value":4915},"    audiences ",{"type":415,"tag":532,"props":4917,"children":4918},{"style":551},[4919],{"type":420,"value":1134},{"type":415,"tag":532,"props":4921,"children":4922},{"style":539},[4923],{"type":420,"value":4776},{"type":415,"tag":532,"props":4925,"children":4926},{"style":551},[4927],{"type":420,"value":4928},"(\n",{"type":415,"tag":532,"props":4930,"children":4931},{"class":534,"line":719},[4932,4937,4942],{"type":415,"tag":532,"props":4933,"children":4934},{"style":551},[4935],{"type":420,"value":4936},"        \"",{"type":415,"tag":532,"props":4938,"children":4939},{"style":804},[4940],{"type":420,"value":4941},"api://AzureADTokenExchange",{"type":415,"tag":532,"props":4943,"children":4944},{"style":551},[4945],{"type":420,"value":4051},{"type":415,"tag":532,"props":4947,"children":4948},{"class":534,"line":758},[4949],{"type":415,"tag":532,"props":4950,"children":4951},{"style":551},[4952],{"type":420,"value":4953},"    )\n",{"type":415,"tag":532,"props":4955,"children":4956},{"class":534,"line":767},[4957],{"type":415,"tag":532,"props":4958,"children":4959},{"style":551},[4960],{"type":420,"value":1379},{"type":415,"tag":434,"props":4962,"children":4963},{"icon":436},[4964],{"type":415,"tag":416,"props":4965,"children":4966},{},[4967,4969,4975,4977,4983],{"type":420,"value":4968},"The ",{"type":415,"tag":468,"props":4970,"children":4972},{"className":4971},[],[4973],{"type":420,"value":4974},"subject",{"type":420,"value":4976}," 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":415,"tag":423,"props":4978,"children":4981},{"href":4979,"rel":4980},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims",[427],[4982],{"type":420,"value":499},{"type":420,"value":4984}," to learn more about these options.",{"type":415,"tag":416,"props":4986,"children":4987},{},[4988,4990,4997],{"type":420,"value":4989},"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":415,"tag":423,"props":4991,"children":4994},{"href":4992,"rel":4993},"https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b",[427],[4995],{"type":420,"value":4996},"blog article",{"type":420,"value":432},{"type":415,"tag":523,"props":4999,"children":5001},{"className":4059,"code":5000,"language":248,"meta":401,"style":401},"$parameters = $($parametersJson | ConvertTo-Json -Depth 100 -Compress).Replace(\"`\"\", \"\\`\"\")\n",[5002],{"type":415,"tag":468,"props":5003,"children":5004},{"__ignoreMap":401},[5005],{"type":415,"tag":532,"props":5006,"children":5007},{"class":534,"line":535},[5008,5012,5017,5021,5026,5030,5035,5040,5044,5049,5054,5058,5063,5067,5072,5076,5080,5085,5089,5093,5097,5102,5106,5110],{"type":415,"tag":532,"props":5009,"children":5010},{"style":551},[5011],{"type":420,"value":4072},{"type":415,"tag":532,"props":5013,"children":5014},{"style":545},[5015],{"type":420,"value":5016},"parameters ",{"type":415,"tag":532,"props":5018,"children":5019},{"style":551},[5020],{"type":420,"value":1134},{"type":415,"tag":532,"props":5022,"children":5023},{"style":551},[5024],{"type":420,"value":5025}," $($",{"type":415,"tag":532,"props":5027,"children":5028},{"style":545},[5029],{"type":420,"value":4767},{"type":415,"tag":532,"props":5031,"children":5032},{"style":551},[5033],{"type":420,"value":5034},"|",{"type":415,"tag":532,"props":5036,"children":5037},{"style":656},[5038],{"type":420,"value":5039}," ConvertTo-Json",{"type":415,"tag":532,"props":5041,"children":5042},{"style":551},[5043],{"type":420,"value":4335},{"type":415,"tag":532,"props":5045,"children":5046},{"style":545},[5047],{"type":420,"value":5048},"Depth ",{"type":415,"tag":532,"props":5050,"children":5051},{"style":539},[5052],{"type":420,"value":5053},"100",{"type":415,"tag":532,"props":5055,"children":5056},{"style":551},[5057],{"type":420,"value":4335},{"type":415,"tag":532,"props":5059,"children":5060},{"style":545},[5061],{"type":420,"value":5062},"Compress",{"type":415,"tag":532,"props":5064,"children":5065},{"style":551},[5066],{"type":420,"value":1349},{"type":415,"tag":532,"props":5068,"children":5069},{"style":545},[5070],{"type":420,"value":5071},".Replace",{"type":415,"tag":532,"props":5073,"children":5074},{"style":551},[5075],{"type":420,"value":664},{"type":415,"tag":532,"props":5077,"children":5078},{"style":551},[5079],{"type":420,"value":801},{"type":415,"tag":532,"props":5081,"children":5082},{"style":545},[5083],{"type":420,"value":5084},"`\"",{"type":415,"tag":532,"props":5086,"children":5087},{"style":551},[5088],{"type":420,"value":801},{"type":415,"tag":532,"props":5090,"children":5091},{"style":551},[5092],{"type":420,"value":1099},{"type":415,"tag":532,"props":5094,"children":5095},{"style":551},[5096],{"type":420,"value":4041},{"type":415,"tag":532,"props":5098,"children":5099},{"style":804},[5100],{"type":420,"value":5101},"\\",{"type":415,"tag":532,"props":5103,"children":5104},{"style":545},[5105],{"type":420,"value":5084},{"type":415,"tag":532,"props":5107,"children":5108},{"style":551},[5109],{"type":420,"value":801},{"type":415,"tag":532,"props":5111,"children":5112},{"style":551},[5113],{"type":420,"value":1113},{"type":415,"tag":416,"props":5115,"children":5116},{},[5117],{"type":420,"value":5118},"And finally, we can create the federated credentials.",{"type":415,"tag":523,"props":5120,"children":5122},{"className":4059,"code":5121,"language":248,"meta":401,"style":401},"az ad app federated-credential create --id $appId --parameters $parameters\n",[5123],{"type":415,"tag":468,"props":5124,"children":5125},{"__ignoreMap":401},[5126],{"type":415,"tag":532,"props":5127,"children":5128},{"class":534,"line":535},[5129,5134,5138,5143,5147,5151,5155,5159,5163,5167,5171],{"type":415,"tag":532,"props":5130,"children":5131},{"style":545},[5132],{"type":420,"value":5133},"az ad app federated",{"type":415,"tag":532,"props":5135,"children":5136},{"style":551},[5137],{"type":420,"value":4216},{"type":415,"tag":532,"props":5139,"children":5140},{"style":545},[5141],{"type":420,"value":5142},"credential create ",{"type":415,"tag":532,"props":5144,"children":5145},{"style":551},[5146],{"type":420,"value":4115},{"type":415,"tag":532,"props":5148,"children":5149},{"style":545},[5150],{"type":420,"value":4564},{"type":415,"tag":532,"props":5152,"children":5153},{"style":551},[5154],{"type":420,"value":4072},{"type":415,"tag":532,"props":5156,"children":5157},{"style":545},[5158],{"type":420,"value":4573},{"type":415,"tag":532,"props":5160,"children":5161},{"style":551},[5162],{"type":420,"value":4115},{"type":415,"tag":532,"props":5164,"children":5165},{"style":545},[5166],{"type":420,"value":5016},{"type":415,"tag":532,"props":5168,"children":5169},{"style":551},[5170],{"type":420,"value":4072},{"type":415,"tag":532,"props":5172,"children":5173},{"style":545},[5174],{"type":420,"value":5175},"parameters\n",{"type":415,"tag":3914,"props":5177,"children":5179},{"id":5178},"configure-the-github-actions-and-run-the-workflow",[5180],{"type":420,"value":5181},"Configure the GitHub Actions and run the workflow",{"type":415,"tag":416,"props":5183,"children":5184},{},[5185],{"type":420,"value":5186},"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":415,"tag":5188,"props":5189,"children":5190},"ol",{},[5191,5196,5201],{"type":415,"tag":512,"props":5192,"children":5193},{},[5194],{"type":420,"value":5195},"The identifier of the Azure tenant",{"type":415,"tag":512,"props":5197,"children":5198},{},[5199],{"type":420,"value":5200},"The identifier of the Azure subscription",{"type":415,"tag":512,"props":5202,"children":5203},{},[5204],{"type":420,"value":5205},"The application identifier of the app registration",{"type":415,"tag":523,"props":5207,"children":5209},{"className":4059,"code":5208,"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",[5210],{"type":415,"tag":468,"props":5211,"children":5212},{"__ignoreMap":401},[5213,5239,5263],{"type":415,"tag":532,"props":5214,"children":5215},{"class":534,"line":535},[5216,5221,5225,5230,5234],{"type":415,"tag":532,"props":5217,"children":5218},{"style":545},[5219],{"type":420,"value":5220},"gh secret set AZURE_TENANT_ID ",{"type":415,"tag":532,"props":5222,"children":5223},{"style":551},[5224],{"type":420,"value":4115},{"type":415,"tag":532,"props":5226,"children":5227},{"style":545},[5228],{"type":420,"value":5229},"body ",{"type":415,"tag":532,"props":5231,"children":5232},{"style":551},[5233],{"type":420,"value":4072},{"type":415,"tag":532,"props":5235,"children":5236},{"style":545},[5237],{"type":420,"value":5238},"tenantId\n",{"type":415,"tag":532,"props":5240,"children":5241},{"class":534,"line":566},[5242,5247,5251,5255,5259],{"type":415,"tag":532,"props":5243,"children":5244},{"style":545},[5245],{"type":420,"value":5246},"gh secret set AZURE_SUBSCRIPTION_ID ",{"type":415,"tag":532,"props":5248,"children":5249},{"style":551},[5250],{"type":420,"value":4115},{"type":415,"tag":532,"props":5252,"children":5253},{"style":545},[5254],{"type":420,"value":5229},{"type":415,"tag":532,"props":5256,"children":5257},{"style":551},[5258],{"type":420,"value":4072},{"type":415,"tag":532,"props":5260,"children":5261},{"style":545},[5262],{"type":420,"value":4743},{"type":415,"tag":532,"props":5264,"children":5265},{"class":534,"line":583},[5266,5271,5275,5279,5283],{"type":415,"tag":532,"props":5267,"children":5268},{"style":545},[5269],{"type":420,"value":5270},"gh secret set AZURE_CLIENT_ID ",{"type":415,"tag":532,"props":5272,"children":5273},{"style":551},[5274],{"type":420,"value":4115},{"type":415,"tag":532,"props":5276,"children":5277},{"style":545},[5278],{"type":420,"value":5229},{"type":415,"tag":532,"props":5280,"children":5281},{"style":551},[5282],{"type":420,"value":4072},{"type":415,"tag":532,"props":5284,"children":5285},{"style":545},[5286],{"type":420,"value":5287},"appId\n",{"type":415,"tag":416,"props":5289,"children":5290},{},[5291],{"type":420,"value":5292},"We can directly run the workflow from the GitHub CLI, and watch the run until it is completed.",{"type":415,"tag":523,"props":5294,"children":5296},{"className":4059,"code":5295,"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",[5297],{"type":415,"tag":468,"props":5298,"children":5299},{"__ignoreMap":401},[5300,5308,5381],{"type":415,"tag":532,"props":5301,"children":5302},{"class":534,"line":535},[5303],{"type":415,"tag":532,"props":5304,"children":5305},{"style":545},[5306],{"type":420,"value":5307},"gh workflow run main.yml\n",{"type":415,"tag":532,"props":5309,"children":5310},{"class":534,"line":566},[5311,5315,5320,5324,5329,5333,5338,5342,5347,5351,5356,5360,5364,5368,5373,5377],{"type":415,"tag":532,"props":5312,"children":5313},{"style":551},[5314],{"type":420,"value":4072},{"type":415,"tag":532,"props":5316,"children":5317},{"style":545},[5318],{"type":420,"value":5319},"runId",{"type":415,"tag":532,"props":5321,"children":5322},{"style":551},[5323],{"type":420,"value":4197},{"type":415,"tag":532,"props":5325,"children":5326},{"style":545},[5327],{"type":420,"value":5328},"gh run list ",{"type":415,"tag":532,"props":5330,"children":5331},{"style":551},[5332],{"type":420,"value":4115},{"type":415,"tag":532,"props":5334,"children":5335},{"style":545},[5336],{"type":420,"value":5337},"workflow",{"type":415,"tag":532,"props":5339,"children":5340},{"style":551},[5341],{"type":420,"value":1134},{"type":415,"tag":532,"props":5343,"children":5344},{"style":545},[5345],{"type":420,"value":5346},"main.yml ",{"type":415,"tag":532,"props":5348,"children":5349},{"style":551},[5350],{"type":420,"value":4115},{"type":415,"tag":532,"props":5352,"children":5353},{"style":545},[5354],{"type":420,"value":5355},"json databaseId ",{"type":415,"tag":532,"props":5357,"children":5358},{"style":551},[5359],{"type":420,"value":4216},{"type":415,"tag":532,"props":5361,"children":5362},{"style":545},[5363],{"type":420,"value":4221},{"type":415,"tag":532,"props":5365,"children":5366},{"style":551},[5367],{"type":420,"value":801},{"type":415,"tag":532,"props":5369,"children":5370},{"style":804},[5371],{"type":420,"value":5372},".[0].databaseId",{"type":415,"tag":532,"props":5374,"children":5375},{"style":551},[5376],{"type":420,"value":801},{"type":415,"tag":532,"props":5378,"children":5379},{"style":551},[5380],{"type":420,"value":1113},{"type":415,"tag":532,"props":5382,"children":5383},{"class":534,"line":583},[5384,5389,5393],{"type":415,"tag":532,"props":5385,"children":5386},{"style":545},[5387],{"type":420,"value":5388},"gh run watch ",{"type":415,"tag":532,"props":5390,"children":5391},{"style":551},[5392],{"type":420,"value":4072},{"type":415,"tag":532,"props":5394,"children":5395},{"style":545},[5396],{"type":420,"value":5397},"runId\n",{"type":415,"tag":416,"props":5399,"children":5400},{},[5401],{"type":415,"tag":3882,"props":5402,"children":5406},{"alt":5403,"className":5404,"src":5405},"Screenshot of the GitHub Actions workfow run",[3886,3887],"/posts/images/scripting_azurereadygithub_github_1.webp",[],{"type":415,"tag":482,"props":5408,"children":5410},{"id":5409},"full-script",[5411],{"type":420,"value":5412},"Full script",{"type":415,"tag":523,"props":5414,"children":5416},{"className":4059,"code":5415,"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",[5417],{"type":415,"tag":468,"props":5418,"children":5419},{"__ignoreMap":401},[5420,5429,5437,5445,5453,5482,5489,5497,5524,5567,5574,5582,5638,5645,5653,5704,5755,5762,5770,5857,5924,5931,5939,6051,6059,6068,6092,6116,6140,6180,6212,6232,6248,6256,6264,6272,6281,6290,6390,6398,6407,6455,6463,6472,6496,6520,6544,6552,6561,6569,6637,6653,6661,6670],{"type":415,"tag":532,"props":5421,"children":5422},{"class":534,"line":535},[5423],{"type":415,"tag":532,"props":5424,"children":5426},{"style":5425},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[5427],{"type":420,"value":5428},"# Initialize git repository with current code\n",{"type":415,"tag":532,"props":5430,"children":5431},{"class":534,"line":566},[5432],{"type":415,"tag":532,"props":5433,"children":5434},{"style":5425},[5435],{"type":420,"value":5436},"# You should have added the main.yml workflow file in the `.github\\workflows` directory \n",{"type":415,"tag":532,"props":5438,"children":5439},{"class":534,"line":583},[5440],{"type":415,"tag":532,"props":5441,"children":5442},{"style":545},[5443],{"type":420,"value":5444},"git init\n",{"type":415,"tag":532,"props":5446,"children":5447},{"class":534,"line":617},[5448],{"type":415,"tag":532,"props":5449,"children":5450},{"style":545},[5451],{"type":420,"value":5452},"git add .\n",{"type":415,"tag":532,"props":5454,"children":5455},{"class":534,"line":627},[5456,5461,5465,5470,5474,5478],{"type":415,"tag":532,"props":5457,"children":5458},{"style":545},[5459],{"type":420,"value":5460},"git commit ",{"type":415,"tag":532,"props":5462,"children":5463},{"style":551},[5464],{"type":420,"value":4216},{"type":415,"tag":532,"props":5466,"children":5467},{"style":545},[5468],{"type":420,"value":5469},"m ",{"type":415,"tag":532,"props":5471,"children":5472},{"style":551},[5473],{"type":420,"value":801},{"type":415,"tag":532,"props":5475,"children":5476},{"style":804},[5477],{"type":420,"value":4046},{"type":415,"tag":532,"props":5479,"children":5480},{"style":551},[5481],{"type":420,"value":4051},{"type":415,"tag":532,"props":5483,"children":5484},{"class":534,"line":677},[5485],{"type":415,"tag":532,"props":5486,"children":5487},{"emptyLinePlaceholder":621},[5488],{"type":420,"value":624},{"type":415,"tag":532,"props":5490,"children":5491},{"class":534,"line":719},[5492],{"type":415,"tag":532,"props":5493,"children":5494},{"style":5425},[5495],{"type":420,"value":5496},"# Create a new remote private GitHub repository\n",{"type":415,"tag":532,"props":5498,"children":5499},{"class":534,"line":758},[5500,5504,5508,5512,5516,5520],{"type":415,"tag":532,"props":5501,"children":5502},{"style":551},[5503],{"type":420,"value":4072},{"type":415,"tag":532,"props":5505,"children":5506},{"style":545},[5507],{"type":420,"value":4077},{"type":415,"tag":532,"props":5509,"children":5510},{"style":551},[5511],{"type":420,"value":1134},{"type":415,"tag":532,"props":5513,"children":5514},{"style":551},[5515],{"type":420,"value":4041},{"type":415,"tag":532,"props":5517,"children":5518},{"style":804},[5519],{"type":420,"value":4090},{"type":415,"tag":532,"props":5521,"children":5522},{"style":551},[5523],{"type":420,"value":4051},{"type":415,"tag":532,"props":5525,"children":5526},{"class":534,"line":767},[5527,5531,5535,5539,5543,5547,5551,5555,5559,5563],{"type":415,"tag":532,"props":5528,"children":5529},{"style":545},[5530],{"type":420,"value":4102},{"type":415,"tag":532,"props":5532,"children":5533},{"style":551},[5534],{"type":420,"value":4072},{"type":415,"tag":532,"props":5536,"children":5537},{"style":545},[5538],{"type":420,"value":4077},{"type":415,"tag":532,"props":5540,"children":5541},{"style":551},[5542],{"type":420,"value":4115},{"type":415,"tag":532,"props":5544,"children":5545},{"style":545},[5546],{"type":420,"value":4120},{"type":415,"tag":532,"props":5548,"children":5549},{"style":551},[5550],{"type":420,"value":4115},{"type":415,"tag":532,"props":5552,"children":5553},{"style":545},[5554],{"type":420,"value":4129},{"type":415,"tag":532,"props":5556,"children":5557},{"style":551},[5558],{"type":420,"value":4134},{"type":415,"tag":532,"props":5560,"children":5561},{"style":551},[5562],{"type":420,"value":4139},{"type":415,"tag":532,"props":5564,"children":5565},{"style":545},[5566],{"type":420,"value":4144},{"type":415,"tag":532,"props":5568,"children":5569},{"class":534,"line":819},[5570],{"type":415,"tag":532,"props":5571,"children":5572},{"emptyLinePlaceholder":621},[5573],{"type":420,"value":624},{"type":415,"tag":532,"props":5575,"children":5576},{"class":534,"line":850},[5577],{"type":415,"tag":532,"props":5578,"children":5579},{"style":5425},[5580],{"type":420,"value":5581},"# Retrieve the repository full name (org/repo)\n",{"type":415,"tag":532,"props":5583,"children":5584},{"class":534,"line":859},[5585,5589,5593,5597,5601,5605,5609,5613,5617,5621,5625,5629,5633],{"type":415,"tag":532,"props":5586,"children":5587},{"style":551},[5588],{"type":420,"value":4072},{"type":415,"tag":532,"props":5590,"children":5591},{"style":545},[5592],{"type":420,"value":4192},{"type":415,"tag":532,"props":5594,"children":5595},{"style":551},[5596],{"type":420,"value":4197},{"type":415,"tag":532,"props":5598,"children":5599},{"style":545},[5600],{"type":420,"value":4202},{"type":415,"tag":532,"props":5602,"children":5603},{"style":551},[5604],{"type":420,"value":4115},{"type":415,"tag":532,"props":5606,"children":5607},{"style":545},[5608],{"type":420,"value":4211},{"type":415,"tag":532,"props":5610,"children":5611},{"style":551},[5612],{"type":420,"value":4216},{"type":415,"tag":532,"props":5614,"children":5615},{"style":545},[5616],{"type":420,"value":4221},{"type":415,"tag":532,"props":5618,"children":5619},{"style":551},[5620],{"type":420,"value":801},{"type":415,"tag":532,"props":5622,"children":5623},{"style":804},[5624],{"type":420,"value":4230},{"type":415,"tag":532,"props":5626,"children":5627},{"style":551},[5628],{"type":420,"value":801},{"type":415,"tag":532,"props":5630,"children":5631},{"style":551},[5632],{"type":420,"value":1349},{"type":415,"tag":532,"props":5634,"children":5635},{"style":545},[5636],{"type":420,"value":5637}," \n",{"type":415,"tag":532,"props":5639,"children":5640},{"class":534,"line":867},[5641],{"type":415,"tag":532,"props":5642,"children":5643},{"emptyLinePlaceholder":621},[5644],{"type":420,"value":624},{"type":415,"tag":532,"props":5646,"children":5647},{"class":534,"line":902},[5648],{"type":415,"tag":532,"props":5649,"children":5650},{"style":5425},[5651],{"type":420,"value":5652},"# Retrieve the current subscription and current tenant identifiers \n",{"type":415,"tag":532,"props":5654,"children":5655},{"class":534,"line":1302},[5656,5660,5664,5668,5672,5676,5680,5684,5688,5692,5696,5700],{"type":415,"tag":532,"props":5657,"children":5658},{"style":551},[5659],{"type":420,"value":4072},{"type":415,"tag":532,"props":5661,"children":5662},{"style":545},[5663],{"type":420,"value":4299},{"type":415,"tag":532,"props":5665,"children":5666},{"style":551},[5667],{"type":420,"value":4197},{"type":415,"tag":532,"props":5669,"children":5670},{"style":545},[5671],{"type":420,"value":4308},{"type":415,"tag":532,"props":5673,"children":5674},{"style":551},[5675],{"type":420,"value":4115},{"type":415,"tag":532,"props":5677,"children":5678},{"style":545},[5679],{"type":420,"value":4317},{"type":415,"tag":532,"props":5681,"children":5682},{"style":551},[5683],{"type":420,"value":801},{"type":415,"tag":532,"props":5685,"children":5686},{"style":804},[5687],{"type":420,"value":4326},{"type":415,"tag":532,"props":5689,"children":5690},{"style":551},[5691],{"type":420,"value":801},{"type":415,"tag":532,"props":5693,"children":5694},{"style":551},[5695],{"type":420,"value":4335},{"type":415,"tag":532,"props":5697,"children":5698},{"style":545},[5699],{"type":420,"value":4340},{"type":415,"tag":532,"props":5701,"children":5702},{"style":551},[5703],{"type":420,"value":1113},{"type":415,"tag":532,"props":5705,"children":5706},{"class":534,"line":1311},[5707,5711,5715,5719,5723,5727,5731,5735,5739,5743,5747,5751],{"type":415,"tag":532,"props":5708,"children":5709},{"style":551},[5710],{"type":420,"value":4072},{"type":415,"tag":532,"props":5712,"children":5713},{"style":545},[5714],{"type":420,"value":4356},{"type":415,"tag":532,"props":5716,"children":5717},{"style":551},[5718],{"type":420,"value":4197},{"type":415,"tag":532,"props":5720,"children":5721},{"style":545},[5722],{"type":420,"value":4308},{"type":415,"tag":532,"props":5724,"children":5725},{"style":551},[5726],{"type":420,"value":4115},{"type":415,"tag":532,"props":5728,"children":5729},{"style":545},[5730],{"type":420,"value":4317},{"type":415,"tag":532,"props":5732,"children":5733},{"style":551},[5734],{"type":420,"value":801},{"type":415,"tag":532,"props":5736,"children":5737},{"style":804},[5738],{"type":420,"value":4356},{"type":415,"tag":532,"props":5740,"children":5741},{"style":551},[5742],{"type":420,"value":801},{"type":415,"tag":532,"props":5744,"children":5745},{"style":551},[5746],{"type":420,"value":4335},{"type":415,"tag":532,"props":5748,"children":5749},{"style":545},[5750],{"type":420,"value":4340},{"type":415,"tag":532,"props":5752,"children":5753},{"style":551},[5754],{"type":420,"value":1113},{"type":415,"tag":532,"props":5756,"children":5757},{"class":534,"line":1356},[5758],{"type":415,"tag":532,"props":5759,"children":5760},{"emptyLinePlaceholder":621},[5761],{"type":420,"value":624},{"type":415,"tag":532,"props":5763,"children":5764},{"class":534,"line":1365},[5765],{"type":415,"tag":532,"props":5766,"children":5767},{"style":5425},[5768],{"type":420,"value":5769},"# Create an App Registration and its associated service principal\n",{"type":415,"tag":532,"props":5771,"children":5772},{"class":534,"line":1373},[5773,5777,5781,5785,5789,5793,5797,5801,5805,5809,5813,5817,5821,5825,5829,5833,5837,5841,5845,5849,5853],{"type":415,"tag":532,"props":5774,"children":5775},{"style":551},[5776],{"type":420,"value":4072},{"type":415,"tag":532,"props":5778,"children":5779},{"style":545},[5780],{"type":420,"value":4452},{"type":415,"tag":532,"props":5782,"children":5783},{"style":551},[5784],{"type":420,"value":4197},{"type":415,"tag":532,"props":5786,"children":5787},{"style":545},[5788],{"type":420,"value":4461},{"type":415,"tag":532,"props":5790,"children":5791},{"style":551},[5792],{"type":420,"value":4115},{"type":415,"tag":532,"props":5794,"children":5795},{"style":545},[5796],{"type":420,"value":4470},{"type":415,"tag":532,"props":5798,"children":5799},{"style":551},[5800],{"type":420,"value":4216},{"type":415,"tag":532,"props":5802,"children":5803},{"style":545},[5804],{"type":420,"value":4479},{"type":415,"tag":532,"props":5806,"children":5807},{"style":551},[5808],{"type":420,"value":801},{"type":415,"tag":532,"props":5810,"children":5811},{"style":804},[5812],{"type":420,"value":4488},{"type":415,"tag":532,"props":5814,"children":5815},{"style":551},[5816],{"type":420,"value":4493},{"type":415,"tag":532,"props":5818,"children":5819},{"style":545},[5820],{"type":420,"value":4192},{"type":415,"tag":532,"props":5822,"children":5823},{"style":551},[5824],{"type":420,"value":4502},{"type":415,"tag":532,"props":5826,"children":5827},{"style":551},[5828],{"type":420,"value":4139},{"type":415,"tag":532,"props":5830,"children":5831},{"style":545},[5832],{"type":420,"value":4317},{"type":415,"tag":532,"props":5834,"children":5835},{"style":551},[5836],{"type":420,"value":801},{"type":415,"tag":532,"props":5838,"children":5839},{"style":804},[5840],{"type":420,"value":4452},{"type":415,"tag":532,"props":5842,"children":5843},{"style":551},[5844],{"type":420,"value":801},{"type":415,"tag":532,"props":5846,"children":5847},{"style":551},[5848],{"type":420,"value":4335},{"type":415,"tag":532,"props":5850,"children":5851},{"style":545},[5852],{"type":420,"value":4340},{"type":415,"tag":532,"props":5854,"children":5855},{"style":551},[5856],{"type":420,"value":1113},{"type":415,"tag":532,"props":5858,"children":5859},{"class":534,"line":3825},[5860,5864,5868,5872,5876,5880,5884,5888,5892,5896,5900,5904,5908,5912,5916,5920],{"type":415,"tag":532,"props":5861,"children":5862},{"style":551},[5863],{"type":420,"value":4072},{"type":415,"tag":532,"props":5865,"children":5866},{"style":545},[5867],{"type":420,"value":4546},{"type":415,"tag":532,"props":5869,"children":5870},{"style":551},[5871],{"type":420,"value":4197},{"type":415,"tag":532,"props":5873,"children":5874},{"style":545},[5875],{"type":420,"value":4555},{"type":415,"tag":532,"props":5877,"children":5878},{"style":551},[5879],{"type":420,"value":4115},{"type":415,"tag":532,"props":5881,"children":5882},{"style":545},[5883],{"type":420,"value":4564},{"type":415,"tag":532,"props":5885,"children":5886},{"style":551},[5887],{"type":420,"value":4072},{"type":415,"tag":532,"props":5889,"children":5890},{"style":545},[5891],{"type":420,"value":4573},{"type":415,"tag":532,"props":5893,"children":5894},{"style":551},[5895],{"type":420,"value":4115},{"type":415,"tag":532,"props":5897,"children":5898},{"style":545},[5899],{"type":420,"value":4317},{"type":415,"tag":532,"props":5901,"children":5902},{"style":551},[5903],{"type":420,"value":801},{"type":415,"tag":532,"props":5905,"children":5906},{"style":804},[5907],{"type":420,"value":4326},{"type":415,"tag":532,"props":5909,"children":5910},{"style":551},[5911],{"type":420,"value":801},{"type":415,"tag":532,"props":5913,"children":5914},{"style":551},[5915],{"type":420,"value":4335},{"type":415,"tag":532,"props":5917,"children":5918},{"style":545},[5919],{"type":420,"value":4340},{"type":415,"tag":532,"props":5921,"children":5922},{"style":551},[5923],{"type":420,"value":1113},{"type":415,"tag":532,"props":5925,"children":5926},{"class":534,"line":3843},[5927],{"type":415,"tag":532,"props":5928,"children":5929},{"emptyLinePlaceholder":621},[5930],{"type":420,"value":624},{"type":415,"tag":532,"props":5932,"children":5933},{"class":534,"line":3852},[5934],{"type":415,"tag":532,"props":5935,"children":5936},{"style":5425},[5937],{"type":420,"value":5938},"# Assign the contributor role to the service principal on the subscription\n",{"type":415,"tag":532,"props":5940,"children":5942},{"class":534,"line":5941},23,[5943,5947,5951,5955,5959,5963,5967,5971,5975,5979,5983,5987,5991,5995,5999,6003,6007,6011,6015,6019,6023,6027,6031,6035,6039,6043,6047],{"type":415,"tag":532,"props":5944,"children":5945},{"style":545},[5946],{"type":420,"value":4625},{"type":415,"tag":532,"props":5948,"children":5949},{"style":551},[5950],{"type":420,"value":4115},{"type":415,"tag":532,"props":5952,"children":5953},{"style":545},[5954],{"type":420,"value":4634},{"type":415,"tag":532,"props":5956,"children":5957},{"style":551},[5958],{"type":420,"value":4115},{"type":415,"tag":532,"props":5960,"children":5961},{"style":545},[5962],{"type":420,"value":4643},{"type":415,"tag":532,"props":5964,"children":5965},{"style":551},[5966],{"type":420,"value":4072},{"type":415,"tag":532,"props":5968,"children":5969},{"style":545},[5970],{"type":420,"value":4652},{"type":415,"tag":532,"props":5972,"children":5973},{"style":551},[5974],{"type":420,"value":4115},{"type":415,"tag":532,"props":5976,"children":5977},{"style":545},[5978],{"type":420,"value":4661},{"type":415,"tag":532,"props":5980,"children":5981},{"style":551},[5982],{"type":420,"value":4216},{"type":415,"tag":532,"props":5984,"children":5985},{"style":545},[5986],{"type":420,"value":4670},{"type":415,"tag":532,"props":5988,"children":5989},{"style":551},[5990],{"type":420,"value":4216},{"type":415,"tag":532,"props":5992,"children":5993},{"style":545},[5994],{"type":420,"value":4679},{"type":415,"tag":532,"props":5996,"children":5997},{"style":551},[5998],{"type":420,"value":4072},{"type":415,"tag":532,"props":6000,"children":6001},{"style":545},[6002],{"type":420,"value":4688},{"type":415,"tag":532,"props":6004,"children":6005},{"style":551},[6006],{"type":420,"value":4115},{"type":415,"tag":532,"props":6008,"children":6009},{"style":545},[6010],{"type":420,"value":4661},{"type":415,"tag":532,"props":6012,"children":6013},{"style":551},[6014],{"type":420,"value":4216},{"type":415,"tag":532,"props":6016,"children":6017},{"style":545},[6018],{"type":420,"value":4705},{"type":415,"tag":532,"props":6020,"children":6021},{"style":551},[6022],{"type":420,"value":4216},{"type":415,"tag":532,"props":6024,"children":6025},{"style":545},[6026],{"type":420,"value":4714},{"type":415,"tag":532,"props":6028,"children":6029},{"style":551},[6030],{"type":420,"value":4115},{"type":415,"tag":532,"props":6032,"children":6033},{"style":545},[6034],{"type":420,"value":4723},{"type":415,"tag":532,"props":6036,"children":6037},{"style":551},[6038],{"type":420,"value":4728},{"type":415,"tag":532,"props":6040,"children":6041},{"style":545},[6042],{"type":420,"value":4733},{"type":415,"tag":532,"props":6044,"children":6045},{"style":551},[6046],{"type":420,"value":4738},{"type":415,"tag":532,"props":6048,"children":6049},{"style":545},[6050],{"type":420,"value":4743},{"type":415,"tag":532,"props":6052,"children":6054},{"class":534,"line":6053},24,[6055],{"type":415,"tag":532,"props":6056,"children":6057},{"emptyLinePlaceholder":621},[6058],{"type":420,"value":624},{"type":415,"tag":532,"props":6060,"children":6062},{"class":534,"line":6061},25,[6063],{"type":415,"tag":532,"props":6064,"children":6065},{"style":5425},[6066],{"type":420,"value":6067},"# Prepare parameters for federated credentials\n",{"type":415,"tag":532,"props":6069,"children":6071},{"class":534,"line":6070},26,[6072,6076,6080,6084,6088],{"type":415,"tag":532,"props":6073,"children":6074},{"style":551},[6075],{"type":420,"value":4072},{"type":415,"tag":532,"props":6077,"children":6078},{"style":545},[6079],{"type":420,"value":4767},{"type":415,"tag":532,"props":6081,"children":6082},{"style":551},[6083],{"type":420,"value":1134},{"type":415,"tag":532,"props":6085,"children":6086},{"style":539},[6087],{"type":420,"value":4776},{"type":415,"tag":532,"props":6089,"children":6090},{"style":551},[6091],{"type":420,"value":764},{"type":415,"tag":532,"props":6093,"children":6095},{"class":534,"line":6094},27,[6096,6100,6104,6108,6112],{"type":415,"tag":532,"props":6097,"children":6098},{"style":545},[6099],{"type":420,"value":4788},{"type":415,"tag":532,"props":6101,"children":6102},{"style":551},[6103],{"type":420,"value":1134},{"type":415,"tag":532,"props":6105,"children":6106},{"style":551},[6107],{"type":420,"value":4041},{"type":415,"tag":532,"props":6109,"children":6110},{"style":804},[6111],{"type":420,"value":4801},{"type":415,"tag":532,"props":6113,"children":6114},{"style":551},[6115],{"type":420,"value":4051},{"type":415,"tag":532,"props":6117,"children":6119},{"class":534,"line":6118},28,[6120,6124,6128,6132,6136],{"type":415,"tag":532,"props":6121,"children":6122},{"style":545},[6123],{"type":420,"value":4813},{"type":415,"tag":532,"props":6125,"children":6126},{"style":551},[6127],{"type":420,"value":1134},{"type":415,"tag":532,"props":6129,"children":6130},{"style":551},[6131],{"type":420,"value":4041},{"type":415,"tag":532,"props":6133,"children":6134},{"style":804},[6135],{"type":420,"value":4826},{"type":415,"tag":532,"props":6137,"children":6138},{"style":551},[6139],{"type":420,"value":4051},{"type":415,"tag":532,"props":6141,"children":6143},{"class":534,"line":6142},29,[6144,6148,6152,6156,6160,6164,6168,6172,6176],{"type":415,"tag":532,"props":6145,"children":6146},{"style":545},[6147],{"type":420,"value":4838},{"type":415,"tag":532,"props":6149,"children":6150},{"style":551},[6151],{"type":420,"value":1134},{"type":415,"tag":532,"props":6153,"children":6154},{"style":551},[6155],{"type":420,"value":4041},{"type":415,"tag":532,"props":6157,"children":6158},{"style":804},[6159],{"type":420,"value":4851},{"type":415,"tag":532,"props":6161,"children":6162},{"style":551},[6163],{"type":420,"value":4493},{"type":415,"tag":532,"props":6165,"children":6166},{"style":545},[6167],{"type":420,"value":4192},{"type":415,"tag":532,"props":6169,"children":6170},{"style":551},[6171],{"type":420,"value":4864},{"type":415,"tag":532,"props":6173,"children":6174},{"style":804},[6175],{"type":420,"value":4869},{"type":415,"tag":532,"props":6177,"children":6178},{"style":551},[6179],{"type":420,"value":4051},{"type":415,"tag":532,"props":6181,"children":6183},{"class":534,"line":6182},30,[6184,6188,6192,6196,6200,6204,6208],{"type":415,"tag":532,"props":6185,"children":6186},{"style":545},[6187],{"type":420,"value":4881},{"type":415,"tag":532,"props":6189,"children":6190},{"style":551},[6191],{"type":420,"value":1134},{"type":415,"tag":532,"props":6193,"children":6194},{"style":551},[6195],{"type":420,"value":4041},{"type":415,"tag":532,"props":6197,"children":6198},{"style":804},[6199],{"type":420,"value":4894},{"type":415,"tag":532,"props":6201,"children":6202},{"style":551},[6203],{"type":420,"value":4493},{"type":415,"tag":532,"props":6205,"children":6206},{"style":545},[6207],{"type":420,"value":4192},{"type":415,"tag":532,"props":6209,"children":6210},{"style":551},[6211],{"type":420,"value":4907},{"type":415,"tag":532,"props":6213,"children":6215},{"class":534,"line":6214},31,[6216,6220,6224,6228],{"type":415,"tag":532,"props":6217,"children":6218},{"style":545},[6219],{"type":420,"value":4915},{"type":415,"tag":532,"props":6221,"children":6222},{"style":551},[6223],{"type":420,"value":1134},{"type":415,"tag":532,"props":6225,"children":6226},{"style":539},[6227],{"type":420,"value":4776},{"type":415,"tag":532,"props":6229,"children":6230},{"style":551},[6231],{"type":420,"value":4928},{"type":415,"tag":532,"props":6233,"children":6235},{"class":534,"line":6234},32,[6236,6240,6244],{"type":415,"tag":532,"props":6237,"children":6238},{"style":551},[6239],{"type":420,"value":4936},{"type":415,"tag":532,"props":6241,"children":6242},{"style":804},[6243],{"type":420,"value":4941},{"type":415,"tag":532,"props":6245,"children":6246},{"style":551},[6247],{"type":420,"value":4051},{"type":415,"tag":532,"props":6249,"children":6251},{"class":534,"line":6250},33,[6252],{"type":415,"tag":532,"props":6253,"children":6254},{"style":551},[6255],{"type":420,"value":4953},{"type":415,"tag":532,"props":6257,"children":6259},{"class":534,"line":6258},34,[6260],{"type":415,"tag":532,"props":6261,"children":6262},{"style":551},[6263],{"type":420,"value":1379},{"type":415,"tag":532,"props":6265,"children":6267},{"class":534,"line":6266},35,[6268],{"type":415,"tag":532,"props":6269,"children":6270},{"emptyLinePlaceholder":621},[6271],{"type":420,"value":624},{"type":415,"tag":532,"props":6273,"children":6275},{"class":534,"line":6274},36,[6276],{"type":415,"tag":532,"props":6277,"children":6278},{"style":5425},[6279],{"type":420,"value":6280},"# Change parameters to single line string with escaped quotes to make it work with Azure CLI\n",{"type":415,"tag":532,"props":6282,"children":6284},{"class":534,"line":6283},37,[6285],{"type":415,"tag":532,"props":6286,"children":6287},{"style":5425},[6288],{"type":420,"value":6289},"# https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b\n",{"type":415,"tag":532,"props":6291,"children":6293},{"class":534,"line":6292},38,[6294,6298,6302,6306,6310,6314,6318,6322,6326,6330,6334,6338,6342,6346,6350,6354,6358,6362,6366,6370,6374,6378,6382,6386],{"type":415,"tag":532,"props":6295,"children":6296},{"style":551},[6297],{"type":420,"value":4072},{"type":415,"tag":532,"props":6299,"children":6300},{"style":545},[6301],{"type":420,"value":5016},{"type":415,"tag":532,"props":6303,"children":6304},{"style":551},[6305],{"type":420,"value":1134},{"type":415,"tag":532,"props":6307,"children":6308},{"style":551},[6309],{"type":420,"value":5025},{"type":415,"tag":532,"props":6311,"children":6312},{"style":545},[6313],{"type":420,"value":4767},{"type":415,"tag":532,"props":6315,"children":6316},{"style":551},[6317],{"type":420,"value":5034},{"type":415,"tag":532,"props":6319,"children":6320},{"style":656},[6321],{"type":420,"value":5039},{"type":415,"tag":532,"props":6323,"children":6324},{"style":551},[6325],{"type":420,"value":4335},{"type":415,"tag":532,"props":6327,"children":6328},{"style":545},[6329],{"type":420,"value":5048},{"type":415,"tag":532,"props":6331,"children":6332},{"style":539},[6333],{"type":420,"value":5053},{"type":415,"tag":532,"props":6335,"children":6336},{"style":551},[6337],{"type":420,"value":4335},{"type":415,"tag":532,"props":6339,"children":6340},{"style":545},[6341],{"type":420,"value":5062},{"type":415,"tag":532,"props":6343,"children":6344},{"style":551},[6345],{"type":420,"value":1349},{"type":415,"tag":532,"props":6347,"children":6348},{"style":545},[6349],{"type":420,"value":5071},{"type":415,"tag":532,"props":6351,"children":6352},{"style":551},[6353],{"type":420,"value":664},{"type":415,"tag":532,"props":6355,"children":6356},{"style":551},[6357],{"type":420,"value":801},{"type":415,"tag":532,"props":6359,"children":6360},{"style":545},[6361],{"type":420,"value":5084},{"type":415,"tag":532,"props":6363,"children":6364},{"style":551},[6365],{"type":420,"value":801},{"type":415,"tag":532,"props":6367,"children":6368},{"style":551},[6369],{"type":420,"value":1099},{"type":415,"tag":532,"props":6371,"children":6372},{"style":551},[6373],{"type":420,"value":4041},{"type":415,"tag":532,"props":6375,"children":6376},{"style":804},[6377],{"type":420,"value":5101},{"type":415,"tag":532,"props":6379,"children":6380},{"style":545},[6381],{"type":420,"value":5084},{"type":415,"tag":532,"props":6383,"children":6384},{"style":551},[6385],{"type":420,"value":801},{"type":415,"tag":532,"props":6387,"children":6388},{"style":551},[6389],{"type":420,"value":1113},{"type":415,"tag":532,"props":6391,"children":6393},{"class":534,"line":6392},39,[6394],{"type":415,"tag":532,"props":6395,"children":6396},{"emptyLinePlaceholder":621},[6397],{"type":420,"value":624},{"type":415,"tag":532,"props":6399,"children":6401},{"class":534,"line":6400},40,[6402],{"type":415,"tag":532,"props":6403,"children":6404},{"style":5425},[6405],{"type":420,"value":6406},"# Create federated credentials\n",{"type":415,"tag":532,"props":6408,"children":6410},{"class":534,"line":6409},41,[6411,6415,6419,6423,6427,6431,6435,6439,6443,6447,6451],{"type":415,"tag":532,"props":6412,"children":6413},{"style":545},[6414],{"type":420,"value":5133},{"type":415,"tag":532,"props":6416,"children":6417},{"style":551},[6418],{"type":420,"value":4216},{"type":415,"tag":532,"props":6420,"children":6421},{"style":545},[6422],{"type":420,"value":5142},{"type":415,"tag":532,"props":6424,"children":6425},{"style":551},[6426],{"type":420,"value":4115},{"type":415,"tag":532,"props":6428,"children":6429},{"style":545},[6430],{"type":420,"value":4564},{"type":415,"tag":532,"props":6432,"children":6433},{"style":551},[6434],{"type":420,"value":4072},{"type":415,"tag":532,"props":6436,"children":6437},{"style":545},[6438],{"type":420,"value":4573},{"type":415,"tag":532,"props":6440,"children":6441},{"style":551},[6442],{"type":420,"value":4115},{"type":415,"tag":532,"props":6444,"children":6445},{"style":545},[6446],{"type":420,"value":5016},{"type":415,"tag":532,"props":6448,"children":6449},{"style":551},[6450],{"type":420,"value":4072},{"type":415,"tag":532,"props":6452,"children":6453},{"style":545},[6454],{"type":420,"value":5175},{"type":415,"tag":532,"props":6456,"children":6458},{"class":534,"line":6457},42,[6459],{"type":415,"tag":532,"props":6460,"children":6461},{"emptyLinePlaceholder":621},[6462],{"type":420,"value":624},{"type":415,"tag":532,"props":6464,"children":6466},{"class":534,"line":6465},43,[6467],{"type":415,"tag":532,"props":6468,"children":6469},{"style":5425},[6470],{"type":420,"value":6471},"# Create GitHub secrets needed for the GitHub Actions\n",{"type":415,"tag":532,"props":6473,"children":6475},{"class":534,"line":6474},44,[6476,6480,6484,6488,6492],{"type":415,"tag":532,"props":6477,"children":6478},{"style":545},[6479],{"type":420,"value":5220},{"type":415,"tag":532,"props":6481,"children":6482},{"style":551},[6483],{"type":420,"value":4115},{"type":415,"tag":532,"props":6485,"children":6486},{"style":545},[6487],{"type":420,"value":5229},{"type":415,"tag":532,"props":6489,"children":6490},{"style":551},[6491],{"type":420,"value":4072},{"type":415,"tag":532,"props":6493,"children":6494},{"style":545},[6495],{"type":420,"value":5238},{"type":415,"tag":532,"props":6497,"children":6499},{"class":534,"line":6498},45,[6500,6504,6508,6512,6516],{"type":415,"tag":532,"props":6501,"children":6502},{"style":545},[6503],{"type":420,"value":5246},{"type":415,"tag":532,"props":6505,"children":6506},{"style":551},[6507],{"type":420,"value":4115},{"type":415,"tag":532,"props":6509,"children":6510},{"style":545},[6511],{"type":420,"value":5229},{"type":415,"tag":532,"props":6513,"children":6514},{"style":551},[6515],{"type":420,"value":4072},{"type":415,"tag":532,"props":6517,"children":6518},{"style":545},[6519],{"type":420,"value":4743},{"type":415,"tag":532,"props":6521,"children":6523},{"class":534,"line":6522},46,[6524,6528,6532,6536,6540],{"type":415,"tag":532,"props":6525,"children":6526},{"style":545},[6527],{"type":420,"value":5270},{"type":415,"tag":532,"props":6529,"children":6530},{"style":551},[6531],{"type":420,"value":4115},{"type":415,"tag":532,"props":6533,"children":6534},{"style":545},[6535],{"type":420,"value":5229},{"type":415,"tag":532,"props":6537,"children":6538},{"style":551},[6539],{"type":420,"value":4072},{"type":415,"tag":532,"props":6541,"children":6542},{"style":545},[6543],{"type":420,"value":5287},{"type":415,"tag":532,"props":6545,"children":6547},{"class":534,"line":6546},47,[6548],{"type":415,"tag":532,"props":6549,"children":6550},{"emptyLinePlaceholder":621},[6551],{"type":420,"value":624},{"type":415,"tag":532,"props":6553,"children":6555},{"class":534,"line":6554},48,[6556],{"type":415,"tag":532,"props":6557,"children":6558},{"style":5425},[6559],{"type":420,"value":6560},"# Run workflow\n",{"type":415,"tag":532,"props":6562,"children":6564},{"class":534,"line":6563},49,[6565],{"type":415,"tag":532,"props":6566,"children":6567},{"style":545},[6568],{"type":420,"value":5307},{"type":415,"tag":532,"props":6570,"children":6572},{"class":534,"line":6571},50,[6573,6577,6581,6585,6589,6593,6597,6601,6605,6609,6613,6617,6621,6625,6629,6633],{"type":415,"tag":532,"props":6574,"children":6575},{"style":551},[6576],{"type":420,"value":4072},{"type":415,"tag":532,"props":6578,"children":6579},{"style":545},[6580],{"type":420,"value":5319},{"type":415,"tag":532,"props":6582,"children":6583},{"style":551},[6584],{"type":420,"value":4197},{"type":415,"tag":532,"props":6586,"children":6587},{"style":545},[6588],{"type":420,"value":5328},{"type":415,"tag":532,"props":6590,"children":6591},{"style":551},[6592],{"type":420,"value":4115},{"type":415,"tag":532,"props":6594,"children":6595},{"style":545},[6596],{"type":420,"value":5337},{"type":415,"tag":532,"props":6598,"children":6599},{"style":551},[6600],{"type":420,"value":1134},{"type":415,"tag":532,"props":6602,"children":6603},{"style":545},[6604],{"type":420,"value":5346},{"type":415,"tag":532,"props":6606,"children":6607},{"style":551},[6608],{"type":420,"value":4115},{"type":415,"tag":532,"props":6610,"children":6611},{"style":545},[6612],{"type":420,"value":5355},{"type":415,"tag":532,"props":6614,"children":6615},{"style":551},[6616],{"type":420,"value":4216},{"type":415,"tag":532,"props":6618,"children":6619},{"style":545},[6620],{"type":420,"value":4221},{"type":415,"tag":532,"props":6622,"children":6623},{"style":551},[6624],{"type":420,"value":801},{"type":415,"tag":532,"props":6626,"children":6627},{"style":804},[6628],{"type":420,"value":5372},{"type":415,"tag":532,"props":6630,"children":6631},{"style":551},[6632],{"type":420,"value":801},{"type":415,"tag":532,"props":6634,"children":6635},{"style":551},[6636],{"type":420,"value":1113},{"type":415,"tag":532,"props":6638,"children":6640},{"class":534,"line":6639},51,[6641,6645,6649],{"type":415,"tag":532,"props":6642,"children":6643},{"style":545},[6644],{"type":420,"value":5388},{"type":415,"tag":532,"props":6646,"children":6647},{"style":551},[6648],{"type":420,"value":4072},{"type":415,"tag":532,"props":6650,"children":6651},{"style":545},[6652],{"type":420,"value":5397},{"type":415,"tag":532,"props":6654,"children":6656},{"class":534,"line":6655},52,[6657],{"type":415,"tag":532,"props":6658,"children":6659},{"emptyLinePlaceholder":621},[6660],{"type":420,"value":624},{"type":415,"tag":532,"props":6662,"children":6664},{"class":534,"line":6663},53,[6665],{"type":415,"tag":532,"props":6666,"children":6667},{"style":5425},[6668],{"type":420,"value":6669},"# Open the repostory in the browser\n",{"type":415,"tag":532,"props":6671,"children":6673},{"class":534,"line":6672},54,[6674,6678,6682],{"type":415,"tag":532,"props":6675,"children":6676},{"style":545},[6677],{"type":420,"value":4202},{"type":415,"tag":532,"props":6679,"children":6680},{"style":551},[6681],{"type":420,"value":4216},{"type":415,"tag":532,"props":6683,"children":6684},{"style":545},[6685],{"type":420,"value":6686},"w\n",{"type":415,"tag":482,"props":6688,"children":6690},{"id":6689},"final-thoughts",[6691],{"type":420,"value":6692},"Final Thoughts",{"type":415,"tag":416,"props":6694,"children":6695},{},[6696,6698,6704],{"type":420,"value":6697},"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":415,"tag":423,"props":6699,"children":6701},{"href":3900,"rel":6700},[427],[6702],{"type":420,"value":6703},"same using Pulumi",{"type":420,"value":6705},", 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":415,"tag":416,"props":6707,"children":6708},{},[6709],{"type":420,"value":6710},"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":415,"tag":416,"props":6712,"children":6713},{},[6714,6716,6721,6723,6729],{"type":420,"value":6715},"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":415,"tag":468,"props":6717,"children":6719},{"className":6718},[],[6720],{"type":420,"value":4252},{"type":420,"value":6722}," and ",{"type":415,"tag":468,"props":6724,"children":6726},{"className":6725},[],[6727],{"type":420,"value":6728},"-q",{"type":420,"value":6730}," 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":415,"tag":416,"props":6732,"children":6733},{},[6734],{"type":420,"value":6735},"As for Azure CLI, I am still a big fan, although a bit disappointed to have struggled with the inline JSON string.",{"type":415,"tag":416,"props":6737,"children":6738},{},[6739],{"type":420,"value":6740},"Keep learning, keep sharing.",{"type":415,"tag":3470,"props":6742,"children":6743},{},[6744],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":6746},[6747,6748,6754,6755],{"id":3504,"depth":566,"text":3507},{"id":3909,"depth":566,"text":3912,"children":6749},[6750,6751,6752,6753],{"id":3916,"depth":583,"text":3919},{"id":3960,"depth":583,"text":3963},{"id":4272,"depth":583,"text":4275},{"id":5178,"depth":583,"text":5181},{"id":5409,"depth":566,"text":5412},{"id":6689,"depth":566,"text":6692},"content:1.posts:55.scripting-azure-ready-github-repository.md","1.posts/55.scripting-azure-ready-github-repository.md",{"_path":169,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":168,"description":6759,"lead":6760,"date":6761,"image":6762,"badge":6764,"tags":6765,"body":6766,"_type":3483,"_id":10954,"_source":3485,"_file":10955,"_extension":3487},"If you are deploying your application to Azure from Azure Pipelines, you might want to leverage the ability to do so without using secrets thanks to Workload identity federation. In this article, I will demonstrate how to automate the configuration of your Azure DevOps project, with everything pre-configured to securely deploy applications to Azure.","Azure DevOps Workload identity federation (OIDC) with Pulumi","2023-09-21T00:00:00.000Z",{"src":6763},"/images/azuredevopsoidc.webp",{"label":266},[228,233,307,374,312,315,376,239],{"type":412,"children":6767,"toc":10941},[6768,6772,6778,6792,6805,6810,6830,6839,6857,6869,6874,6887,6892,6897,6905,6914,6919,6924,6934,6940,6946,6951,7012,7024,7083,7088,7127,7132,7177,7183,7188,7227,7241,7277,7301,7306,7658,7663,7677,7787,7792,8058,8097,8103,8117,8405,8418,8573,8578,8600,8820,8826,8831,8849,8854,9329,9344,9349,9665,9678,9684,9689,9702,9935,9940,10195,10200,10471,10476,10661,10666,10829,10842,10873,10882,10887,10893,10906,10911,10916,10921,10937],{"type":415,"tag":416,"props":6769,"children":6770},{},[6771],{"type":420,"value":6759},{"type":415,"tag":482,"props":6773,"children":6775},{"id":6774},"why-should-you-use-workload-identity-federation-for-your-deployment-pipelines",[6776],{"type":420,"value":6777},"Why should you use Workload Identity Federation for your deployment pipelines?",{"type":415,"tag":416,"props":6779,"children":6780},{},[6781,6783,6790],{"type":420,"value":6782},"I already wrote about the ",{"type":415,"tag":423,"props":6784,"children":6787},{"href":6785,"rel":6786},"https://www.techwatching.dev/posts/azure-ready-github-repository#the-problem-with-secret-credentials",[427],[6788],{"type":420,"value":6789},"problem of secret credentials",{"type":420,"value":6791},", but let me remind you 2 reasons why I think you should always avoid using secrets in your deployment pipelines:",{"type":415,"tag":508,"props":6793,"children":6794},{},[6795,6800],{"type":415,"tag":512,"props":6796,"children":6797},{},[6798],{"type":420,"value":6799},"It's more secure if you don't need a secret to authenticate to Azure",{"type":415,"tag":512,"props":6801,"children":6802},{},[6803],{"type":420,"value":6804},"It's more practical if you don't need to handle secret rotation when secrets expire",{"type":415,"tag":416,"props":6806,"children":6807},{},[6808],{"type":420,"value":6809},"This is true whatever the CI/CD platform you are using.",{"type":415,"tag":416,"props":6811,"children":6812},{},[6813,6820,6822,6828],{"type":415,"tag":423,"props":6814,"children":6817},{"href":6815,"rel":6816},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation",[427],[6818],{"type":420,"value":6819},"Workload identity federation",{"type":420,"value":6821}," leverages OpenID Connect to solve these problems and avoid using secrets in your pipelines to authenticate to Azure. I previously published ",{"type":415,"tag":423,"props":6823,"children":6825},{"href":3900,"rel":6824},[427],[6826],{"type":420,"value":6827},"an article about using Azure OpenID Connect with Pulumi in GitHub Actions",{"type":420,"value":6829},", but that also works with Azure Pipelines.",{"type":415,"tag":416,"props":6831,"children":6832},{},[6833],{"type":415,"tag":3882,"props":6834,"children":6838},{"alt":6835,"className":6836,"src":6837},"Workload Identity Federation for Azure DevOps",[3886,3887],"/posts/images/azuredevopsoidc_schema_1.webp",[],{"type":415,"tag":434,"props":6840,"children":6842},{"icon":6841},"i-heroicons-information-circle",[6843],{"type":415,"tag":416,"props":6844,"children":6845},{},[6846,6848,6855],{"type":420,"value":6847},"Microsoft has announced the ",{"type":415,"tag":423,"props":6849,"children":6852},{"href":6850,"rel":6851},"https://devblogs.microsoft.com/devops/public-preview-of-workload-identity-federation-for-azure-pipelines/",[427],[6853],{"type":420,"value":6854},"public preview of Workload identity federation for Azure Pipelines",{"type":420,"value":6856}," on the 11th September 2023.",{"type":415,"tag":482,"props":6858,"children":6860},{"id":6859},"how-can-you-use-workload-identity-federation-to-deploy-to-azure-from-azure-pipelines",[6861,6863],{"type":420,"value":6862},"How can you use ",{"type":415,"tag":6864,"props":6865,"children":6866},"strong",{},[6867],{"type":420,"value":6868},"Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"type":415,"tag":416,"props":6870,"children":6871},{},[6872],{"type":420,"value":6873},"Azure Pipelines tasks use service connections to authenticate with external services. Specifically, for Azure, it is necessary to create an Azure Resource Manager service connection.",{"type":415,"tag":416,"props":6875,"children":6876},{},[6877,6879,6885],{"type":420,"value":6878},"You can create an Azure Resource Manager service connection that uses workload identity federation by configuring it in your Azure DevOps organization portal (check the documentation ",{"type":415,"tag":423,"props":6880,"children":6883},{"href":6881,"rel":6882},"https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-using-workload-identity-federation",[427],[6884],{"type":420,"value":4427},{"type":420,"value":6886},").",{"type":415,"tag":416,"props":6888,"children":6889},{},[6890],{"type":420,"value":6891},"Or ... you can automate that using Infrastructure as Code 😉.",{"type":415,"tag":416,"props":6893,"children":6894},{},[6895],{"type":420,"value":6896},"Yet, who wants to manually configure things from a wizard when everything can be automated in versioned code? So let's go the IaC way.",{"type":415,"tag":434,"props":6898,"children":6899},{"icon":1382},[6900],{"type":415,"tag":416,"props":6901,"children":6902},{},[6903],{"type":420,"value":6904},"All kidding aside, I genuinely believe that there are many advantages to provisioning your Azure DevOps projects and their associated resources (Repos, Service Connections, policies, pipelines, ...) using Infrastructure as Code. It takes time to properly configure Azure DevOps projects, and if they are often organized similarly, it's more efficient to automate their configuration rather than doing it manually.",{"type":415,"tag":416,"props":6906,"children":6907},{},[6908],{"type":415,"tag":3882,"props":6909,"children":6913},{"alt":6910,"className":6911,"src":6912},"Diagram to deploy from Azure Pipelines to Azure",[3886,3887],"/posts/images/azuredevopsoidc_schema_2.webp",[],{"type":415,"tag":416,"props":6915,"children":6916},{},[6917],{"type":420,"value":6918},"I will use Pulumi and its Azure DevOps provider to provision the necessary resources. The infrastructure as code will be written in C# but you could easily convert the C# code to any language that Pulumi supports (like TypeScript, I am a big fan of using TypeScript to write infrastructure code 🔥).",{"type":415,"tag":416,"props":6920,"children":6921},{},[6922],{"type":420,"value":6923},"Here is the complete solution to implement:",{"type":415,"tag":416,"props":6925,"children":6926},{},[6927],{"type":415,"tag":3882,"props":6928,"children":6933},{"alt":6929,"className":6930,"src":6931,"width":6932},"Schema of the complete solution",[3886,3887],"/posts/images/azuredevopsoidc_schema_3.webp",1000,[],{"type":415,"tag":482,"props":6935,"children":6937},{"id":6936},"automate-the-configuration-of-workload-identity-federation-in-azure-devops",[6938],{"type":420,"value":6939},"Automate the configuration of Workload identity federation in Azure DevOps",{"type":415,"tag":3914,"props":6941,"children":6943},{"id":6942},"create-the-pulumi-net-project",[6944],{"type":420,"value":6945},"Create the Pulumi .NET project",{"type":415,"tag":416,"props":6947,"children":6948},{},[6949],{"type":420,"value":6950},"Let's start by scaffolding a new Pulumi project using .NET:",{"type":415,"tag":523,"props":6952,"children":6954},{"className":3984,"code":6953,"language":3986,"meta":401,"style":401},"pulumi new csharp -n AzureDevOpsWorkloadIdentity -s dev -d \"A program to set up an Azure-Ready Azure DevOps repository\"\n",[6955],{"type":415,"tag":468,"props":6956,"children":6957},{"__ignoreMap":401},[6958],{"type":415,"tag":532,"props":6959,"children":6960},{"class":534,"line":535},[6961,6965,6969,6974,6979,6984,6989,6994,6999,7003,7008],{"type":415,"tag":532,"props":6962,"children":6963},{"style":631},[6964],{"type":420,"value":311},{"type":415,"tag":532,"props":6966,"children":6967},{"style":804},[6968],{"type":420,"value":3276},{"type":415,"tag":532,"props":6970,"children":6971},{"style":804},[6972],{"type":420,"value":6973}," csharp",{"type":415,"tag":532,"props":6975,"children":6976},{"style":804},[6977],{"type":420,"value":6978}," -n",{"type":415,"tag":532,"props":6980,"children":6981},{"style":804},[6982],{"type":420,"value":6983}," AzureDevOpsWorkloadIdentity",{"type":415,"tag":532,"props":6985,"children":6986},{"style":804},[6987],{"type":420,"value":6988}," -s",{"type":415,"tag":532,"props":6990,"children":6991},{"style":804},[6992],{"type":420,"value":6993}," dev",{"type":415,"tag":532,"props":6995,"children":6996},{"style":804},[6997],{"type":420,"value":6998}," -d",{"type":415,"tag":532,"props":7000,"children":7001},{"style":551},[7002],{"type":420,"value":4041},{"type":415,"tag":532,"props":7004,"children":7005},{"style":804},[7006],{"type":420,"value":7007},"A program to set up an Azure-Ready Azure DevOps repository",{"type":415,"tag":532,"props":7009,"children":7010},{"style":551},[7011],{"type":420,"value":4051},{"type":415,"tag":416,"props":7013,"children":7014},{},[7015,7017,7022],{"type":420,"value":7016},"This command creates a new pulumi project and stack from the ",{"type":415,"tag":468,"props":7018,"children":7020},{"className":7019},[],[7021],{"type":420,"value":326},{"type":420,"value":7023}," template:",{"type":415,"tag":508,"props":7025,"children":7026},{},[7027,7048,7065],{"type":415,"tag":512,"props":7028,"children":7029},{},[7030,7032,7038,7040,7046],{"type":420,"value":7031},"The name of the project \"",{"type":415,"tag":7033,"props":7034,"children":7035},"em",{},[7036],{"type":420,"value":7037},"AzureDevOpsWorkloadIdentity",{"type":420,"value":7039},"\" is specified using the ",{"type":415,"tag":468,"props":7041,"children":7043},{"className":7042},[],[7044],{"type":420,"value":7045},"-n",{"type":420,"value":7047}," option",{"type":415,"tag":512,"props":7049,"children":7050},{},[7051,7053,7057,7058,7064],{"type":420,"value":7052},"The description of the project \"",{"type":415,"tag":7033,"props":7054,"children":7055},{},[7056],{"type":420,"value":7007},{"type":420,"value":7039},{"type":415,"tag":468,"props":7059,"children":7061},{"className":7060},[],[7062],{"type":420,"value":7063},"-d",{"type":420,"value":7047},{"type":415,"tag":512,"props":7066,"children":7067},{},[7068,7070,7075,7076,7082],{"type":420,"value":7069},"The stack of the project \"",{"type":415,"tag":7033,"props":7071,"children":7072},{},[7073],{"type":420,"value":7074},"dev",{"type":420,"value":7039},{"type":415,"tag":468,"props":7077,"children":7079},{"className":7078},[],[7080],{"type":420,"value":7081},"-s",{"type":420,"value":7047},{"type":415,"tag":416,"props":7084,"children":7085},{},[7086],{"type":420,"value":7087},"This project will need 3 different providers:",{"type":415,"tag":508,"props":7089,"children":7090},{},[7091,7103,7116],{"type":415,"tag":512,"props":7092,"children":7093},{},[7094,7096],{"type":420,"value":7095},"the ",{"type":415,"tag":423,"props":7097,"children":7100},{"href":7098,"rel":7099},"https://www.pulumi.com/registry/packages/azure-native/",[427],[7101],{"type":420,"value":7102},"Azure Native provider",{"type":415,"tag":512,"props":7104,"children":7105},{},[7106,7107,7114],{"type":420,"value":7095},{"type":415,"tag":423,"props":7108,"children":7111},{"href":7109,"rel":7110},"https://www.pulumi.com/registry/packages/azuread/",[427],[7112],{"type":420,"value":7113},"Azure Active Directory provider",{"type":420,"value":7115}," (provider for Microsoft Entra ID)",{"type":415,"tag":512,"props":7117,"children":7118},{},[7119,7120],{"type":420,"value":7095},{"type":415,"tag":423,"props":7121,"children":7124},{"href":7122,"rel":7123},"https://www.pulumi.com/registry/packages/azuredevops/",[427],[7125],{"type":420,"value":7126},"Azure DevOps provider",{"type":415,"tag":416,"props":7128,"children":7129},{},[7130],{"type":420,"value":7131},"So we can add the following Nuget packages to our project:",{"type":415,"tag":508,"props":7133,"children":7134},{},[7135,7149,7163],{"type":415,"tag":512,"props":7136,"children":7137},{},[7138],{"type":415,"tag":423,"props":7139,"children":7142},{"href":7140,"rel":7141},"https://www.nuget.org/packages/Pulumi.AzureNative",[427],[7143],{"type":415,"tag":468,"props":7144,"children":7146},{"className":7145},[],[7147],{"type":420,"value":7148},"Pulumi.AzureNative",{"type":415,"tag":512,"props":7150,"children":7151},{},[7152],{"type":415,"tag":423,"props":7153,"children":7156},{"href":7154,"rel":7155},"https://www.nuget.org/packages/Pulumi.AzureAD",[427],[7157],{"type":415,"tag":468,"props":7158,"children":7160},{"className":7159},[],[7161],{"type":420,"value":7162},"Pulumi.AzureAD",{"type":415,"tag":512,"props":7164,"children":7165},{},[7166],{"type":415,"tag":423,"props":7167,"children":7170},{"href":7168,"rel":7169},"https://www.nuget.org/packages/Pulumi.AzureDevOps",[427],[7171],{"type":415,"tag":468,"props":7172,"children":7174},{"className":7173},[],[7175],{"type":420,"value":7176},"Pulumi.AzureDevOps",{"type":415,"tag":3914,"props":7178,"children":7180},{"id":7179},"create-the-azure-devops-project",[7181],{"type":420,"value":7182},"Create the Azure DevOps project",{"type":415,"tag":416,"props":7184,"children":7185},{},[7186],{"type":420,"value":7187},"First, we must select the Azure DevOps organization where we wish to create a project and set its URL in our Pulumi configuration.",{"type":415,"tag":523,"props":7189,"children":7191},{"className":3984,"code":7190,"language":3986,"meta":401,"style":401},"pulumi config set azuredevops:orgServiceUrl XXXXXXXXXXXXXX --secret\n",[7192],{"type":415,"tag":468,"props":7193,"children":7194},{"__ignoreMap":401},[7195],{"type":415,"tag":532,"props":7196,"children":7197},{"class":534,"line":535},[7198,7202,7207,7212,7217,7222],{"type":415,"tag":532,"props":7199,"children":7200},{"style":631},[7201],{"type":420,"value":311},{"type":415,"tag":532,"props":7203,"children":7204},{"style":804},[7205],{"type":420,"value":7206}," config",{"type":415,"tag":532,"props":7208,"children":7209},{"style":804},[7210],{"type":420,"value":7211}," set",{"type":415,"tag":532,"props":7213,"children":7214},{"style":804},[7215],{"type":420,"value":7216}," azuredevops:orgServiceUrl",{"type":415,"tag":532,"props":7218,"children":7219},{"style":804},[7220],{"type":420,"value":7221}," XXXXXXXXXXXXXX",{"type":415,"tag":532,"props":7223,"children":7224},{"style":804},[7225],{"type":420,"value":7226}," --secret\n",{"type":415,"tag":416,"props":7228,"children":7229},{},[7230,7232,7239],{"type":420,"value":7231},"Second, we need to supply the necessary Azure DevOps credentials. For that, we can ",{"type":415,"tag":423,"props":7233,"children":7236},{"href":7234,"rel":7235},"https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#create-a-pat",[427],[7237],{"type":420,"value":7238},"create a personal access token",{"type":420,"value":7240}," and add it to our Pulumi configuration.",{"type":415,"tag":523,"props":7242,"children":7244},{"className":3984,"code":7243,"language":3986,"meta":401,"style":401},"pulumi config set azuredevops:personalAccessToken YYYYYYYYYYYYYY --secret\n",[7245],{"type":415,"tag":468,"props":7246,"children":7247},{"__ignoreMap":401},[7248],{"type":415,"tag":532,"props":7249,"children":7250},{"class":534,"line":535},[7251,7255,7259,7263,7268,7273],{"type":415,"tag":532,"props":7252,"children":7253},{"style":631},[7254],{"type":420,"value":311},{"type":415,"tag":532,"props":7256,"children":7257},{"style":804},[7258],{"type":420,"value":7206},{"type":415,"tag":532,"props":7260,"children":7261},{"style":804},[7262],{"type":420,"value":7211},{"type":415,"tag":532,"props":7264,"children":7265},{"style":804},[7266],{"type":420,"value":7267}," azuredevops:personalAccessToken",{"type":415,"tag":532,"props":7269,"children":7270},{"style":804},[7271],{"type":420,"value":7272}," YYYYYYYYYYYYYY",{"type":415,"tag":532,"props":7274,"children":7275},{"style":804},[7276],{"type":420,"value":7226},{"type":415,"tag":434,"props":7278,"children":7280},{"icon":7279},"i-fluent-emoji-flat-locked-with-key",[7281],{"type":415,"tag":416,"props":7282,"children":7283},{},[7284,7286,7292,7294,7299],{"type":420,"value":7285},"I followed the documentation but to be honest, I don't think it's necessary to include the ",{"type":415,"tag":468,"props":7287,"children":7289},{"className":7288},[],[7290],{"type":420,"value":7291},"--secret",{"type":420,"value":7293}," option for the organization URL as it's not really a sensitive value that needs to be encrypted. However, ",{"type":415,"tag":6864,"props":7295,"children":7296},{},[7297],{"type":420,"value":7298},"it's mandatory to include it for the access token",{"type":420,"value":7300}," so that we can safely commit the configuration files without creating security risks.",{"type":415,"tag":416,"props":7302,"children":7303},{},[7304],{"type":420,"value":7305},"Third, we can create the DevOps project:",{"type":415,"tag":523,"props":7307,"children":7309},{"className":525,"code":7308,"language":326,"meta":401,"style":401},"var project = new Project(\"AzureReadyADOProject\", new()\n{\n    Description = \"New project with everything correctly configured to provision Azure resources or deploy applications to Azure\",\n    Features = new()\n    {\n        [\"boards\"] = \"disabled\",\n        [\"repositories\"] = \"enabled\",\n        [\"pipelines\"] = \"enabled\",\n        [\"testplans\"] = \"disabled\",\n        [\"artifacts\"] = \"disabled\"\n    },\n});\n",[7310],{"type":415,"tag":468,"props":7311,"children":7312},{"__ignoreMap":401},[7313,7364,7371,7401,7417,7424,7471,7516,7559,7603,7643,7651],{"type":415,"tag":532,"props":7314,"children":7315},{"class":534,"line":535},[7316,7320,7325,7329,7333,7338,7342,7346,7351,7355,7359],{"type":415,"tag":532,"props":7317,"children":7318},{"style":631},[7319],{"type":420,"value":634},{"type":415,"tag":532,"props":7321,"children":7322},{"style":631},[7323],{"type":420,"value":7324}," project",{"type":415,"tag":532,"props":7326,"children":7327},{"style":551},[7328],{"type":420,"value":644},{"type":415,"tag":532,"props":7330,"children":7331},{"style":551},[7332],{"type":420,"value":3276},{"type":415,"tag":532,"props":7334,"children":7335},{"style":631},[7336],{"type":420,"value":7337}," Project",{"type":415,"tag":532,"props":7339,"children":7340},{"style":551},[7341],{"type":420,"value":664},{"type":415,"tag":532,"props":7343,"children":7344},{"style":551},[7345],{"type":420,"value":801},{"type":415,"tag":532,"props":7347,"children":7348},{"style":804},[7349],{"type":420,"value":7350},"AzureReadyADOProject",{"type":415,"tag":532,"props":7352,"children":7353},{"style":551},[7354],{"type":420,"value":801},{"type":415,"tag":532,"props":7356,"children":7357},{"style":551},[7358],{"type":420,"value":1099},{"type":415,"tag":532,"props":7360,"children":7361},{"style":551},[7362],{"type":420,"value":7363}," new()\n",{"type":415,"tag":532,"props":7365,"children":7366},{"class":534,"line":566},[7367],{"type":415,"tag":532,"props":7368,"children":7369},{"style":551},[7370],{"type":420,"value":764},{"type":415,"tag":532,"props":7372,"children":7373},{"class":534,"line":583},[7374,7379,7383,7387,7392,7396],{"type":415,"tag":532,"props":7375,"children":7376},{"style":545},[7377],{"type":420,"value":7378},"    Description ",{"type":415,"tag":532,"props":7380,"children":7381},{"style":551},[7382],{"type":420,"value":1134},{"type":415,"tag":532,"props":7384,"children":7385},{"style":551},[7386],{"type":420,"value":4041},{"type":415,"tag":532,"props":7388,"children":7389},{"style":804},[7390],{"type":420,"value":7391},"New project with everything correctly configured to provision Azure resources or deploy applications to Azure",{"type":415,"tag":532,"props":7393,"children":7394},{"style":551},[7395],{"type":420,"value":801},{"type":415,"tag":532,"props":7397,"children":7398},{"style":551},[7399],{"type":420,"value":7400},",\n",{"type":415,"tag":532,"props":7402,"children":7403},{"class":534,"line":617},[7404,7409,7413],{"type":415,"tag":532,"props":7405,"children":7406},{"style":545},[7407],{"type":420,"value":7408},"    Features ",{"type":415,"tag":532,"props":7410,"children":7411},{"style":551},[7412],{"type":420,"value":1134},{"type":415,"tag":532,"props":7414,"children":7415},{"style":551},[7416],{"type":420,"value":7363},{"type":415,"tag":532,"props":7418,"children":7419},{"class":534,"line":627},[7420],{"type":415,"tag":532,"props":7421,"children":7422},{"style":551},[7423],{"type":420,"value":1121},{"type":415,"tag":532,"props":7425,"children":7426},{"class":534,"line":677},[7427,7432,7436,7441,7445,7450,7454,7458,7463,7467],{"type":415,"tag":532,"props":7428,"children":7429},{"style":551},[7430],{"type":420,"value":7431},"        [",{"type":415,"tag":532,"props":7433,"children":7434},{"style":551},[7435],{"type":420,"value":801},{"type":415,"tag":532,"props":7437,"children":7438},{"style":804},[7439],{"type":420,"value":7440},"boards",{"type":415,"tag":532,"props":7442,"children":7443},{"style":551},[7444],{"type":420,"value":801},{"type":415,"tag":532,"props":7446,"children":7447},{"style":551},[7448],{"type":420,"value":7449},"]",{"type":415,"tag":532,"props":7451,"children":7452},{"style":551},[7453],{"type":420,"value":644},{"type":415,"tag":532,"props":7455,"children":7456},{"style":551},[7457],{"type":420,"value":4041},{"type":415,"tag":532,"props":7459,"children":7460},{"style":804},[7461],{"type":420,"value":7462},"disabled",{"type":415,"tag":532,"props":7464,"children":7465},{"style":551},[7466],{"type":420,"value":801},{"type":415,"tag":532,"props":7468,"children":7469},{"style":551},[7470],{"type":420,"value":7400},{"type":415,"tag":532,"props":7472,"children":7473},{"class":534,"line":719},[7474,7478,7482,7487,7491,7495,7499,7503,7508,7512],{"type":415,"tag":532,"props":7475,"children":7476},{"style":551},[7477],{"type":420,"value":7431},{"type":415,"tag":532,"props":7479,"children":7480},{"style":551},[7481],{"type":420,"value":801},{"type":415,"tag":532,"props":7483,"children":7484},{"style":804},[7485],{"type":420,"value":7486},"repositories",{"type":415,"tag":532,"props":7488,"children":7489},{"style":551},[7490],{"type":420,"value":801},{"type":415,"tag":532,"props":7492,"children":7493},{"style":551},[7494],{"type":420,"value":7449},{"type":415,"tag":532,"props":7496,"children":7497},{"style":551},[7498],{"type":420,"value":644},{"type":415,"tag":532,"props":7500,"children":7501},{"style":551},[7502],{"type":420,"value":4041},{"type":415,"tag":532,"props":7504,"children":7505},{"style":804},[7506],{"type":420,"value":7507},"enabled",{"type":415,"tag":532,"props":7509,"children":7510},{"style":551},[7511],{"type":420,"value":801},{"type":415,"tag":532,"props":7513,"children":7514},{"style":551},[7515],{"type":420,"value":7400},{"type":415,"tag":532,"props":7517,"children":7518},{"class":534,"line":758},[7519,7523,7527,7531,7535,7539,7543,7547,7551,7555],{"type":415,"tag":532,"props":7520,"children":7521},{"style":551},[7522],{"type":420,"value":7431},{"type":415,"tag":532,"props":7524,"children":7525},{"style":551},[7526],{"type":420,"value":801},{"type":415,"tag":532,"props":7528,"children":7529},{"style":804},[7530],{"type":420,"value":367},{"type":415,"tag":532,"props":7532,"children":7533},{"style":551},[7534],{"type":420,"value":801},{"type":415,"tag":532,"props":7536,"children":7537},{"style":551},[7538],{"type":420,"value":7449},{"type":415,"tag":532,"props":7540,"children":7541},{"style":551},[7542],{"type":420,"value":644},{"type":415,"tag":532,"props":7544,"children":7545},{"style":551},[7546],{"type":420,"value":4041},{"type":415,"tag":532,"props":7548,"children":7549},{"style":804},[7550],{"type":420,"value":7507},{"type":415,"tag":532,"props":7552,"children":7553},{"style":551},[7554],{"type":420,"value":801},{"type":415,"tag":532,"props":7556,"children":7557},{"style":551},[7558],{"type":420,"value":7400},{"type":415,"tag":532,"props":7560,"children":7561},{"class":534,"line":767},[7562,7566,7570,7575,7579,7583,7587,7591,7595,7599],{"type":415,"tag":532,"props":7563,"children":7564},{"style":551},[7565],{"type":420,"value":7431},{"type":415,"tag":532,"props":7567,"children":7568},{"style":551},[7569],{"type":420,"value":801},{"type":415,"tag":532,"props":7571,"children":7572},{"style":804},[7573],{"type":420,"value":7574},"testplans",{"type":415,"tag":532,"props":7576,"children":7577},{"style":551},[7578],{"type":420,"value":801},{"type":415,"tag":532,"props":7580,"children":7581},{"style":551},[7582],{"type":420,"value":7449},{"type":415,"tag":532,"props":7584,"children":7585},{"style":551},[7586],{"type":420,"value":644},{"type":415,"tag":532,"props":7588,"children":7589},{"style":551},[7590],{"type":420,"value":4041},{"type":415,"tag":532,"props":7592,"children":7593},{"style":804},[7594],{"type":420,"value":7462},{"type":415,"tag":532,"props":7596,"children":7597},{"style":551},[7598],{"type":420,"value":801},{"type":415,"tag":532,"props":7600,"children":7601},{"style":551},[7602],{"type":420,"value":7400},{"type":415,"tag":532,"props":7604,"children":7605},{"class":534,"line":819},[7606,7610,7614,7619,7623,7627,7631,7635,7639],{"type":415,"tag":532,"props":7607,"children":7608},{"style":551},[7609],{"type":420,"value":7431},{"type":415,"tag":532,"props":7611,"children":7612},{"style":551},[7613],{"type":420,"value":801},{"type":415,"tag":532,"props":7615,"children":7616},{"style":804},[7617],{"type":420,"value":7618},"artifacts",{"type":415,"tag":532,"props":7620,"children":7621},{"style":551},[7622],{"type":420,"value":801},{"type":415,"tag":532,"props":7624,"children":7625},{"style":551},[7626],{"type":420,"value":7449},{"type":415,"tag":532,"props":7628,"children":7629},{"style":551},[7630],{"type":420,"value":644},{"type":415,"tag":532,"props":7632,"children":7633},{"style":551},[7634],{"type":420,"value":4041},{"type":415,"tag":532,"props":7636,"children":7637},{"style":804},[7638],{"type":420,"value":7462},{"type":415,"tag":532,"props":7640,"children":7641},{"style":551},[7642],{"type":420,"value":4051},{"type":415,"tag":532,"props":7644,"children":7645},{"class":534,"line":850},[7646],{"type":415,"tag":532,"props":7647,"children":7648},{"style":551},[7649],{"type":420,"value":7650},"    },\n",{"type":415,"tag":532,"props":7652,"children":7653},{"class":534,"line":859},[7654],{"type":415,"tag":532,"props":7655,"children":7656},{"style":551},[7657],{"type":420,"value":856},{"type":415,"tag":416,"props":7659,"children":7660},{},[7661],{"type":420,"value":7662},"I intentionally disabled Azure Boards, Azure Test Plans, and Azure Artifacts as we only need Azure Repos and Azure Pipelines for this demo but you can enable what you need for your projects.",{"type":415,"tag":416,"props":7664,"children":7665},{},[7666,7668,7675],{"type":420,"value":7667},"By default, when we create an Azure DevOps project, a ",{"type":415,"tag":423,"props":7669,"children":7672},{"href":7670,"rel":7671},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/git/",[427],[7673],{"type":420,"value":7674},"Git repository",{"type":420,"value":7676}," is created for us with the same name as the project. This repository can be retrieved using the following code:",{"type":415,"tag":523,"props":7678,"children":7680},{"className":525,"code":7679,"language":326,"meta":401,"style":401},"var repository = GetGitRepository.Invoke(new()\n{\n    ProjectId = project.Id,\n    Name = project.Name\n});\n",[7681],{"type":415,"tag":468,"props":7682,"children":7683},{"__ignoreMap":401},[7684,7719,7726,7755,7780],{"type":415,"tag":532,"props":7685,"children":7686},{"class":534,"line":535},[7687,7691,7696,7700,7705,7709,7714],{"type":415,"tag":532,"props":7688,"children":7689},{"style":631},[7690],{"type":420,"value":634},{"type":415,"tag":532,"props":7692,"children":7693},{"style":631},[7694],{"type":420,"value":7695}," repository",{"type":415,"tag":532,"props":7697,"children":7698},{"style":551},[7699],{"type":420,"value":644},{"type":415,"tag":532,"props":7701,"children":7702},{"style":545},[7703],{"type":420,"value":7704}," GetGitRepository",{"type":415,"tag":532,"props":7706,"children":7707},{"style":551},[7708],{"type":420,"value":432},{"type":415,"tag":532,"props":7710,"children":7711},{"style":656},[7712],{"type":420,"value":7713},"Invoke",{"type":415,"tag":532,"props":7715,"children":7716},{"style":551},[7717],{"type":420,"value":7718},"(new()\n",{"type":415,"tag":532,"props":7720,"children":7721},{"class":534,"line":566},[7722],{"type":415,"tag":532,"props":7723,"children":7724},{"style":551},[7725],{"type":420,"value":764},{"type":415,"tag":532,"props":7727,"children":7728},{"class":534,"line":583},[7729,7734,7738,7742,7746,7751],{"type":415,"tag":532,"props":7730,"children":7731},{"style":545},[7732],{"type":420,"value":7733},"    ProjectId ",{"type":415,"tag":532,"props":7735,"children":7736},{"style":551},[7737],{"type":420,"value":1134},{"type":415,"tag":532,"props":7739,"children":7740},{"style":545},[7741],{"type":420,"value":7324},{"type":415,"tag":532,"props":7743,"children":7744},{"style":551},[7745],{"type":420,"value":432},{"type":415,"tag":532,"props":7747,"children":7748},{"style":545},[7749],{"type":420,"value":7750},"Id",{"type":415,"tag":532,"props":7752,"children":7753},{"style":551},[7754],{"type":420,"value":7400},{"type":415,"tag":532,"props":7756,"children":7757},{"class":534,"line":617},[7758,7763,7767,7771,7775],{"type":415,"tag":532,"props":7759,"children":7760},{"style":545},[7761],{"type":420,"value":7762},"    Name ",{"type":415,"tag":532,"props":7764,"children":7765},{"style":551},[7766],{"type":420,"value":1134},{"type":415,"tag":532,"props":7768,"children":7769},{"style":545},[7770],{"type":420,"value":7324},{"type":415,"tag":532,"props":7772,"children":7773},{"style":551},[7774],{"type":420,"value":432},{"type":415,"tag":532,"props":7776,"children":7777},{"style":545},[7778],{"type":420,"value":7779},"Name\n",{"type":415,"tag":532,"props":7781,"children":7782},{"class":534,"line":627},[7783],{"type":415,"tag":532,"props":7784,"children":7785},{"style":551},[7786],{"type":420,"value":856},{"type":415,"tag":416,"props":7788,"children":7789},{},[7790],{"type":420,"value":7791},"We can also choose to create a new Git repository like this:",{"type":415,"tag":523,"props":7793,"children":7795},{"className":525,"code":7794,"language":326,"meta":401,"style":401},"var repository = new Git(\"AzureReadyADORepository\", new()\n{\n    ProjectId = project.Id,\n    Initialization = new GitInitializationArgs()\n    {\n        InitType = \"Clean\",\n        SourceType = \"Git\",\n        SourceUrl = \"https://repo.com\",\n        ServiceConnectionId = \"\"\n    },\n    DefaultBranch = \"refs/heads/main\"\n});\n",[7796],{"type":415,"tag":468,"props":7797,"children":7798},{"__ignoreMap":401},[7799,7848,7855,7882,7908,7915,7944,7973,8002,8019,8026,8051],{"type":415,"tag":532,"props":7800,"children":7801},{"class":534,"line":535},[7802,7806,7810,7814,7818,7823,7827,7831,7836,7840,7844],{"type":415,"tag":532,"props":7803,"children":7804},{"style":631},[7805],{"type":420,"value":634},{"type":415,"tag":532,"props":7807,"children":7808},{"style":631},[7809],{"type":420,"value":7695},{"type":415,"tag":532,"props":7811,"children":7812},{"style":551},[7813],{"type":420,"value":644},{"type":415,"tag":532,"props":7815,"children":7816},{"style":551},[7817],{"type":420,"value":3276},{"type":415,"tag":532,"props":7819,"children":7820},{"style":631},[7821],{"type":420,"value":7822}," Git",{"type":415,"tag":532,"props":7824,"children":7825},{"style":551},[7826],{"type":420,"value":664},{"type":415,"tag":532,"props":7828,"children":7829},{"style":551},[7830],{"type":420,"value":801},{"type":415,"tag":532,"props":7832,"children":7833},{"style":804},[7834],{"type":420,"value":7835},"AzureReadyADORepository",{"type":415,"tag":532,"props":7837,"children":7838},{"style":551},[7839],{"type":420,"value":801},{"type":415,"tag":532,"props":7841,"children":7842},{"style":551},[7843],{"type":420,"value":1099},{"type":415,"tag":532,"props":7845,"children":7846},{"style":551},[7847],{"type":420,"value":7363},{"type":415,"tag":532,"props":7849,"children":7850},{"class":534,"line":566},[7851],{"type":415,"tag":532,"props":7852,"children":7853},{"style":551},[7854],{"type":420,"value":764},{"type":415,"tag":532,"props":7856,"children":7857},{"class":534,"line":583},[7858,7862,7866,7870,7874,7878],{"type":415,"tag":532,"props":7859,"children":7860},{"style":545},[7861],{"type":420,"value":7733},{"type":415,"tag":532,"props":7863,"children":7864},{"style":551},[7865],{"type":420,"value":1134},{"type":415,"tag":532,"props":7867,"children":7868},{"style":545},[7869],{"type":420,"value":7324},{"type":415,"tag":532,"props":7871,"children":7872},{"style":551},[7873],{"type":420,"value":432},{"type":415,"tag":532,"props":7875,"children":7876},{"style":545},[7877],{"type":420,"value":7750},{"type":415,"tag":532,"props":7879,"children":7880},{"style":551},[7881],{"type":420,"value":7400},{"type":415,"tag":532,"props":7883,"children":7884},{"class":534,"line":617},[7885,7890,7894,7898,7903],{"type":415,"tag":532,"props":7886,"children":7887},{"style":545},[7888],{"type":420,"value":7889},"    Initialization ",{"type":415,"tag":532,"props":7891,"children":7892},{"style":551},[7893],{"type":420,"value":1134},{"type":415,"tag":532,"props":7895,"children":7896},{"style":551},[7897],{"type":420,"value":3276},{"type":415,"tag":532,"props":7899,"children":7900},{"style":631},[7901],{"type":420,"value":7902}," GitInitializationArgs",{"type":415,"tag":532,"props":7904,"children":7905},{"style":551},[7906],{"type":420,"value":7907},"()\n",{"type":415,"tag":532,"props":7909,"children":7910},{"class":534,"line":627},[7911],{"type":415,"tag":532,"props":7912,"children":7913},{"style":551},[7914],{"type":420,"value":1121},{"type":415,"tag":532,"props":7916,"children":7917},{"class":534,"line":677},[7918,7923,7927,7931,7936,7940],{"type":415,"tag":532,"props":7919,"children":7920},{"style":545},[7921],{"type":420,"value":7922},"        InitType ",{"type":415,"tag":532,"props":7924,"children":7925},{"style":551},[7926],{"type":420,"value":1134},{"type":415,"tag":532,"props":7928,"children":7929},{"style":551},[7930],{"type":420,"value":4041},{"type":415,"tag":532,"props":7932,"children":7933},{"style":804},[7934],{"type":420,"value":7935},"Clean",{"type":415,"tag":532,"props":7937,"children":7938},{"style":551},[7939],{"type":420,"value":801},{"type":415,"tag":532,"props":7941,"children":7942},{"style":551},[7943],{"type":420,"value":7400},{"type":415,"tag":532,"props":7945,"children":7946},{"class":534,"line":719},[7947,7952,7956,7960,7965,7969],{"type":415,"tag":532,"props":7948,"children":7949},{"style":545},[7950],{"type":420,"value":7951},"        SourceType ",{"type":415,"tag":532,"props":7953,"children":7954},{"style":551},[7955],{"type":420,"value":1134},{"type":415,"tag":532,"props":7957,"children":7958},{"style":551},[7959],{"type":420,"value":4041},{"type":415,"tag":532,"props":7961,"children":7962},{"style":804},[7963],{"type":420,"value":7964},"Git",{"type":415,"tag":532,"props":7966,"children":7967},{"style":551},[7968],{"type":420,"value":801},{"type":415,"tag":532,"props":7970,"children":7971},{"style":551},[7972],{"type":420,"value":7400},{"type":415,"tag":532,"props":7974,"children":7975},{"class":534,"line":758},[7976,7981,7985,7989,7994,7998],{"type":415,"tag":532,"props":7977,"children":7978},{"style":545},[7979],{"type":420,"value":7980},"        SourceUrl ",{"type":415,"tag":532,"props":7982,"children":7983},{"style":551},[7984],{"type":420,"value":1134},{"type":415,"tag":532,"props":7986,"children":7987},{"style":551},[7988],{"type":420,"value":4041},{"type":415,"tag":532,"props":7990,"children":7991},{"style":804},[7992],{"type":420,"value":7993},"https://repo.com",{"type":415,"tag":532,"props":7995,"children":7996},{"style":551},[7997],{"type":420,"value":801},{"type":415,"tag":532,"props":7999,"children":8000},{"style":551},[8001],{"type":420,"value":7400},{"type":415,"tag":532,"props":8003,"children":8004},{"class":534,"line":767},[8005,8010,8014],{"type":415,"tag":532,"props":8006,"children":8007},{"style":545},[8008],{"type":420,"value":8009},"        ServiceConnectionId ",{"type":415,"tag":532,"props":8011,"children":8012},{"style":551},[8013],{"type":420,"value":1134},{"type":415,"tag":532,"props":8015,"children":8016},{"style":551},[8017],{"type":420,"value":8018}," \"\"\n",{"type":415,"tag":532,"props":8020,"children":8021},{"class":534,"line":819},[8022],{"type":415,"tag":532,"props":8023,"children":8024},{"style":551},[8025],{"type":420,"value":7650},{"type":415,"tag":532,"props":8027,"children":8028},{"class":534,"line":850},[8029,8034,8038,8042,8047],{"type":415,"tag":532,"props":8030,"children":8031},{"style":545},[8032],{"type":420,"value":8033},"    DefaultBranch ",{"type":415,"tag":532,"props":8035,"children":8036},{"style":551},[8037],{"type":420,"value":1134},{"type":415,"tag":532,"props":8039,"children":8040},{"style":551},[8041],{"type":420,"value":4041},{"type":415,"tag":532,"props":8043,"children":8044},{"style":804},[8045],{"type":420,"value":8046},"refs/heads/main",{"type":415,"tag":532,"props":8048,"children":8049},{"style":551},[8050],{"type":420,"value":4051},{"type":415,"tag":532,"props":8052,"children":8053},{"class":534,"line":859},[8054],{"type":415,"tag":532,"props":8055,"children":8056},{"style":551},[8057],{"type":420,"value":856},{"type":415,"tag":434,"props":8059,"children":8060},{"icon":6841},[8061],{"type":415,"tag":416,"props":8062,"children":8063},{},[8064,8066,8072,8074,8080,8081,8087,8089,8095],{"type":420,"value":8065},"We should not have to set the ",{"type":415,"tag":468,"props":8067,"children":8069},{"className":8068},[],[8070],{"type":420,"value":8071},"SourceType",{"type":420,"value":8073},", ",{"type":415,"tag":468,"props":8075,"children":8077},{"className":8076},[],[8078],{"type":420,"value":8079},"SourceUrl",{"type":420,"value":6722},{"type":415,"tag":468,"props":8082,"children":8084},{"className":8083},[],[8085],{"type":420,"value":8086},"ServiceConnectionId",{"type":420,"value":8088}," properties as we are initializing a clean Git repository, not importing one, but it's a workaround because of this ",{"type":415,"tag":423,"props":8090,"children":8093},{"href":8091,"rel":8092},"https://github.com/pulumi/pulumi-azuredevops/issues/66",[427],[8094],{"type":420,"value":3004},{"type":420,"value":8096}," on the provider.",{"type":415,"tag":3914,"props":8098,"children":8100},{"id":8099},"configure-the-arm-service-connection-in-azure-devops",[8101],{"type":420,"value":8102},"Configure the ARM Service Connection in Azure DevOps",{"type":415,"tag":416,"props":8104,"children":8105},{},[8106,8108,8115],{"type":420,"value":8107},"In the Azure DevOps provider, the Azure Resource Manager service connection is called a ",{"type":415,"tag":423,"props":8109,"children":8112},{"href":8110,"rel":8111},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/serviceendpointazurerm/#workload-identity-federation-manual-azurerm-service-endpoint-subscription-scoped",[427],[8113],{"type":420,"value":8114},"ServiceEndpointAzureRM",{"type":420,"value":8116},". We can create such a resource like this:",{"type":415,"tag":523,"props":8118,"children":8120},{"className":525,"code":8119,"language":326,"meta":401,"style":401},"var serviceConnection = new ServiceEndpointAzureRM(\"AzureServiceConnection\", new()\n{\n    ProjectId = project.Id,\n    ServiceEndpointName = \"azure-with-oidc\",\n    ServiceEndpointAuthenticationScheme = \"WorkloadIdentityFederation\",\n    AzurermSpnTenantid = tenantId,\n    AzurermSubscriptionId = subscriptionId,\n    AzurermSubscriptionName = subscriptionName,\n    Credentials = new ServiceEndpointAzureRMCredentialsArgs()\n    {\n        Serviceprincipalid = servicePrincipal.ApplicationId,\n    }\n});\n",[8121],{"type":415,"tag":468,"props":8122,"children":8123},{"__ignoreMap":401},[8124,8174,8181,8208,8237,8266,8287,8308,8329,8354,8361,8391,8398],{"type":415,"tag":532,"props":8125,"children":8126},{"class":534,"line":535},[8127,8131,8136,8140,8144,8149,8153,8157,8162,8166,8170],{"type":415,"tag":532,"props":8128,"children":8129},{"style":631},[8130],{"type":420,"value":634},{"type":415,"tag":532,"props":8132,"children":8133},{"style":631},[8134],{"type":420,"value":8135}," serviceConnection",{"type":415,"tag":532,"props":8137,"children":8138},{"style":551},[8139],{"type":420,"value":644},{"type":415,"tag":532,"props":8141,"children":8142},{"style":551},[8143],{"type":420,"value":3276},{"type":415,"tag":532,"props":8145,"children":8146},{"style":631},[8147],{"type":420,"value":8148}," ServiceEndpointAzureRM",{"type":415,"tag":532,"props":8150,"children":8151},{"style":551},[8152],{"type":420,"value":664},{"type":415,"tag":532,"props":8154,"children":8155},{"style":551},[8156],{"type":420,"value":801},{"type":415,"tag":532,"props":8158,"children":8159},{"style":804},[8160],{"type":420,"value":8161},"AzureServiceConnection",{"type":415,"tag":532,"props":8163,"children":8164},{"style":551},[8165],{"type":420,"value":801},{"type":415,"tag":532,"props":8167,"children":8168},{"style":551},[8169],{"type":420,"value":1099},{"type":415,"tag":532,"props":8171,"children":8172},{"style":551},[8173],{"type":420,"value":7363},{"type":415,"tag":532,"props":8175,"children":8176},{"class":534,"line":566},[8177],{"type":415,"tag":532,"props":8178,"children":8179},{"style":551},[8180],{"type":420,"value":764},{"type":415,"tag":532,"props":8182,"children":8183},{"class":534,"line":583},[8184,8188,8192,8196,8200,8204],{"type":415,"tag":532,"props":8185,"children":8186},{"style":545},[8187],{"type":420,"value":7733},{"type":415,"tag":532,"props":8189,"children":8190},{"style":551},[8191],{"type":420,"value":1134},{"type":415,"tag":532,"props":8193,"children":8194},{"style":545},[8195],{"type":420,"value":7324},{"type":415,"tag":532,"props":8197,"children":8198},{"style":551},[8199],{"type":420,"value":432},{"type":415,"tag":532,"props":8201,"children":8202},{"style":545},[8203],{"type":420,"value":7750},{"type":415,"tag":532,"props":8205,"children":8206},{"style":551},[8207],{"type":420,"value":7400},{"type":415,"tag":532,"props":8209,"children":8210},{"class":534,"line":617},[8211,8216,8220,8224,8229,8233],{"type":415,"tag":532,"props":8212,"children":8213},{"style":545},[8214],{"type":420,"value":8215},"    ServiceEndpointName ",{"type":415,"tag":532,"props":8217,"children":8218},{"style":551},[8219],{"type":420,"value":1134},{"type":415,"tag":532,"props":8221,"children":8222},{"style":551},[8223],{"type":420,"value":4041},{"type":415,"tag":532,"props":8225,"children":8226},{"style":804},[8227],{"type":420,"value":8228},"azure-with-oidc",{"type":415,"tag":532,"props":8230,"children":8231},{"style":551},[8232],{"type":420,"value":801},{"type":415,"tag":532,"props":8234,"children":8235},{"style":551},[8236],{"type":420,"value":7400},{"type":415,"tag":532,"props":8238,"children":8239},{"class":534,"line":627},[8240,8245,8249,8253,8258,8262],{"type":415,"tag":532,"props":8241,"children":8242},{"style":545},[8243],{"type":420,"value":8244},"    ServiceEndpointAuthenticationScheme ",{"type":415,"tag":532,"props":8246,"children":8247},{"style":551},[8248],{"type":420,"value":1134},{"type":415,"tag":532,"props":8250,"children":8251},{"style":551},[8252],{"type":420,"value":4041},{"type":415,"tag":532,"props":8254,"children":8255},{"style":804},[8256],{"type":420,"value":8257},"WorkloadIdentityFederation",{"type":415,"tag":532,"props":8259,"children":8260},{"style":551},[8261],{"type":420,"value":801},{"type":415,"tag":532,"props":8263,"children":8264},{"style":551},[8265],{"type":420,"value":7400},{"type":415,"tag":532,"props":8267,"children":8268},{"class":534,"line":677},[8269,8274,8278,8283],{"type":415,"tag":532,"props":8270,"children":8271},{"style":545},[8272],{"type":420,"value":8273},"    AzurermSpnTenantid ",{"type":415,"tag":532,"props":8275,"children":8276},{"style":551},[8277],{"type":420,"value":1134},{"type":415,"tag":532,"props":8279,"children":8280},{"style":545},[8281],{"type":420,"value":8282}," tenantId",{"type":415,"tag":532,"props":8284,"children":8285},{"style":551},[8286],{"type":420,"value":7400},{"type":415,"tag":532,"props":8288,"children":8289},{"class":534,"line":719},[8290,8295,8299,8304],{"type":415,"tag":532,"props":8291,"children":8292},{"style":545},[8293],{"type":420,"value":8294},"    AzurermSubscriptionId ",{"type":415,"tag":532,"props":8296,"children":8297},{"style":551},[8298],{"type":420,"value":1134},{"type":415,"tag":532,"props":8300,"children":8301},{"style":545},[8302],{"type":420,"value":8303}," subscriptionId",{"type":415,"tag":532,"props":8305,"children":8306},{"style":551},[8307],{"type":420,"value":7400},{"type":415,"tag":532,"props":8309,"children":8310},{"class":534,"line":758},[8311,8316,8320,8325],{"type":415,"tag":532,"props":8312,"children":8313},{"style":545},[8314],{"type":420,"value":8315},"    AzurermSubscriptionName ",{"type":415,"tag":532,"props":8317,"children":8318},{"style":551},[8319],{"type":420,"value":1134},{"type":415,"tag":532,"props":8321,"children":8322},{"style":545},[8323],{"type":420,"value":8324}," subscriptionName",{"type":415,"tag":532,"props":8326,"children":8327},{"style":551},[8328],{"type":420,"value":7400},{"type":415,"tag":532,"props":8330,"children":8331},{"class":534,"line":767},[8332,8337,8341,8345,8350],{"type":415,"tag":532,"props":8333,"children":8334},{"style":545},[8335],{"type":420,"value":8336},"    Credentials ",{"type":415,"tag":532,"props":8338,"children":8339},{"style":551},[8340],{"type":420,"value":1134},{"type":415,"tag":532,"props":8342,"children":8343},{"style":551},[8344],{"type":420,"value":3276},{"type":415,"tag":532,"props":8346,"children":8347},{"style":631},[8348],{"type":420,"value":8349}," ServiceEndpointAzureRMCredentialsArgs",{"type":415,"tag":532,"props":8351,"children":8352},{"style":551},[8353],{"type":420,"value":7907},{"type":415,"tag":532,"props":8355,"children":8356},{"class":534,"line":819},[8357],{"type":415,"tag":532,"props":8358,"children":8359},{"style":551},[8360],{"type":420,"value":1121},{"type":415,"tag":532,"props":8362,"children":8363},{"class":534,"line":850},[8364,8369,8373,8378,8382,8387],{"type":415,"tag":532,"props":8365,"children":8366},{"style":545},[8367],{"type":420,"value":8368},"        Serviceprincipalid ",{"type":415,"tag":532,"props":8370,"children":8371},{"style":551},[8372],{"type":420,"value":1134},{"type":415,"tag":532,"props":8374,"children":8375},{"style":545},[8376],{"type":420,"value":8377}," servicePrincipal",{"type":415,"tag":532,"props":8379,"children":8380},{"style":551},[8381],{"type":420,"value":432},{"type":415,"tag":532,"props":8383,"children":8384},{"style":545},[8385],{"type":420,"value":8386},"ApplicationId",{"type":415,"tag":532,"props":8388,"children":8389},{"style":551},[8390],{"type":420,"value":7400},{"type":415,"tag":532,"props":8392,"children":8393},{"class":534,"line":859},[8394],{"type":415,"tag":532,"props":8395,"children":8396},{"style":551},[8397],{"type":420,"value":1170},{"type":415,"tag":532,"props":8399,"children":8400},{"class":534,"line":867},[8401],{"type":415,"tag":532,"props":8402,"children":8403},{"style":551},[8404],{"type":420,"value":856},{"type":415,"tag":416,"props":8406,"children":8407},{},[8408,8410,8416],{"type":420,"value":8409},"Do not worry about the service principal, we will see in the next section how to create it. The tenant and the subscription identifiers can be retrieved from the current configuration of the Azure Native provider (using the ",{"type":415,"tag":468,"props":8411,"children":8413},{"className":8412},[],[8414],{"type":420,"value":8415},"GetClientConfig.Invoke",{"type":420,"value":8417}," function):",{"type":415,"tag":523,"props":8419,"children":8421},{"className":525,"code":8420,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar tenantId = azureConfig.Apply(c => c.tenantId);\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\n",[8422],{"type":415,"tag":468,"props":8423,"children":8424},{"__ignoreMap":401},[8425,8458,8517],{"type":415,"tag":532,"props":8426,"children":8427},{"class":534,"line":535},[8428,8432,8437,8441,8446,8450,8454],{"type":415,"tag":532,"props":8429,"children":8430},{"style":631},[8431],{"type":420,"value":634},{"type":415,"tag":532,"props":8433,"children":8434},{"style":631},[8435],{"type":420,"value":8436}," azureConfig",{"type":415,"tag":532,"props":8438,"children":8439},{"style":551},[8440],{"type":420,"value":644},{"type":415,"tag":532,"props":8442,"children":8443},{"style":545},[8444],{"type":420,"value":8445}," GetClientConfig",{"type":415,"tag":532,"props":8447,"children":8448},{"style":551},[8449],{"type":420,"value":432},{"type":415,"tag":532,"props":8451,"children":8452},{"style":656},[8453],{"type":420,"value":7713},{"type":415,"tag":532,"props":8455,"children":8456},{"style":551},[8457],{"type":420,"value":899},{"type":415,"tag":532,"props":8459,"children":8460},{"class":534,"line":566},[8461,8465,8469,8473,8477,8481,8486,8490,8495,8500,8505,8509,8513],{"type":415,"tag":532,"props":8462,"children":8463},{"style":631},[8464],{"type":420,"value":634},{"type":415,"tag":532,"props":8466,"children":8467},{"style":631},[8468],{"type":420,"value":8282},{"type":415,"tag":532,"props":8470,"children":8471},{"style":551},[8472],{"type":420,"value":644},{"type":415,"tag":532,"props":8474,"children":8475},{"style":545},[8476],{"type":420,"value":8436},{"type":415,"tag":532,"props":8478,"children":8479},{"style":551},[8480],{"type":420,"value":432},{"type":415,"tag":532,"props":8482,"children":8483},{"style":656},[8484],{"type":420,"value":8485},"Apply",{"type":415,"tag":532,"props":8487,"children":8488},{"style":551},[8489],{"type":420,"value":664},{"type":415,"tag":532,"props":8491,"children":8492},{"style":631},[8493],{"type":420,"value":8494},"c",{"type":415,"tag":532,"props":8496,"children":8497},{"style":551},[8498],{"type":420,"value":8499}," =>",{"type":415,"tag":532,"props":8501,"children":8502},{"style":545},[8503],{"type":420,"value":8504}," c",{"type":415,"tag":532,"props":8506,"children":8507},{"style":551},[8508],{"type":420,"value":432},{"type":415,"tag":532,"props":8510,"children":8511},{"style":545},[8512],{"type":420,"value":4356},{"type":415,"tag":532,"props":8514,"children":8515},{"style":551},[8516],{"type":420,"value":674},{"type":415,"tag":532,"props":8518,"children":8519},{"class":534,"line":583},[8520,8524,8528,8532,8536,8540,8544,8548,8552,8556,8560,8564,8569],{"type":415,"tag":532,"props":8521,"children":8522},{"style":631},[8523],{"type":420,"value":634},{"type":415,"tag":532,"props":8525,"children":8526},{"style":631},[8527],{"type":420,"value":8303},{"type":415,"tag":532,"props":8529,"children":8530},{"style":551},[8531],{"type":420,"value":644},{"type":415,"tag":532,"props":8533,"children":8534},{"style":545},[8535],{"type":420,"value":8436},{"type":415,"tag":532,"props":8537,"children":8538},{"style":551},[8539],{"type":420,"value":432},{"type":415,"tag":532,"props":8541,"children":8542},{"style":656},[8543],{"type":420,"value":8485},{"type":415,"tag":532,"props":8545,"children":8546},{"style":551},[8547],{"type":420,"value":664},{"type":415,"tag":532,"props":8549,"children":8550},{"style":631},[8551],{"type":420,"value":8494},{"type":415,"tag":532,"props":8553,"children":8554},{"style":551},[8555],{"type":420,"value":8499},{"type":415,"tag":532,"props":8557,"children":8558},{"style":545},[8559],{"type":420,"value":8504},{"type":415,"tag":532,"props":8561,"children":8562},{"style":551},[8563],{"type":420,"value":432},{"type":415,"tag":532,"props":8565,"children":8566},{"style":545},[8567],{"type":420,"value":8568},"SubscriptionId",{"type":415,"tag":532,"props":8570,"children":8571},{"style":551},[8572],{"type":420,"value":674},{"type":415,"tag":416,"props":8574,"children":8575},{},[8576],{"type":420,"value":8577},"For the subscription name, it's more complicated as we don't have it, and no easy way to retrieve it. To be frank, I think having to provide the subscription name while we already provide the subscription identifier is completely useless but that's how the Azure DevOps provider works.",{"type":415,"tag":416,"props":8579,"children":8580},{},[8581,8583,8590,8592,8598],{"type":420,"value":8582},"The Azure Classic provider offers a ",{"type":415,"tag":423,"props":8584,"children":8587},{"href":8585,"rel":8586},"https://www.pulumi.com/registry/packages/azure/api-docs/core/getsubscription/#azure-core-getsubscription",[427],[8588],{"type":420,"value":8589},"function",{"type":420,"value":8591}," to get a subscription by its identifier but it's not available in the Azure Native provider. I don't want to add the Azure Classic provider to my project solely for this purpose. However, it's not a big deal as it allows us to experience one of the advantages of using Pulumi: when something is not available you can just implement it or use any library that can help you, such as the ",{"type":415,"tag":423,"props":8593,"children":8596},{"href":8594,"rel":8595},"https://www.nuget.org/packages/Azure.ResourceManager",[427],[8597],{"type":420,"value":302},{"type":420,"value":8599}," in this case.",{"type":415,"tag":523,"props":8601,"children":8603},{"className":525,"code":8602,"language":326,"meta":401,"style":401},"var subscriptionName = subscriptionId.Apply(s =>\n{\n    var armClient = new ArmClient(new DefaultAzureCredential());\n    var subscription = armClient.GetSubscriptionResource(new ResourceIdentifier($\"/subscriptions/{s}\")).Get();\n    return subscription.Value.Data.DisplayName;\n});\n",[8604],{"type":415,"tag":468,"props":8605,"children":8606},{"__ignoreMap":401},[8607,8647,8654,8692,8771,8813],{"type":415,"tag":532,"props":8608,"children":8609},{"class":534,"line":535},[8610,8614,8618,8622,8626,8630,8634,8638,8643],{"type":415,"tag":532,"props":8611,"children":8612},{"style":631},[8613],{"type":420,"value":634},{"type":415,"tag":532,"props":8615,"children":8616},{"style":631},[8617],{"type":420,"value":8324},{"type":415,"tag":532,"props":8619,"children":8620},{"style":551},[8621],{"type":420,"value":644},{"type":415,"tag":532,"props":8623,"children":8624},{"style":545},[8625],{"type":420,"value":8303},{"type":415,"tag":532,"props":8627,"children":8628},{"style":551},[8629],{"type":420,"value":432},{"type":415,"tag":532,"props":8631,"children":8632},{"style":656},[8633],{"type":420,"value":8485},{"type":415,"tag":532,"props":8635,"children":8636},{"style":551},[8637],{"type":420,"value":664},{"type":415,"tag":532,"props":8639,"children":8640},{"style":631},[8641],{"type":420,"value":8642},"s",{"type":415,"tag":532,"props":8644,"children":8645},{"style":551},[8646],{"type":420,"value":755},{"type":415,"tag":532,"props":8648,"children":8649},{"class":534,"line":566},[8650],{"type":415,"tag":532,"props":8651,"children":8652},{"style":551},[8653],{"type":420,"value":764},{"type":415,"tag":532,"props":8655,"children":8656},{"class":534,"line":583},[8657,8662,8667,8671,8675,8680,8684,8688],{"type":415,"tag":532,"props":8658,"children":8659},{"style":631},[8660],{"type":420,"value":8661},"    var",{"type":415,"tag":532,"props":8663,"children":8664},{"style":631},[8665],{"type":420,"value":8666}," armClient",{"type":415,"tag":532,"props":8668,"children":8669},{"style":551},[8670],{"type":420,"value":644},{"type":415,"tag":532,"props":8672,"children":8673},{"style":551},[8674],{"type":420,"value":3276},{"type":415,"tag":532,"props":8676,"children":8677},{"style":631},[8678],{"type":420,"value":8679}," ArmClient",{"type":415,"tag":532,"props":8681,"children":8682},{"style":551},[8683],{"type":420,"value":787},{"type":415,"tag":532,"props":8685,"children":8686},{"style":631},[8687],{"type":420,"value":842},{"type":415,"tag":532,"props":8689,"children":8690},{"style":551},[8691],{"type":420,"value":847},{"type":415,"tag":532,"props":8693,"children":8694},{"class":534,"line":617},[8695,8699,8704,8708,8712,8716,8721,8725,8730,8734,8739,8744,8749,8753,8757,8762,8767],{"type":415,"tag":532,"props":8696,"children":8697},{"style":631},[8698],{"type":420,"value":8661},{"type":415,"tag":532,"props":8700,"children":8701},{"style":631},[8702],{"type":420,"value":8703}," subscription",{"type":415,"tag":532,"props":8705,"children":8706},{"style":551},[8707],{"type":420,"value":644},{"type":415,"tag":532,"props":8709,"children":8710},{"style":545},[8711],{"type":420,"value":8666},{"type":415,"tag":532,"props":8713,"children":8714},{"style":551},[8715],{"type":420,"value":432},{"type":415,"tag":532,"props":8717,"children":8718},{"style":656},[8719],{"type":420,"value":8720},"GetSubscriptionResource",{"type":415,"tag":532,"props":8722,"children":8723},{"style":551},[8724],{"type":420,"value":787},{"type":415,"tag":532,"props":8726,"children":8727},{"style":631},[8728],{"type":420,"value":8729}," ResourceIdentifier",{"type":415,"tag":532,"props":8731,"children":8732},{"style":551},[8733],{"type":420,"value":664},{"type":415,"tag":532,"props":8735,"children":8736},{"style":551},[8737],{"type":420,"value":8738},"$\"",{"type":415,"tag":532,"props":8740,"children":8741},{"style":804},[8742],{"type":420,"value":8743},"/subscriptions/",{"type":415,"tag":532,"props":8745,"children":8746},{"style":551},[8747],{"type":420,"value":8748},"{",{"type":415,"tag":532,"props":8750,"children":8751},{"style":545},[8752],{"type":420,"value":8642},{"type":415,"tag":532,"props":8754,"children":8755},{"style":551},[8756],{"type":420,"value":4502},{"type":415,"tag":532,"props":8758,"children":8759},{"style":551},[8760],{"type":420,"value":8761},")).",{"type":415,"tag":532,"props":8763,"children":8764},{"style":656},[8765],{"type":420,"value":8766},"Get",{"type":415,"tag":532,"props":8768,"children":8769},{"style":551},[8770],{"type":420,"value":899},{"type":415,"tag":532,"props":8772,"children":8773},{"class":534,"line":627},[8774,8779,8783,8787,8791,8795,8800,8804,8809],{"type":415,"tag":532,"props":8775,"children":8776},{"style":1241},[8777],{"type":420,"value":8778},"    return",{"type":415,"tag":532,"props":8780,"children":8781},{"style":545},[8782],{"type":420,"value":8703},{"type":415,"tag":532,"props":8784,"children":8785},{"style":551},[8786],{"type":420,"value":432},{"type":415,"tag":532,"props":8788,"children":8789},{"style":545},[8790],{"type":420,"value":3259},{"type":415,"tag":532,"props":8792,"children":8793},{"style":551},[8794],{"type":420,"value":432},{"type":415,"tag":532,"props":8796,"children":8797},{"style":545},[8798],{"type":420,"value":8799},"Data",{"type":415,"tag":532,"props":8801,"children":8802},{"style":551},[8803],{"type":420,"value":432},{"type":415,"tag":532,"props":8805,"children":8806},{"style":545},[8807],{"type":420,"value":8808},"DisplayName",{"type":415,"tag":532,"props":8810,"children":8811},{"style":551},[8812],{"type":420,"value":563},{"type":415,"tag":532,"props":8814,"children":8815},{"class":534,"line":677},[8816],{"type":415,"tag":532,"props":8817,"children":8818},{"style":551},[8819],{"type":420,"value":856},{"type":415,"tag":3914,"props":8821,"children":8823},{"id":8822},"set-up-the-necessary-microsoft-entra-id-resources",[8824],{"type":420,"value":8825},"Set up the necessary Microsoft Entra ID resources",{"type":415,"tag":416,"props":8827,"children":8828},{},[8829],{"type":420,"value":8830},"We need to set up the following resources in Microsoft Entra ID:",{"type":415,"tag":508,"props":8832,"children":8833},{},[8834,8839,8844],{"type":415,"tag":512,"props":8835,"children":8836},{},[8837],{"type":420,"value":8838},"an Application that represents the Azure DevOps service connection identity",{"type":415,"tag":512,"props":8840,"children":8841},{},[8842],{"type":420,"value":8843},"a Service Principal (related to the application above) that has the contributor role on the Azure subscription",{"type":415,"tag":512,"props":8845,"children":8846},{},[8847],{"type":420,"value":8848},"credentials for the CI/CD pipeline to authenticate to Azure on behalf of this Microsoft Entra ID application",{"type":415,"tag":416,"props":8850,"children":8851},{},[8852],{"type":420,"value":8853},"Let's take care of the first 2 points:",{"type":415,"tag":523,"props":8855,"children":8857},{"className":525,"code":8856,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar aadApplication = new Application(\"ADOAzureReadyApp\", new()\n{\n    DisplayName = \"ADO Azure Ready App\"\n});\nvar servicePrincipal  = new ServicePrincipal(\"AzureReadyServicePrincipal\", new()\n{\n    ApplicationId = aadApplication.ApplicationId,\n});\n\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\nnew RoleAssignment(\"contributor\", new()\n{\n    PrincipalId= servicePrincipal.Id,\n    PrincipalType= PrincipalType.ServicePrincipal,\n    RoleDefinitionId = AzureBuiltInRoles.Contributor,\n    Scope = Output.Format($\"/subscriptions/{subscriptionId}\")\n});\n",[8858],{"type":415,"tag":468,"props":8859,"children":8860},{"__ignoreMap":401},[8861,8892,8942,8949,8974,8981,9031,9038,9066,9073,9080,9135,9173,9180,9208,9238,9268,9322],{"type":415,"tag":532,"props":8862,"children":8863},{"class":534,"line":535},[8864,8868,8872,8876,8880,8884,8888],{"type":415,"tag":532,"props":8865,"children":8866},{"style":631},[8867],{"type":420,"value":634},{"type":415,"tag":532,"props":8869,"children":8870},{"style":631},[8871],{"type":420,"value":8436},{"type":415,"tag":532,"props":8873,"children":8874},{"style":551},[8875],{"type":420,"value":644},{"type":415,"tag":532,"props":8877,"children":8878},{"style":545},[8879],{"type":420,"value":8445},{"type":415,"tag":532,"props":8881,"children":8882},{"style":551},[8883],{"type":420,"value":432},{"type":415,"tag":532,"props":8885,"children":8886},{"style":656},[8887],{"type":420,"value":7713},{"type":415,"tag":532,"props":8889,"children":8890},{"style":551},[8891],{"type":420,"value":899},{"type":415,"tag":532,"props":8893,"children":8894},{"class":534,"line":566},[8895,8899,8904,8908,8912,8917,8921,8925,8930,8934,8938],{"type":415,"tag":532,"props":8896,"children":8897},{"style":631},[8898],{"type":420,"value":634},{"type":415,"tag":532,"props":8900,"children":8901},{"style":631},[8902],{"type":420,"value":8903}," aadApplication",{"type":415,"tag":532,"props":8905,"children":8906},{"style":551},[8907],{"type":420,"value":644},{"type":415,"tag":532,"props":8909,"children":8910},{"style":551},[8911],{"type":420,"value":3276},{"type":415,"tag":532,"props":8913,"children":8914},{"style":631},[8915],{"type":420,"value":8916}," Application",{"type":415,"tag":532,"props":8918,"children":8919},{"style":551},[8920],{"type":420,"value":664},{"type":415,"tag":532,"props":8922,"children":8923},{"style":551},[8924],{"type":420,"value":801},{"type":415,"tag":532,"props":8926,"children":8927},{"style":804},[8928],{"type":420,"value":8929},"ADOAzureReadyApp",{"type":415,"tag":532,"props":8931,"children":8932},{"style":551},[8933],{"type":420,"value":801},{"type":415,"tag":532,"props":8935,"children":8936},{"style":551},[8937],{"type":420,"value":1099},{"type":415,"tag":532,"props":8939,"children":8940},{"style":551},[8941],{"type":420,"value":7363},{"type":415,"tag":532,"props":8943,"children":8944},{"class":534,"line":583},[8945],{"type":415,"tag":532,"props":8946,"children":8947},{"style":551},[8948],{"type":420,"value":764},{"type":415,"tag":532,"props":8950,"children":8951},{"class":534,"line":617},[8952,8957,8961,8965,8970],{"type":415,"tag":532,"props":8953,"children":8954},{"style":545},[8955],{"type":420,"value":8956},"    DisplayName ",{"type":415,"tag":532,"props":8958,"children":8959},{"style":551},[8960],{"type":420,"value":1134},{"type":415,"tag":532,"props":8962,"children":8963},{"style":551},[8964],{"type":420,"value":4041},{"type":415,"tag":532,"props":8966,"children":8967},{"style":804},[8968],{"type":420,"value":8969},"ADO Azure Ready App",{"type":415,"tag":532,"props":8971,"children":8972},{"style":551},[8973],{"type":420,"value":4051},{"type":415,"tag":532,"props":8975,"children":8976},{"class":534,"line":627},[8977],{"type":415,"tag":532,"props":8978,"children":8979},{"style":551},[8980],{"type":420,"value":856},{"type":415,"tag":532,"props":8982,"children":8983},{"class":534,"line":677},[8984,8988,8992,8997,9001,9006,9010,9014,9019,9023,9027],{"type":415,"tag":532,"props":8985,"children":8986},{"style":631},[8987],{"type":420,"value":634},{"type":415,"tag":532,"props":8989,"children":8990},{"style":631},[8991],{"type":420,"value":8377},{"type":415,"tag":532,"props":8993,"children":8994},{"style":551},[8995],{"type":420,"value":8996},"  =",{"type":415,"tag":532,"props":8998,"children":8999},{"style":551},[9000],{"type":420,"value":3276},{"type":415,"tag":532,"props":9002,"children":9003},{"style":631},[9004],{"type":420,"value":9005}," ServicePrincipal",{"type":415,"tag":532,"props":9007,"children":9008},{"style":551},[9009],{"type":420,"value":664},{"type":415,"tag":532,"props":9011,"children":9012},{"style":551},[9013],{"type":420,"value":801},{"type":415,"tag":532,"props":9015,"children":9016},{"style":804},[9017],{"type":420,"value":9018},"AzureReadyServicePrincipal",{"type":415,"tag":532,"props":9020,"children":9021},{"style":551},[9022],{"type":420,"value":801},{"type":415,"tag":532,"props":9024,"children":9025},{"style":551},[9026],{"type":420,"value":1099},{"type":415,"tag":532,"props":9028,"children":9029},{"style":551},[9030],{"type":420,"value":7363},{"type":415,"tag":532,"props":9032,"children":9033},{"class":534,"line":719},[9034],{"type":415,"tag":532,"props":9035,"children":9036},{"style":551},[9037],{"type":420,"value":764},{"type":415,"tag":532,"props":9039,"children":9040},{"class":534,"line":758},[9041,9046,9050,9054,9058,9062],{"type":415,"tag":532,"props":9042,"children":9043},{"style":545},[9044],{"type":420,"value":9045},"    ApplicationId ",{"type":415,"tag":532,"props":9047,"children":9048},{"style":551},[9049],{"type":420,"value":1134},{"type":415,"tag":532,"props":9051,"children":9052},{"style":545},[9053],{"type":420,"value":8903},{"type":415,"tag":532,"props":9055,"children":9056},{"style":551},[9057],{"type":420,"value":432},{"type":415,"tag":532,"props":9059,"children":9060},{"style":545},[9061],{"type":420,"value":8386},{"type":415,"tag":532,"props":9063,"children":9064},{"style":551},[9065],{"type":420,"value":7400},{"type":415,"tag":532,"props":9067,"children":9068},{"class":534,"line":767},[9069],{"type":415,"tag":532,"props":9070,"children":9071},{"style":551},[9072],{"type":420,"value":856},{"type":415,"tag":532,"props":9074,"children":9075},{"class":534,"line":819},[9076],{"type":415,"tag":532,"props":9077,"children":9078},{"emptyLinePlaceholder":621},[9079],{"type":420,"value":624},{"type":415,"tag":532,"props":9081,"children":9082},{"class":534,"line":850},[9083,9087,9091,9095,9099,9103,9107,9111,9115,9119,9123,9127,9131],{"type":415,"tag":532,"props":9084,"children":9085},{"style":631},[9086],{"type":420,"value":634},{"type":415,"tag":532,"props":9088,"children":9089},{"style":631},[9090],{"type":420,"value":8303},{"type":415,"tag":532,"props":9092,"children":9093},{"style":551},[9094],{"type":420,"value":644},{"type":415,"tag":532,"props":9096,"children":9097},{"style":545},[9098],{"type":420,"value":8436},{"type":415,"tag":532,"props":9100,"children":9101},{"style":551},[9102],{"type":420,"value":432},{"type":415,"tag":532,"props":9104,"children":9105},{"style":656},[9106],{"type":420,"value":8485},{"type":415,"tag":532,"props":9108,"children":9109},{"style":551},[9110],{"type":420,"value":664},{"type":415,"tag":532,"props":9112,"children":9113},{"style":631},[9114],{"type":420,"value":8494},{"type":415,"tag":532,"props":9116,"children":9117},{"style":551},[9118],{"type":420,"value":8499},{"type":415,"tag":532,"props":9120,"children":9121},{"style":545},[9122],{"type":420,"value":8504},{"type":415,"tag":532,"props":9124,"children":9125},{"style":551},[9126],{"type":420,"value":432},{"type":415,"tag":532,"props":9128,"children":9129},{"style":545},[9130],{"type":420,"value":8568},{"type":415,"tag":532,"props":9132,"children":9133},{"style":551},[9134],{"type":420,"value":674},{"type":415,"tag":532,"props":9136,"children":9137},{"class":534,"line":859},[9138,9143,9148,9152,9156,9161,9165,9169],{"type":415,"tag":532,"props":9139,"children":9140},{"style":954},[9141],{"type":420,"value":9142},"new",{"type":415,"tag":532,"props":9144,"children":9145},{"style":656},[9146],{"type":420,"value":9147}," RoleAssignment",{"type":415,"tag":532,"props":9149,"children":9150},{"style":551},[9151],{"type":420,"value":664},{"type":415,"tag":532,"props":9153,"children":9154},{"style":551},[9155],{"type":420,"value":801},{"type":415,"tag":532,"props":9157,"children":9158},{"style":804},[9159],{"type":420,"value":9160},"contributor",{"type":415,"tag":532,"props":9162,"children":9163},{"style":551},[9164],{"type":420,"value":801},{"type":415,"tag":532,"props":9166,"children":9167},{"style":551},[9168],{"type":420,"value":1099},{"type":415,"tag":532,"props":9170,"children":9171},{"style":551},[9172],{"type":420,"value":7363},{"type":415,"tag":532,"props":9174,"children":9175},{"class":534,"line":867},[9176],{"type":415,"tag":532,"props":9177,"children":9178},{"style":551},[9179],{"type":420,"value":764},{"type":415,"tag":532,"props":9181,"children":9182},{"class":534,"line":902},[9183,9188,9192,9196,9200,9204],{"type":415,"tag":532,"props":9184,"children":9185},{"style":545},[9186],{"type":420,"value":9187},"    PrincipalId",{"type":415,"tag":532,"props":9189,"children":9190},{"style":551},[9191],{"type":420,"value":1134},{"type":415,"tag":532,"props":9193,"children":9194},{"style":545},[9195],{"type":420,"value":8377},{"type":415,"tag":532,"props":9197,"children":9198},{"style":551},[9199],{"type":420,"value":432},{"type":415,"tag":532,"props":9201,"children":9202},{"style":545},[9203],{"type":420,"value":7750},{"type":415,"tag":532,"props":9205,"children":9206},{"style":551},[9207],{"type":420,"value":7400},{"type":415,"tag":532,"props":9209,"children":9210},{"class":534,"line":1302},[9211,9216,9220,9225,9229,9234],{"type":415,"tag":532,"props":9212,"children":9213},{"style":545},[9214],{"type":420,"value":9215},"    PrincipalType",{"type":415,"tag":532,"props":9217,"children":9218},{"style":551},[9219],{"type":420,"value":1134},{"type":415,"tag":532,"props":9221,"children":9222},{"style":545},[9223],{"type":420,"value":9224}," PrincipalType",{"type":415,"tag":532,"props":9226,"children":9227},{"style":551},[9228],{"type":420,"value":432},{"type":415,"tag":532,"props":9230,"children":9231},{"style":545},[9232],{"type":420,"value":9233},"ServicePrincipal",{"type":415,"tag":532,"props":9235,"children":9236},{"style":551},[9237],{"type":420,"value":7400},{"type":415,"tag":532,"props":9239,"children":9240},{"class":534,"line":1311},[9241,9246,9250,9255,9259,9264],{"type":415,"tag":532,"props":9242,"children":9243},{"style":545},[9244],{"type":420,"value":9245},"    RoleDefinitionId ",{"type":415,"tag":532,"props":9247,"children":9248},{"style":551},[9249],{"type":420,"value":1134},{"type":415,"tag":532,"props":9251,"children":9252},{"style":545},[9253],{"type":420,"value":9254}," AzureBuiltInRoles",{"type":415,"tag":532,"props":9256,"children":9257},{"style":551},[9258],{"type":420,"value":432},{"type":415,"tag":532,"props":9260,"children":9261},{"style":545},[9262],{"type":420,"value":9263},"Contributor",{"type":415,"tag":532,"props":9265,"children":9266},{"style":551},[9267],{"type":420,"value":7400},{"type":415,"tag":532,"props":9269,"children":9270},{"class":534,"line":1356},[9271,9276,9280,9285,9289,9294,9298,9302,9306,9310,9314,9318],{"type":415,"tag":532,"props":9272,"children":9273},{"style":545},[9274],{"type":420,"value":9275},"    Scope ",{"type":415,"tag":532,"props":9277,"children":9278},{"style":551},[9279],{"type":420,"value":1134},{"type":415,"tag":532,"props":9281,"children":9282},{"style":545},[9283],{"type":420,"value":9284}," Output",{"type":415,"tag":532,"props":9286,"children":9287},{"style":551},[9288],{"type":420,"value":432},{"type":415,"tag":532,"props":9290,"children":9291},{"style":656},[9292],{"type":420,"value":9293},"Format",{"type":415,"tag":532,"props":9295,"children":9296},{"style":551},[9297],{"type":420,"value":664},{"type":415,"tag":532,"props":9299,"children":9300},{"style":551},[9301],{"type":420,"value":8738},{"type":415,"tag":532,"props":9303,"children":9304},{"style":804},[9305],{"type":420,"value":8743},{"type":415,"tag":532,"props":9307,"children":9308},{"style":551},[9309],{"type":420,"value":8748},{"type":415,"tag":532,"props":9311,"children":9312},{"style":545},[9313],{"type":420,"value":4299},{"type":415,"tag":532,"props":9315,"children":9316},{"style":551},[9317],{"type":420,"value":4502},{"type":415,"tag":532,"props":9319,"children":9320},{"style":551},[9321],{"type":420,"value":1113},{"type":415,"tag":532,"props":9323,"children":9324},{"class":534,"line":1365},[9325],{"type":415,"tag":532,"props":9326,"children":9327},{"style":551},[9328],{"type":420,"value":856},{"type":415,"tag":434,"props":9330,"children":9331},{"icon":6841},[9332],{"type":415,"tag":416,"props":9333,"children":9334},{},[9335,9337],{"type":420,"value":9336},"It's worth mentioning that using an Application and its associated Service Principal is not the only way to proceed, we could have created instead a ",{"type":415,"tag":423,"props":9338,"children":9341},{"href":9339,"rel":9340},"https://www.pulumi.com/registry/packages/azure-native/api-docs/managedidentity/userassignedidentity/",[427],[9342],{"type":420,"value":9343},"User Assigned Identity",{"type":415,"tag":416,"props":9345,"children":9346},{},[9347],{"type":420,"value":9348},"Now that everything is created, we can create the Federated identity credentials:",{"type":415,"tag":523,"props":9350,"children":9352},{"className":525,"code":9351,"language":326,"meta":401,"style":401},"new ApplicationFederatedIdentityCredential(\"ADOAzureReadyAppFederatedIdentityCredential\", new() \n{\n    ApplicationObjectId = aadApplication.ObjectId,\n    DisplayName = \"AzureReadyDeploys\",\n    Description = \"Deployments for azure-ready-repository\",\n    Audiences = new(){\"api://AzureADTokenExchange\" },\n    Issuer = serviceConnection.WorkloadIdentityFederationIssuer,\n    Subject = Output.Format($\"sc://{organisationName}/{project.Name}/{serviceConnection.ServiceEndpointName}\")\n});\n",[9353],{"type":415,"tag":468,"props":9354,"children":9355},{"__ignoreMap":401},[9356,9398,9405,9434,9462,9490,9524,9553,9658],{"type":415,"tag":532,"props":9357,"children":9358},{"class":534,"line":535},[9359,9363,9368,9372,9376,9381,9385,9389,9394],{"type":415,"tag":532,"props":9360,"children":9361},{"style":954},[9362],{"type":420,"value":9142},{"type":415,"tag":532,"props":9364,"children":9365},{"style":656},[9366],{"type":420,"value":9367}," ApplicationFederatedIdentityCredential",{"type":415,"tag":532,"props":9369,"children":9370},{"style":551},[9371],{"type":420,"value":664},{"type":415,"tag":532,"props":9373,"children":9374},{"style":551},[9375],{"type":420,"value":801},{"type":415,"tag":532,"props":9377,"children":9378},{"style":804},[9379],{"type":420,"value":9380},"ADOAzureReadyAppFederatedIdentityCredential",{"type":415,"tag":532,"props":9382,"children":9383},{"style":551},[9384],{"type":420,"value":801},{"type":415,"tag":532,"props":9386,"children":9387},{"style":551},[9388],{"type":420,"value":1099},{"type":415,"tag":532,"props":9390,"children":9391},{"style":551},[9392],{"type":420,"value":9393}," new()",{"type":415,"tag":532,"props":9395,"children":9396},{"style":545},[9397],{"type":420,"value":5637},{"type":415,"tag":532,"props":9399,"children":9400},{"class":534,"line":566},[9401],{"type":415,"tag":532,"props":9402,"children":9403},{"style":551},[9404],{"type":420,"value":764},{"type":415,"tag":532,"props":9406,"children":9407},{"class":534,"line":583},[9408,9413,9417,9421,9425,9430],{"type":415,"tag":532,"props":9409,"children":9410},{"style":545},[9411],{"type":420,"value":9412},"    ApplicationObjectId ",{"type":415,"tag":532,"props":9414,"children":9415},{"style":551},[9416],{"type":420,"value":1134},{"type":415,"tag":532,"props":9418,"children":9419},{"style":545},[9420],{"type":420,"value":8903},{"type":415,"tag":532,"props":9422,"children":9423},{"style":551},[9424],{"type":420,"value":432},{"type":415,"tag":532,"props":9426,"children":9427},{"style":545},[9428],{"type":420,"value":9429},"ObjectId",{"type":415,"tag":532,"props":9431,"children":9432},{"style":551},[9433],{"type":420,"value":7400},{"type":415,"tag":532,"props":9435,"children":9436},{"class":534,"line":617},[9437,9441,9445,9449,9454,9458],{"type":415,"tag":532,"props":9438,"children":9439},{"style":545},[9440],{"type":420,"value":8956},{"type":415,"tag":532,"props":9442,"children":9443},{"style":551},[9444],{"type":420,"value":1134},{"type":415,"tag":532,"props":9446,"children":9447},{"style":551},[9448],{"type":420,"value":4041},{"type":415,"tag":532,"props":9450,"children":9451},{"style":804},[9452],{"type":420,"value":9453},"AzureReadyDeploys",{"type":415,"tag":532,"props":9455,"children":9456},{"style":551},[9457],{"type":420,"value":801},{"type":415,"tag":532,"props":9459,"children":9460},{"style":551},[9461],{"type":420,"value":7400},{"type":415,"tag":532,"props":9463,"children":9464},{"class":534,"line":627},[9465,9469,9473,9477,9482,9486],{"type":415,"tag":532,"props":9466,"children":9467},{"style":545},[9468],{"type":420,"value":7378},{"type":415,"tag":532,"props":9470,"children":9471},{"style":551},[9472],{"type":420,"value":1134},{"type":415,"tag":532,"props":9474,"children":9475},{"style":551},[9476],{"type":420,"value":4041},{"type":415,"tag":532,"props":9478,"children":9479},{"style":804},[9480],{"type":420,"value":9481},"Deployments for azure-ready-repository",{"type":415,"tag":532,"props":9483,"children":9484},{"style":551},[9485],{"type":420,"value":801},{"type":415,"tag":532,"props":9487,"children":9488},{"style":551},[9489],{"type":420,"value":7400},{"type":415,"tag":532,"props":9491,"children":9492},{"class":534,"line":677},[9493,9498,9502,9507,9511,9515,9519],{"type":415,"tag":532,"props":9494,"children":9495},{"style":545},[9496],{"type":420,"value":9497},"    Audiences ",{"type":415,"tag":532,"props":9499,"children":9500},{"style":551},[9501],{"type":420,"value":1134},{"type":415,"tag":532,"props":9503,"children":9504},{"style":551},[9505],{"type":420,"value":9506}," new(){",{"type":415,"tag":532,"props":9508,"children":9509},{"style":551},[9510],{"type":420,"value":801},{"type":415,"tag":532,"props":9512,"children":9513},{"style":804},[9514],{"type":420,"value":4941},{"type":415,"tag":532,"props":9516,"children":9517},{"style":551},[9518],{"type":420,"value":801},{"type":415,"tag":532,"props":9520,"children":9521},{"style":551},[9522],{"type":420,"value":9523}," },\n",{"type":415,"tag":532,"props":9525,"children":9526},{"class":534,"line":719},[9527,9532,9536,9540,9544,9549],{"type":415,"tag":532,"props":9528,"children":9529},{"style":545},[9530],{"type":420,"value":9531},"    Issuer ",{"type":415,"tag":532,"props":9533,"children":9534},{"style":551},[9535],{"type":420,"value":1134},{"type":415,"tag":532,"props":9537,"children":9538},{"style":545},[9539],{"type":420,"value":8135},{"type":415,"tag":532,"props":9541,"children":9542},{"style":551},[9543],{"type":420,"value":432},{"type":415,"tag":532,"props":9545,"children":9546},{"style":545},[9547],{"type":420,"value":9548},"WorkloadIdentityFederationIssuer",{"type":415,"tag":532,"props":9550,"children":9551},{"style":551},[9552],{"type":420,"value":7400},{"type":415,"tag":532,"props":9554,"children":9555},{"class":534,"line":758},[9556,9561,9565,9569,9573,9577,9581,9585,9590,9594,9599,9603,9607,9611,9616,9620,9624,9628,9632,9636,9641,9645,9650,9654],{"type":415,"tag":532,"props":9557,"children":9558},{"style":545},[9559],{"type":420,"value":9560},"    Subject ",{"type":415,"tag":532,"props":9562,"children":9563},{"style":551},[9564],{"type":420,"value":1134},{"type":415,"tag":532,"props":9566,"children":9567},{"style":545},[9568],{"type":420,"value":9284},{"type":415,"tag":532,"props":9570,"children":9571},{"style":551},[9572],{"type":420,"value":432},{"type":415,"tag":532,"props":9574,"children":9575},{"style":656},[9576],{"type":420,"value":9293},{"type":415,"tag":532,"props":9578,"children":9579},{"style":551},[9580],{"type":420,"value":664},{"type":415,"tag":532,"props":9582,"children":9583},{"style":551},[9584],{"type":420,"value":8738},{"type":415,"tag":532,"props":9586,"children":9587},{"style":804},[9588],{"type":420,"value":9589},"sc://",{"type":415,"tag":532,"props":9591,"children":9592},{"style":551},[9593],{"type":420,"value":8748},{"type":415,"tag":532,"props":9595,"children":9596},{"style":545},[9597],{"type":420,"value":9598},"organisationName",{"type":415,"tag":532,"props":9600,"children":9601},{"style":551},[9602],{"type":420,"value":4864},{"type":415,"tag":532,"props":9604,"children":9605},{"style":804},[9606],{"type":420,"value":4728},{"type":415,"tag":532,"props":9608,"children":9609},{"style":551},[9610],{"type":420,"value":8748},{"type":415,"tag":532,"props":9612,"children":9613},{"style":545},[9614],{"type":420,"value":9615},"project",{"type":415,"tag":532,"props":9617,"children":9618},{"style":551},[9619],{"type":420,"value":432},{"type":415,"tag":532,"props":9621,"children":9622},{"style":545},[9623],{"type":420,"value":1344},{"type":415,"tag":532,"props":9625,"children":9626},{"style":551},[9627],{"type":420,"value":4864},{"type":415,"tag":532,"props":9629,"children":9630},{"style":804},[9631],{"type":420,"value":4728},{"type":415,"tag":532,"props":9633,"children":9634},{"style":551},[9635],{"type":420,"value":8748},{"type":415,"tag":532,"props":9637,"children":9638},{"style":545},[9639],{"type":420,"value":9640},"serviceConnection",{"type":415,"tag":532,"props":9642,"children":9643},{"style":551},[9644],{"type":420,"value":432},{"type":415,"tag":532,"props":9646,"children":9647},{"style":545},[9648],{"type":420,"value":9649},"ServiceEndpointName",{"type":415,"tag":532,"props":9651,"children":9652},{"style":551},[9653],{"type":420,"value":4502},{"type":415,"tag":532,"props":9655,"children":9656},{"style":551},[9657],{"type":420,"value":1113},{"type":415,"tag":532,"props":9659,"children":9660},{"class":534,"line":767},[9661],{"type":415,"tag":532,"props":9662,"children":9663},{"style":551},[9664],{"type":420,"value":856},{"type":415,"tag":416,"props":9666,"children":9667},{},[9668,9670,9676],{"type":420,"value":9669},"You can observe that the federation subject adheres to a particular format (",{"type":415,"tag":468,"props":9671,"children":9673},{"className":9672},[],[9674],{"type":420,"value":9675},"sc://\u003Corg>/\u003Cproject>/\u003Cservice connection name>",{"type":420,"value":9677},"), which identifies the service connection authorized for authentication with Azure.",{"type":415,"tag":3914,"props":9679,"children":9681},{"id":9680},"create-the-deployment-pipeline",[9682],{"type":420,"value":9683},"Create the deployment pipeline",{"type":415,"tag":416,"props":9685,"children":9686},{},[9687],{"type":420,"value":9688},"We have completed the configuration of an ARM Service Connection that employs Workload Identity Federation for authentication with Azure. While we could stop at this point, it would be nice to automate the creation of a pipeline that utilizes this service connection and seize the opportunity to ensure everything works properly.",{"type":415,"tag":416,"props":9690,"children":9691},{},[9692,9694,9700],{"type":420,"value":9693},"For this purpose, I have written a very simple YAML pipeline that runs the ",{"type":415,"tag":468,"props":9695,"children":9697},{"className":9696},[],[9698],{"type":420,"value":9699},"AzureCLI",{"type":420,"value":9701}," task to show information about the Azure subscription associated with the previously created service connection.",{"type":415,"tag":523,"props":9703,"children":9705},{"className":525,"code":9704,"language":326,"meta":401,"style":401},"trigger:\n  - main\n\npool:\n  vmImage: ubuntu-latest\n\nsteps:\n  - task: AzureCLI@2\n    inputs:\n      azureSubscription: 'azure-with-oidc'\n      scriptType: 'pscore'\n      scriptLocation: 'inlineScript'\n      inlineScript: 'az account show --query id -o tsv'\n",[9706],{"type":415,"tag":468,"props":9707,"children":9708},{"__ignoreMap":401},[9709,9721,9734,9741,9753,9779,9786,9798,9824,9836,9860,9885,9910],{"type":415,"tag":532,"props":9710,"children":9711},{"class":534,"line":535},[9712,9717],{"type":415,"tag":532,"props":9713,"children":9714},{"style":631},[9715],{"type":420,"value":9716},"trigger",{"type":415,"tag":532,"props":9718,"children":9719},{"style":551},[9720],{"type":420,"value":3557},{"type":415,"tag":532,"props":9722,"children":9723},{"class":534,"line":566},[9724,9729],{"type":415,"tag":532,"props":9725,"children":9726},{"style":551},[9727],{"type":420,"value":9728},"  -",{"type":415,"tag":532,"props":9730,"children":9731},{"style":545},[9732],{"type":420,"value":9733}," main\n",{"type":415,"tag":532,"props":9735,"children":9736},{"class":534,"line":583},[9737],{"type":415,"tag":532,"props":9738,"children":9739},{"emptyLinePlaceholder":621},[9740],{"type":420,"value":624},{"type":415,"tag":532,"props":9742,"children":9743},{"class":534,"line":617},[9744,9749],{"type":415,"tag":532,"props":9745,"children":9746},{"style":631},[9747],{"type":420,"value":9748},"pool",{"type":415,"tag":532,"props":9750,"children":9751},{"style":551},[9752],{"type":420,"value":3557},{"type":415,"tag":532,"props":9754,"children":9755},{"class":534,"line":627},[9756,9761,9765,9770,9774],{"type":415,"tag":532,"props":9757,"children":9758},{"style":631},[9759],{"type":420,"value":9760},"  vmImage",{"type":415,"tag":532,"props":9762,"children":9763},{"style":551},[9764],{"type":420,"value":1290},{"type":415,"tag":532,"props":9766,"children":9767},{"style":545},[9768],{"type":420,"value":9769}," ubuntu",{"type":415,"tag":532,"props":9771,"children":9772},{"style":551},[9773],{"type":420,"value":4216},{"type":415,"tag":532,"props":9775,"children":9776},{"style":545},[9777],{"type":420,"value":9778},"latest\n",{"type":415,"tag":532,"props":9780,"children":9781},{"class":534,"line":677},[9782],{"type":415,"tag":532,"props":9783,"children":9784},{"emptyLinePlaceholder":621},[9785],{"type":420,"value":624},{"type":415,"tag":532,"props":9787,"children":9788},{"class":534,"line":719},[9789,9794],{"type":415,"tag":532,"props":9790,"children":9791},{"style":631},[9792],{"type":420,"value":9793},"steps",{"type":415,"tag":532,"props":9795,"children":9796},{"style":551},[9797],{"type":420,"value":3557},{"type":415,"tag":532,"props":9799,"children":9800},{"class":534,"line":758},[9801,9805,9810,9814,9819],{"type":415,"tag":532,"props":9802,"children":9803},{"style":551},[9804],{"type":420,"value":9728},{"type":415,"tag":532,"props":9806,"children":9807},{"style":631},[9808],{"type":420,"value":9809}," task",{"type":415,"tag":532,"props":9811,"children":9812},{"style":551},[9813],{"type":420,"value":1290},{"type":415,"tag":532,"props":9815,"children":9816},{"style":545},[9817],{"type":420,"value":9818}," AzureCLI@",{"type":415,"tag":532,"props":9820,"children":9821},{"style":539},[9822],{"type":420,"value":9823},"2\n",{"type":415,"tag":532,"props":9825,"children":9826},{"class":534,"line":767},[9827,9832],{"type":415,"tag":532,"props":9828,"children":9829},{"style":631},[9830],{"type":420,"value":9831},"    inputs",{"type":415,"tag":532,"props":9833,"children":9834},{"style":551},[9835],{"type":420,"value":3557},{"type":415,"tag":532,"props":9837,"children":9838},{"class":534,"line":819},[9839,9844,9848,9852,9856],{"type":415,"tag":532,"props":9840,"children":9841},{"style":631},[9842],{"type":420,"value":9843},"      azureSubscription",{"type":415,"tag":532,"props":9845,"children":9846},{"style":551},[9847],{"type":420,"value":1290},{"type":415,"tag":532,"props":9849,"children":9850},{"style":551},[9851],{"type":420,"value":3697},{"type":415,"tag":532,"props":9853,"children":9854},{"style":804},[9855],{"type":420,"value":8228},{"type":415,"tag":532,"props":9857,"children":9858},{"style":551},[9859],{"type":420,"value":3707},{"type":415,"tag":532,"props":9861,"children":9862},{"class":534,"line":850},[9863,9868,9872,9876,9881],{"type":415,"tag":532,"props":9864,"children":9865},{"style":631},[9866],{"type":420,"value":9867},"      scriptType",{"type":415,"tag":532,"props":9869,"children":9870},{"style":551},[9871],{"type":420,"value":1290},{"type":415,"tag":532,"props":9873,"children":9874},{"style":551},[9875],{"type":420,"value":3697},{"type":415,"tag":532,"props":9877,"children":9878},{"style":804},[9879],{"type":420,"value":9880},"pscore",{"type":415,"tag":532,"props":9882,"children":9883},{"style":551},[9884],{"type":420,"value":3707},{"type":415,"tag":532,"props":9886,"children":9887},{"class":534,"line":859},[9888,9893,9897,9901,9906],{"type":415,"tag":532,"props":9889,"children":9890},{"style":631},[9891],{"type":420,"value":9892},"      scriptLocation",{"type":415,"tag":532,"props":9894,"children":9895},{"style":551},[9896],{"type":420,"value":1290},{"type":415,"tag":532,"props":9898,"children":9899},{"style":551},[9900],{"type":420,"value":3697},{"type":415,"tag":532,"props":9902,"children":9903},{"style":804},[9904],{"type":420,"value":9905},"inlineScript",{"type":415,"tag":532,"props":9907,"children":9908},{"style":551},[9909],{"type":420,"value":3707},{"type":415,"tag":532,"props":9911,"children":9912},{"class":534,"line":867},[9913,9918,9922,9926,9931],{"type":415,"tag":532,"props":9914,"children":9915},{"style":631},[9916],{"type":420,"value":9917},"      inlineScript",{"type":415,"tag":532,"props":9919,"children":9920},{"style":551},[9921],{"type":420,"value":1290},{"type":415,"tag":532,"props":9923,"children":9924},{"style":551},[9925],{"type":420,"value":3697},{"type":415,"tag":532,"props":9927,"children":9928},{"style":804},[9929],{"type":420,"value":9930},"az account show --query id -o tsv",{"type":415,"tag":532,"props":9932,"children":9933},{"style":551},[9934],{"type":420,"value":3707},{"type":415,"tag":416,"props":9936,"children":9937},{},[9938],{"type":420,"value":9939},"We can add this file in the Git repository:",{"type":415,"tag":523,"props":9941,"children":9943},{"className":525,"code":9942,"language":326,"meta":401,"style":401},"var pipelineFile = new GitRepositoryFile(\"AzurePipeline\", new()\n{\n    File = \"azure-pipelines.yaml\",\n    RepositoryId = repository.Apply(r => r.Id),\n    CommitMessage = \"Add preconfigured pipeline file\",\n    Content = File.ReadAllText(\"azure-pipelines.yml\"),\n    Branch = \"refs/heads/main\"\n});\n",[9944],{"type":415,"tag":468,"props":9945,"children":9946},{"__ignoreMap":401},[9947,9997,10004,10033,10088,10117,10164,10188],{"type":415,"tag":532,"props":9948,"children":9949},{"class":534,"line":535},[9950,9954,9959,9963,9967,9972,9976,9980,9985,9989,9993],{"type":415,"tag":532,"props":9951,"children":9952},{"style":631},[9953],{"type":420,"value":634},{"type":415,"tag":532,"props":9955,"children":9956},{"style":631},[9957],{"type":420,"value":9958}," pipelineFile",{"type":415,"tag":532,"props":9960,"children":9961},{"style":551},[9962],{"type":420,"value":644},{"type":415,"tag":532,"props":9964,"children":9965},{"style":551},[9966],{"type":420,"value":3276},{"type":415,"tag":532,"props":9968,"children":9969},{"style":631},[9970],{"type":420,"value":9971}," GitRepositoryFile",{"type":415,"tag":532,"props":9973,"children":9974},{"style":551},[9975],{"type":420,"value":664},{"type":415,"tag":532,"props":9977,"children":9978},{"style":551},[9979],{"type":420,"value":801},{"type":415,"tag":532,"props":9981,"children":9982},{"style":804},[9983],{"type":420,"value":9984},"AzurePipeline",{"type":415,"tag":532,"props":9986,"children":9987},{"style":551},[9988],{"type":420,"value":801},{"type":415,"tag":532,"props":9990,"children":9991},{"style":551},[9992],{"type":420,"value":1099},{"type":415,"tag":532,"props":9994,"children":9995},{"style":551},[9996],{"type":420,"value":7363},{"type":415,"tag":532,"props":9998,"children":9999},{"class":534,"line":566},[10000],{"type":415,"tag":532,"props":10001,"children":10002},{"style":551},[10003],{"type":420,"value":764},{"type":415,"tag":532,"props":10005,"children":10006},{"class":534,"line":583},[10007,10012,10016,10020,10025,10029],{"type":415,"tag":532,"props":10008,"children":10009},{"style":545},[10010],{"type":420,"value":10011},"    File ",{"type":415,"tag":532,"props":10013,"children":10014},{"style":551},[10015],{"type":420,"value":1134},{"type":415,"tag":532,"props":10017,"children":10018},{"style":551},[10019],{"type":420,"value":4041},{"type":415,"tag":532,"props":10021,"children":10022},{"style":804},[10023],{"type":420,"value":10024},"azure-pipelines.yaml",{"type":415,"tag":532,"props":10026,"children":10027},{"style":551},[10028],{"type":420,"value":801},{"type":415,"tag":532,"props":10030,"children":10031},{"style":551},[10032],{"type":420,"value":7400},{"type":415,"tag":532,"props":10034,"children":10035},{"class":534,"line":617},[10036,10041,10045,10049,10053,10057,10061,10066,10070,10075,10079,10083],{"type":415,"tag":532,"props":10037,"children":10038},{"style":545},[10039],{"type":420,"value":10040},"    RepositoryId ",{"type":415,"tag":532,"props":10042,"children":10043},{"style":551},[10044],{"type":420,"value":1134},{"type":415,"tag":532,"props":10046,"children":10047},{"style":545},[10048],{"type":420,"value":7695},{"type":415,"tag":532,"props":10050,"children":10051},{"style":551},[10052],{"type":420,"value":432},{"type":415,"tag":532,"props":10054,"children":10055},{"style":656},[10056],{"type":420,"value":8485},{"type":415,"tag":532,"props":10058,"children":10059},{"style":551},[10060],{"type":420,"value":664},{"type":415,"tag":532,"props":10062,"children":10063},{"style":631},[10064],{"type":420,"value":10065},"r",{"type":415,"tag":532,"props":10067,"children":10068},{"style":551},[10069],{"type":420,"value":8499},{"type":415,"tag":532,"props":10071,"children":10072},{"style":545},[10073],{"type":420,"value":10074}," r",{"type":415,"tag":532,"props":10076,"children":10077},{"style":551},[10078],{"type":420,"value":432},{"type":415,"tag":532,"props":10080,"children":10081},{"style":545},[10082],{"type":420,"value":7750},{"type":415,"tag":532,"props":10084,"children":10085},{"style":551},[10086],{"type":420,"value":10087},"),\n",{"type":415,"tag":532,"props":10089,"children":10090},{"class":534,"line":627},[10091,10096,10100,10104,10109,10113],{"type":415,"tag":532,"props":10092,"children":10093},{"style":545},[10094],{"type":420,"value":10095},"    CommitMessage ",{"type":415,"tag":532,"props":10097,"children":10098},{"style":551},[10099],{"type":420,"value":1134},{"type":415,"tag":532,"props":10101,"children":10102},{"style":551},[10103],{"type":420,"value":4041},{"type":415,"tag":532,"props":10105,"children":10106},{"style":804},[10107],{"type":420,"value":10108},"Add preconfigured pipeline file",{"type":415,"tag":532,"props":10110,"children":10111},{"style":551},[10112],{"type":420,"value":801},{"type":415,"tag":532,"props":10114,"children":10115},{"style":551},[10116],{"type":420,"value":7400},{"type":415,"tag":532,"props":10118,"children":10119},{"class":534,"line":677},[10120,10125,10129,10134,10138,10143,10147,10151,10156,10160],{"type":415,"tag":532,"props":10121,"children":10122},{"style":545},[10123],{"type":420,"value":10124},"    Content ",{"type":415,"tag":532,"props":10126,"children":10127},{"style":551},[10128],{"type":420,"value":1134},{"type":415,"tag":532,"props":10130,"children":10131},{"style":545},[10132],{"type":420,"value":10133}," File",{"type":415,"tag":532,"props":10135,"children":10136},{"style":551},[10137],{"type":420,"value":432},{"type":415,"tag":532,"props":10139,"children":10140},{"style":656},[10141],{"type":420,"value":10142},"ReadAllText",{"type":415,"tag":532,"props":10144,"children":10145},{"style":551},[10146],{"type":420,"value":664},{"type":415,"tag":532,"props":10148,"children":10149},{"style":551},[10150],{"type":420,"value":801},{"type":415,"tag":532,"props":10152,"children":10153},{"style":804},[10154],{"type":420,"value":10155},"azure-pipelines.yml",{"type":415,"tag":532,"props":10157,"children":10158},{"style":551},[10159],{"type":420,"value":801},{"type":415,"tag":532,"props":10161,"children":10162},{"style":551},[10163],{"type":420,"value":10087},{"type":415,"tag":532,"props":10165,"children":10166},{"class":534,"line":719},[10167,10172,10176,10180,10184],{"type":415,"tag":532,"props":10168,"children":10169},{"style":545},[10170],{"type":420,"value":10171},"    Branch ",{"type":415,"tag":532,"props":10173,"children":10174},{"style":551},[10175],{"type":420,"value":1134},{"type":415,"tag":532,"props":10177,"children":10178},{"style":551},[10179],{"type":420,"value":4041},{"type":415,"tag":532,"props":10181,"children":10182},{"style":804},[10183],{"type":420,"value":8046},{"type":415,"tag":532,"props":10185,"children":10186},{"style":551},[10187],{"type":420,"value":4051},{"type":415,"tag":532,"props":10189,"children":10190},{"class":534,"line":758},[10191],{"type":415,"tag":532,"props":10192,"children":10193},{"style":551},[10194],{"type":420,"value":856},{"type":415,"tag":416,"props":10196,"children":10197},{},[10198],{"type":420,"value":10199},"Now, we have to create the pipeline itself:",{"type":415,"tag":523,"props":10201,"children":10203},{"className":525,"code":10202,"language":326,"meta":401,"style":401},"var pipeline = new BuildDefinition(\"deployToAzure\", new()\n{\n    ProjectId = project.Id,\n    Repository = new BuildDefinitionRepositoryArgs()\n    {\n        RepoId = repository.Apply(r => r.Id),\n        BranchName = \"refs/heads/main\",\n        YmlPath = pipelineFile.File,\n        RepoType = \"TfsGit\"\n    }\n});\n",[10204],{"type":415,"tag":468,"props":10205,"children":10206},{"__ignoreMap":401},[10207,10257,10264,10291,10316,10323,10375,10403,10432,10457,10464],{"type":415,"tag":532,"props":10208,"children":10209},{"class":534,"line":535},[10210,10214,10219,10223,10227,10232,10236,10240,10245,10249,10253],{"type":415,"tag":532,"props":10211,"children":10212},{"style":631},[10213],{"type":420,"value":634},{"type":415,"tag":532,"props":10215,"children":10216},{"style":631},[10217],{"type":420,"value":10218}," pipeline",{"type":415,"tag":532,"props":10220,"children":10221},{"style":551},[10222],{"type":420,"value":644},{"type":415,"tag":532,"props":10224,"children":10225},{"style":551},[10226],{"type":420,"value":3276},{"type":415,"tag":532,"props":10228,"children":10229},{"style":631},[10230],{"type":420,"value":10231}," BuildDefinition",{"type":415,"tag":532,"props":10233,"children":10234},{"style":551},[10235],{"type":420,"value":664},{"type":415,"tag":532,"props":10237,"children":10238},{"style":551},[10239],{"type":420,"value":801},{"type":415,"tag":532,"props":10241,"children":10242},{"style":804},[10243],{"type":420,"value":10244},"deployToAzure",{"type":415,"tag":532,"props":10246,"children":10247},{"style":551},[10248],{"type":420,"value":801},{"type":415,"tag":532,"props":10250,"children":10251},{"style":551},[10252],{"type":420,"value":1099},{"type":415,"tag":532,"props":10254,"children":10255},{"style":551},[10256],{"type":420,"value":7363},{"type":415,"tag":532,"props":10258,"children":10259},{"class":534,"line":566},[10260],{"type":415,"tag":532,"props":10261,"children":10262},{"style":551},[10263],{"type":420,"value":764},{"type":415,"tag":532,"props":10265,"children":10266},{"class":534,"line":583},[10267,10271,10275,10279,10283,10287],{"type":415,"tag":532,"props":10268,"children":10269},{"style":545},[10270],{"type":420,"value":7733},{"type":415,"tag":532,"props":10272,"children":10273},{"style":551},[10274],{"type":420,"value":1134},{"type":415,"tag":532,"props":10276,"children":10277},{"style":545},[10278],{"type":420,"value":7324},{"type":415,"tag":532,"props":10280,"children":10281},{"style":551},[10282],{"type":420,"value":432},{"type":415,"tag":532,"props":10284,"children":10285},{"style":545},[10286],{"type":420,"value":7750},{"type":415,"tag":532,"props":10288,"children":10289},{"style":551},[10290],{"type":420,"value":7400},{"type":415,"tag":532,"props":10292,"children":10293},{"class":534,"line":617},[10294,10299,10303,10307,10312],{"type":415,"tag":532,"props":10295,"children":10296},{"style":545},[10297],{"type":420,"value":10298},"    Repository ",{"type":415,"tag":532,"props":10300,"children":10301},{"style":551},[10302],{"type":420,"value":1134},{"type":415,"tag":532,"props":10304,"children":10305},{"style":551},[10306],{"type":420,"value":3276},{"type":415,"tag":532,"props":10308,"children":10309},{"style":631},[10310],{"type":420,"value":10311}," BuildDefinitionRepositoryArgs",{"type":415,"tag":532,"props":10313,"children":10314},{"style":551},[10315],{"type":420,"value":7907},{"type":415,"tag":532,"props":10317,"children":10318},{"class":534,"line":627},[10319],{"type":415,"tag":532,"props":10320,"children":10321},{"style":551},[10322],{"type":420,"value":1121},{"type":415,"tag":532,"props":10324,"children":10325},{"class":534,"line":677},[10326,10331,10335,10339,10343,10347,10351,10355,10359,10363,10367,10371],{"type":415,"tag":532,"props":10327,"children":10328},{"style":545},[10329],{"type":420,"value":10330},"        RepoId ",{"type":415,"tag":532,"props":10332,"children":10333},{"style":551},[10334],{"type":420,"value":1134},{"type":415,"tag":532,"props":10336,"children":10337},{"style":545},[10338],{"type":420,"value":7695},{"type":415,"tag":532,"props":10340,"children":10341},{"style":551},[10342],{"type":420,"value":432},{"type":415,"tag":532,"props":10344,"children":10345},{"style":656},[10346],{"type":420,"value":8485},{"type":415,"tag":532,"props":10348,"children":10349},{"style":551},[10350],{"type":420,"value":664},{"type":415,"tag":532,"props":10352,"children":10353},{"style":631},[10354],{"type":420,"value":10065},{"type":415,"tag":532,"props":10356,"children":10357},{"style":551},[10358],{"type":420,"value":8499},{"type":415,"tag":532,"props":10360,"children":10361},{"style":545},[10362],{"type":420,"value":10074},{"type":415,"tag":532,"props":10364,"children":10365},{"style":551},[10366],{"type":420,"value":432},{"type":415,"tag":532,"props":10368,"children":10369},{"style":545},[10370],{"type":420,"value":7750},{"type":415,"tag":532,"props":10372,"children":10373},{"style":551},[10374],{"type":420,"value":10087},{"type":415,"tag":532,"props":10376,"children":10377},{"class":534,"line":719},[10378,10383,10387,10391,10395,10399],{"type":415,"tag":532,"props":10379,"children":10380},{"style":545},[10381],{"type":420,"value":10382},"        BranchName ",{"type":415,"tag":532,"props":10384,"children":10385},{"style":551},[10386],{"type":420,"value":1134},{"type":415,"tag":532,"props":10388,"children":10389},{"style":551},[10390],{"type":420,"value":4041},{"type":415,"tag":532,"props":10392,"children":10393},{"style":804},[10394],{"type":420,"value":8046},{"type":415,"tag":532,"props":10396,"children":10397},{"style":551},[10398],{"type":420,"value":801},{"type":415,"tag":532,"props":10400,"children":10401},{"style":551},[10402],{"type":420,"value":7400},{"type":415,"tag":532,"props":10404,"children":10405},{"class":534,"line":758},[10406,10411,10415,10419,10423,10428],{"type":415,"tag":532,"props":10407,"children":10408},{"style":545},[10409],{"type":420,"value":10410},"        YmlPath ",{"type":415,"tag":532,"props":10412,"children":10413},{"style":551},[10414],{"type":420,"value":1134},{"type":415,"tag":532,"props":10416,"children":10417},{"style":545},[10418],{"type":420,"value":9958},{"type":415,"tag":532,"props":10420,"children":10421},{"style":551},[10422],{"type":420,"value":432},{"type":415,"tag":532,"props":10424,"children":10425},{"style":545},[10426],{"type":420,"value":10427},"File",{"type":415,"tag":532,"props":10429,"children":10430},{"style":551},[10431],{"type":420,"value":7400},{"type":415,"tag":532,"props":10433,"children":10434},{"class":534,"line":767},[10435,10440,10444,10448,10453],{"type":415,"tag":532,"props":10436,"children":10437},{"style":545},[10438],{"type":420,"value":10439},"        RepoType ",{"type":415,"tag":532,"props":10441,"children":10442},{"style":551},[10443],{"type":420,"value":1134},{"type":415,"tag":532,"props":10445,"children":10446},{"style":551},[10447],{"type":420,"value":4041},{"type":415,"tag":532,"props":10449,"children":10450},{"style":804},[10451],{"type":420,"value":10452},"TfsGit",{"type":415,"tag":532,"props":10454,"children":10455},{"style":551},[10456],{"type":420,"value":4051},{"type":415,"tag":532,"props":10458,"children":10459},{"class":534,"line":819},[10460],{"type":415,"tag":532,"props":10461,"children":10462},{"style":551},[10463],{"type":420,"value":1170},{"type":415,"tag":532,"props":10465,"children":10466},{"class":534,"line":850},[10467],{"type":415,"tag":532,"props":10468,"children":10469},{"style":551},[10470],{"type":420,"value":856},{"type":415,"tag":416,"props":10472,"children":10473},{},[10474],{"type":420,"value":10475},"To complete the automation process, we can authorize the pipeline to utilize the service connection, eliminating the need for manual intervention through the portal:",{"type":415,"tag":523,"props":10477,"children":10479},{"className":525,"code":10478,"language":326,"meta":401,"style":401},"new PipelineAuthorization(\"azureOidcPipelineAuthorization\", new()\n{\n    ProjectId = project.Id,\n    Type = \"endpoint\",\n    PipelineId = pipeline.Id.Apply(int.Parse),\n    ResourceId = serviceConnection.Id\n});\n",[10480],{"type":415,"tag":468,"props":10481,"children":10482},{"__ignoreMap":401},[10483,10520,10527,10554,10583,10629,10654],{"type":415,"tag":532,"props":10484,"children":10485},{"class":534,"line":535},[10486,10490,10495,10499,10503,10508,10512,10516],{"type":415,"tag":532,"props":10487,"children":10488},{"style":954},[10489],{"type":420,"value":9142},{"type":415,"tag":532,"props":10491,"children":10492},{"style":656},[10493],{"type":420,"value":10494}," PipelineAuthorization",{"type":415,"tag":532,"props":10496,"children":10497},{"style":551},[10498],{"type":420,"value":664},{"type":415,"tag":532,"props":10500,"children":10501},{"style":551},[10502],{"type":420,"value":801},{"type":415,"tag":532,"props":10504,"children":10505},{"style":804},[10506],{"type":420,"value":10507},"azureOidcPipelineAuthorization",{"type":415,"tag":532,"props":10509,"children":10510},{"style":551},[10511],{"type":420,"value":801},{"type":415,"tag":532,"props":10513,"children":10514},{"style":551},[10515],{"type":420,"value":1099},{"type":415,"tag":532,"props":10517,"children":10518},{"style":551},[10519],{"type":420,"value":7363},{"type":415,"tag":532,"props":10521,"children":10522},{"class":534,"line":566},[10523],{"type":415,"tag":532,"props":10524,"children":10525},{"style":551},[10526],{"type":420,"value":764},{"type":415,"tag":532,"props":10528,"children":10529},{"class":534,"line":583},[10530,10534,10538,10542,10546,10550],{"type":415,"tag":532,"props":10531,"children":10532},{"style":545},[10533],{"type":420,"value":7733},{"type":415,"tag":532,"props":10535,"children":10536},{"style":551},[10537],{"type":420,"value":1134},{"type":415,"tag":532,"props":10539,"children":10540},{"style":545},[10541],{"type":420,"value":7324},{"type":415,"tag":532,"props":10543,"children":10544},{"style":551},[10545],{"type":420,"value":432},{"type":415,"tag":532,"props":10547,"children":10548},{"style":545},[10549],{"type":420,"value":7750},{"type":415,"tag":532,"props":10551,"children":10552},{"style":551},[10553],{"type":420,"value":7400},{"type":415,"tag":532,"props":10555,"children":10556},{"class":534,"line":617},[10557,10562,10566,10570,10575,10579],{"type":415,"tag":532,"props":10558,"children":10559},{"style":545},[10560],{"type":420,"value":10561},"    Type ",{"type":415,"tag":532,"props":10563,"children":10564},{"style":551},[10565],{"type":420,"value":1134},{"type":415,"tag":532,"props":10567,"children":10568},{"style":551},[10569],{"type":420,"value":4041},{"type":415,"tag":532,"props":10571,"children":10572},{"style":804},[10573],{"type":420,"value":10574},"endpoint",{"type":415,"tag":532,"props":10576,"children":10577},{"style":551},[10578],{"type":420,"value":801},{"type":415,"tag":532,"props":10580,"children":10581},{"style":551},[10582],{"type":420,"value":7400},{"type":415,"tag":532,"props":10584,"children":10585},{"class":534,"line":627},[10586,10591,10595,10599,10603,10607,10611,10615,10620,10625],{"type":415,"tag":532,"props":10587,"children":10588},{"style":545},[10589],{"type":420,"value":10590},"    PipelineId ",{"type":415,"tag":532,"props":10592,"children":10593},{"style":551},[10594],{"type":420,"value":1134},{"type":415,"tag":532,"props":10596,"children":10597},{"style":545},[10598],{"type":420,"value":10218},{"type":415,"tag":532,"props":10600,"children":10601},{"style":551},[10602],{"type":420,"value":432},{"type":415,"tag":532,"props":10604,"children":10605},{"style":545},[10606],{"type":420,"value":7750},{"type":415,"tag":532,"props":10608,"children":10609},{"style":551},[10610],{"type":420,"value":432},{"type":415,"tag":532,"props":10612,"children":10613},{"style":656},[10614],{"type":420,"value":8485},{"type":415,"tag":532,"props":10616,"children":10617},{"style":551},[10618],{"type":420,"value":10619},"(int.",{"type":415,"tag":532,"props":10621,"children":10622},{"style":545},[10623],{"type":420,"value":10624},"Parse",{"type":415,"tag":532,"props":10626,"children":10627},{"style":551},[10628],{"type":420,"value":10087},{"type":415,"tag":532,"props":10630,"children":10631},{"class":534,"line":677},[10632,10637,10641,10645,10649],{"type":415,"tag":532,"props":10633,"children":10634},{"style":545},[10635],{"type":420,"value":10636},"    ResourceId ",{"type":415,"tag":532,"props":10638,"children":10639},{"style":551},[10640],{"type":420,"value":1134},{"type":415,"tag":532,"props":10642,"children":10643},{"style":545},[10644],{"type":420,"value":8135},{"type":415,"tag":532,"props":10646,"children":10647},{"style":551},[10648],{"type":420,"value":432},{"type":415,"tag":532,"props":10650,"children":10651},{"style":545},[10652],{"type":420,"value":10653},"Id\n",{"type":415,"tag":532,"props":10655,"children":10656},{"class":534,"line":719},[10657],{"type":415,"tag":532,"props":10658,"children":10659},{"style":551},[10660],{"type":420,"value":856},{"type":415,"tag":416,"props":10662,"children":10663},{},[10664],{"type":420,"value":10665},"The last thing we can do is create a stack output to expose the URL of the created pipeline:",{"type":415,"tag":523,"props":10667,"children":10669},{"className":525,"code":10668,"language":326,"meta":401,"style":401},"return new Dictionary\u003Cstring, object?>\n{\n    [\"pipelineUrl\"] = Output.Format($\"{organizationUrl}{project.Name}/_build?definitionId={pipeline.Id}\")\n};\n",[10670],{"type":415,"tag":468,"props":10671,"children":10672},{"__ignoreMap":401},[10673,10708,10715,10821],{"type":415,"tag":532,"props":10674,"children":10675},{"class":534,"line":535},[10676,10681,10685,10690,10694,10699,10703],{"type":415,"tag":532,"props":10677,"children":10678},{"style":1241},[10679],{"type":420,"value":10680},"return",{"type":415,"tag":532,"props":10682,"children":10683},{"style":551},[10684],{"type":420,"value":3276},{"type":415,"tag":532,"props":10686,"children":10687},{"style":631},[10688],{"type":420,"value":10689}," Dictionary",{"type":415,"tag":532,"props":10691,"children":10692},{"style":551},[10693],{"type":420,"value":706},{"type":415,"tag":532,"props":10695,"children":10696},{"style":551},[10697],{"type":420,"value":10698},"string",{"type":415,"tag":532,"props":10700,"children":10701},{"style":551},[10702],{"type":420,"value":1099},{"type":415,"tag":532,"props":10704,"children":10705},{"style":551},[10706],{"type":420,"value":10707}," object?>\n",{"type":415,"tag":532,"props":10709,"children":10710},{"class":534,"line":566},[10711],{"type":415,"tag":532,"props":10712,"children":10713},{"style":551},[10714],{"type":420,"value":764},{"type":415,"tag":532,"props":10716,"children":10717},{"class":534,"line":583},[10718,10723,10727,10732,10736,10740,10744,10748,10752,10756,10760,10765,10770,10775,10779,10783,10787,10791,10796,10800,10805,10809,10813,10817],{"type":415,"tag":532,"props":10719,"children":10720},{"style":551},[10721],{"type":420,"value":10722},"    [",{"type":415,"tag":532,"props":10724,"children":10725},{"style":551},[10726],{"type":420,"value":801},{"type":415,"tag":532,"props":10728,"children":10729},{"style":804},[10730],{"type":420,"value":10731},"pipelineUrl",{"type":415,"tag":532,"props":10733,"children":10734},{"style":551},[10735],{"type":420,"value":801},{"type":415,"tag":532,"props":10737,"children":10738},{"style":551},[10739],{"type":420,"value":7449},{"type":415,"tag":532,"props":10741,"children":10742},{"style":551},[10743],{"type":420,"value":644},{"type":415,"tag":532,"props":10745,"children":10746},{"style":545},[10747],{"type":420,"value":9284},{"type":415,"tag":532,"props":10749,"children":10750},{"style":551},[10751],{"type":420,"value":432},{"type":415,"tag":532,"props":10753,"children":10754},{"style":656},[10755],{"type":420,"value":9293},{"type":415,"tag":532,"props":10757,"children":10758},{"style":551},[10759],{"type":420,"value":664},{"type":415,"tag":532,"props":10761,"children":10762},{"style":551},[10763],{"type":420,"value":10764},"$\"{",{"type":415,"tag":532,"props":10766,"children":10767},{"style":545},[10768],{"type":420,"value":10769},"organizationUrl",{"type":415,"tag":532,"props":10771,"children":10772},{"style":551},[10773],{"type":420,"value":10774},"}{",{"type":415,"tag":532,"props":10776,"children":10777},{"style":545},[10778],{"type":420,"value":9615},{"type":415,"tag":532,"props":10780,"children":10781},{"style":551},[10782],{"type":420,"value":432},{"type":415,"tag":532,"props":10784,"children":10785},{"style":545},[10786],{"type":420,"value":1344},{"type":415,"tag":532,"props":10788,"children":10789},{"style":551},[10790],{"type":420,"value":4864},{"type":415,"tag":532,"props":10792,"children":10793},{"style":804},[10794],{"type":420,"value":10795},"/_build?definitionId=",{"type":415,"tag":532,"props":10797,"children":10798},{"style":551},[10799],{"type":420,"value":8748},{"type":415,"tag":532,"props":10801,"children":10802},{"style":545},[10803],{"type":420,"value":10804},"pipeline",{"type":415,"tag":532,"props":10806,"children":10807},{"style":551},[10808],{"type":420,"value":432},{"type":415,"tag":532,"props":10810,"children":10811},{"style":545},[10812],{"type":420,"value":7750},{"type":415,"tag":532,"props":10814,"children":10815},{"style":551},[10816],{"type":420,"value":4502},{"type":415,"tag":532,"props":10818,"children":10819},{"style":551},[10820],{"type":420,"value":1113},{"type":415,"tag":532,"props":10822,"children":10823},{"class":534,"line":617},[10824],{"type":415,"tag":532,"props":10825,"children":10826},{"style":551},[10827],{"type":420,"value":10828},"};\n",{"type":415,"tag":416,"props":10830,"children":10831},{},[10832,10834,10840],{"type":420,"value":10833},"Now we can execute the ",{"type":415,"tag":468,"props":10835,"children":10837},{"className":10836},[],[10838],{"type":420,"value":10839},"pulumi up",{"type":420,"value":10841}," command to provision all these resources and then open the pipeline page in our browser to test the pipeline.",{"type":415,"tag":434,"props":10843,"children":10844},{"icon":436},[10845],{"type":415,"tag":416,"props":10846,"children":10847},{},[10848,10850,10856,10858,10865,10867],{"type":420,"value":10849},"On Windows, you can use the ",{"type":415,"tag":468,"props":10851,"children":10853},{"className":10852},[],[10854],{"type":420,"value":10855},"start $(pulumi stack output pipelineUrl)",{"type":420,"value":10857}," command to directly open the browser on the pipeline page. If you are using ",{"type":415,"tag":423,"props":10859,"children":10862},{"href":10860,"rel":10861},"https://www.nushell.sh/",[427],[10863],{"type":420,"value":10864},"Nushell",{"type":420,"value":10866}," the command will be ",{"type":415,"tag":468,"props":10868,"children":10870},{"className":10869},[],[10871],{"type":420,"value":10872},"pulumi stack output pipelineUrl | start $in",{"type":415,"tag":416,"props":10874,"children":10875},{},[10876],{"type":415,"tag":3882,"props":10877,"children":10881},{"alt":10878,"className":10879,"src":10880},"Results of the pipeline run in Azure DevOps",[3886,3887],"/posts/images/azuredevopsoidc_portal.webp",[],{"type":415,"tag":416,"props":10883,"children":10884},{},[10885],{"type":420,"value":10886},"Everything is working as expected.",{"type":415,"tag":482,"props":10888,"children":10890},{"id":10889},"to-conclude",[10891],{"type":420,"value":10892},"To conclude",{"type":415,"tag":416,"props":10894,"children":10895},{},[10896,10898,10904],{"type":420,"value":10897},"In this article, we demonstrated how to automate the configuration of an Azure DevOps project using Workload Identity Federation for secure deployments to Azure. We covered the provisioning of the Microsoft Entra ID and Azure DevOps resources necessary to make this work. It's very similar to ",{"type":415,"tag":423,"props":10899,"children":10901},{"href":3900,"rel":10900},[427],[10902],{"type":420,"value":10903},"what can be done for GitHub",{"type":420,"value":10905}," but with the specificities of Azure DevOps.",{"type":415,"tag":416,"props":10907,"children":10908},{},[10909],{"type":420,"value":10910},"It was an opportunity for me to work with the Azure DevOps provider. Even if it does the job, I must admit I was somewhat disappointed with the developer experience which I found to be not very intuitive, with poorly named resources and an overreliance on strings as parameters. I assume that the Azure DevOps APIs are primarily responsible for this, as they are what the provider calls upon.",{"type":415,"tag":416,"props":10912,"children":10913},{},[10914],{"type":420,"value":10915},"One thing I find interesting with Azure DevOps is that YAML pipelines do not need to be updated to take advantage of workload identity federation as long as the Azure Pipelines tasks you are using support it and your ARM service connection has been converted to workload identity federation.",{"type":415,"tag":416,"props":10917,"children":10918},{},[10919],{"type":420,"value":10920},"Anyway, regardless of the CI/CD platform you are using, I believe that employing Workload Identity Federation to deploy code to Azure from pipelines is the right approach.",{"type":415,"tag":416,"props":10922,"children":10923},{},[10924,10926,10936],{"type":420,"value":10925},"You can find the complete source code used for this article ",{"type":415,"tag":423,"props":10927,"children":10930},{"href":10928,"rel":10929},"https://github.com/TechWatching/AzureDevOpsWorkloadIdentity",[427],[10931],{"type":415,"tag":6864,"props":10932,"children":10933},{},[10934],{"type":420,"value":10935},"in this GitHub repository",{"type":420,"value":432},{"type":415,"tag":3470,"props":10938,"children":10939},{},[10940],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":10942},[10943,10944,10946,10953],{"id":6774,"depth":566,"text":6777},{"id":6859,"depth":566,"text":10945},"How can you use Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"id":6936,"depth":566,"text":6939,"children":10947},[10948,10949,10950,10951,10952],{"id":6942,"depth":583,"text":6945},{"id":7179,"depth":583,"text":7182},{"id":8099,"depth":583,"text":8102},{"id":8822,"depth":583,"text":8825},{"id":9680,"depth":583,"text":9683},{"id":10889,"depth":566,"text":10892},"content:1.posts:54.ado-workload-identity-federation.md","1.posts/54.ado-workload-identity-federation.md",{"_path":166,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":165,"description":10957,"lead":10958,"date":10959,"image":10960,"badge":10962,"tags":10963,"body":10964,"_type":3483,"_id":18334,"_source":3485,"_file":18335,"_extension":3487},"Creating an application and deploying it to Azure is not complicated. You write some code on your machine, do some clicks in the Azure portal, or run some Azure CLI commands from your terminal and that's it: your application is up and running in Azure.","Using Azure OpenID Connect with Pulumi in GitHub Actions","2023-07-20T00:00:00.000Z",{"src":10961},"/images/azureOIDC.webp",{"label":266},[228,233,307,374,312,315,376],{"type":412,"children":10965,"toc":18309},[10966,10970,10975,10987,10993,11003,11012,11018,11029,11063,11072,11078,11090,11128,11137,11155,11161,11166,11171,11179,11184,11192,11197,11218,11236,11256,11262,11270,11276,11281,11303,11308,11331,11336,11342,11348,11353,11408,11413,11463,11502,11506,11538,11551,11569,11573,11596,11620,11635,11640,11894,11915,11937,11969,11981,11986,12235,12251,12256,12542,12567,12572,12586,12595,12601,12606,12611,12910,12922,13024,13029,13118,13139,13202,13210,13216,13221,13226,13242,13247,13398,13403,13901,13918,13924,13929,13934,14246,14259,14857,14870,14895,14903,14932,14965,15058,15080,15280,15285,15673,15678,15710,15733,15739,15751,15760,15765,15774,15779,15818,15823,15828,15878,15890,15903,15920,15941,15950,15955,15959,15965,15970,15975,15981,15986,16004,16009,16015,16020,16106,16112,16117,16122,18289,18300,18305],{"type":415,"tag":416,"props":10967,"children":10968},{},[10969],{"type":420,"value":10957},{"type":415,"tag":416,"props":10971,"children":10972},{},[10973],{"type":420,"value":10974},"Yet, that's not real life, at least not what you will do when working on a professional project. Your code needs to be versioned and pushed to a location where your colleagues can work on it. The provisioning of Azure resources and deployment to Azure should be carried out using a properly configured CI/CD pipeline with the necessary authorization.",{"type":415,"tag":416,"props":10976,"children":10977},{},[10978,10980,10985],{"type":420,"value":10979},"That's a lot of work that would need to be done each time you start a new project. So let's automate that using Pulumi to simplify the process and create an \"",{"type":415,"tag":7033,"props":10981,"children":10982},{},[10983],{"type":420,"value":10984},"Azure-Ready GitHub repository",{"type":420,"value":10986},"\".",{"type":415,"tag":482,"props":10988,"children":10990},{"id":10989},"whats-an-azure-ready-github-repository",[10991],{"type":420,"value":10992},"What's an Azure-Ready GitHub repository?",{"type":415,"tag":416,"props":10994,"children":10995},{},[10996,10997,11001],{"type":420,"value":801},{"type":415,"tag":7033,"props":10998,"children":10999},{},[11000],{"type":420,"value":10984},{"type":420,"value":11002},"\" is not an official term or concept, it's just something I've come up with to describe a Github repository that has everything correctly configured to provision Azure resources or deploy applications to Azure from a GitHub Actions CI/CD pipeline.",{"type":415,"tag":416,"props":11004,"children":11005},{},[11006],{"type":415,"tag":3882,"props":11007,"children":11011},{"alt":11008,"className":11009,"src":11010},"Diagram of a GitHub repository interacting with Azure.",[3886,3887],"/posts/images/azurereadygithub_overview_1.webp",[],{"type":415,"tag":3914,"props":11013,"children":11015},{"id":11014},"the-github-part",[11016],{"type":420,"value":11017},"The GitHub part",{"type":415,"tag":416,"props":11019,"children":11020},{},[11021,11023,11027],{"type":420,"value":11022},"On the GitHub side, to have an ",{"type":415,"tag":7033,"props":11024,"children":11025},{},[11026],{"type":420,"value":10984},{"type":420,"value":11028},", we need:",{"type":415,"tag":508,"props":11030,"children":11031},{},[11032,11045,11050],{"type":415,"tag":512,"props":11033,"children":11034},{},[11035,11037,11043],{"type":420,"value":11036},"the GitHub repository itself (already initialized with a ",{"type":415,"tag":468,"props":11038,"children":11040},{"className":11039},[],[11041],{"type":420,"value":11042},"main",{"type":420,"value":11044}," branch)",{"type":415,"tag":512,"props":11046,"children":11047},{},[11048],{"type":420,"value":11049},"the necessary GitHub Actions variables/secrets to authenticate to the correct Azure subscription",{"type":415,"tag":512,"props":11051,"children":11052},{},[11053,11055,11061],{"type":420,"value":11054},"a YAML file located in the ",{"type":415,"tag":468,"props":11056,"children":11058},{"className":11057},[],[11059],{"type":420,"value":11060},".github/workflows/",{"type":420,"value":11062}," folder that contains the CI/CD pipeline that provisions resources in Azure",{"type":415,"tag":416,"props":11064,"children":11065},{},[11066],{"type":415,"tag":3882,"props":11067,"children":11071},{"alt":11068,"className":11069,"src":11070},"A diagram of the GitHub repository to create.",[3886,3887],"/posts/images/azurereadygithub_github_1.webp",[],{"type":415,"tag":3914,"props":11073,"children":11075},{"id":11074},"the-azure-part",[11076],{"type":420,"value":11077},"The Azure part",{"type":415,"tag":416,"props":11079,"children":11080},{},[11081,11083,11088],{"type":420,"value":11082},"On the Azure side, to have an ",{"type":415,"tag":7033,"props":11084,"children":11085},{},[11086],{"type":420,"value":11087},"Azure-Ready GitHub repository,",{"type":420,"value":11089}," we need:",{"type":415,"tag":508,"props":11091,"children":11092},{},[11093,11098],{"type":415,"tag":512,"props":11094,"children":11095},{},[11096],{"type":420,"value":11097},"the existing Azure subscription to which resources are deployed",{"type":415,"tag":512,"props":11099,"children":11100},{},[11101,11103,11108,11110],{"type":420,"value":11102},"an ",{"type":415,"tag":7033,"props":11104,"children":11105},{},[11106],{"type":420,"value":11107},"identity",{"type":420,"value":11109}," in the Azure Active Directory of the desired tenant so that the GitHub CI/CD pipeline can authenticate to Azure and interact with the subscription",{"type":415,"tag":508,"props":11111,"children":11112},{},[11113,11118,11123],{"type":415,"tag":512,"props":11114,"children":11115},{},[11116],{"type":420,"value":11117},"an Azure AD application that represents the GitHub Actions pipeline identity",{"type":415,"tag":512,"props":11119,"children":11120},{},[11121],{"type":420,"value":11122},"a Service Principal (related to the Azure AD application) that has the contributor role on the Azure subscription",{"type":415,"tag":512,"props":11124,"children":11125},{},[11126],{"type":420,"value":11127},"credentials for the CI/CD pipeline to authenticate to Azure on behalf of this Azure AD application",{"type":415,"tag":416,"props":11129,"children":11130},{},[11131],{"type":415,"tag":3882,"props":11132,"children":11136},{"alt":11133,"className":11134,"src":11135},"A diagram of the resources to configure in Azure.",[3886,3887],"/posts/images/azurereadygithub_azure_1.webp",[],{"type":415,"tag":434,"props":11138,"children":11139},{"icon":6841},[11140],{"type":415,"tag":416,"props":11141,"children":11142},{},[11143,11147,11149,11153],{"type":415,"tag":7033,"props":11144,"children":11145},{},[11146],{"type":420,"value":252},{"type":420,"value":11148}," has recently been renamed ",{"type":415,"tag":7033,"props":11150,"children":11151},{},[11152],{"type":420,"value":382},{"type":420,"value":11154}," (as of the time of writing). However, I will continue to use the term Azure Active Directory throughout the rest of the article. Please note that both terms refer to the same service.",{"type":415,"tag":3914,"props":11156,"children":11158},{"id":11157},"the-problem-with-secret-credentials",[11159],{"type":420,"value":11160},"The problem with secret credentials",{"type":415,"tag":416,"props":11162,"children":11163},{},[11164],{"type":420,"value":11165},"People tend to use secret credentials to authenticate their pipeline to Azure and that's not the best thing to do.",{"type":415,"tag":416,"props":11167,"children":11168},{},[11169],{"type":420,"value":11170},"From a security standpoint, depending on secrets always poses a security risk. Even if in that case the secret would be safely stored in a GitHub secret and never exposed publicly, it's still better to avoid secrets when we can.",{"type":415,"tag":434,"props":11172,"children":11173},{"icon":7279},[11174],{"type":415,"tag":416,"props":11175,"children":11176},{},[11177],{"type":420,"value":11178},"That's precisely why when hosting applications in Azure, we use Managed Identities and IAM roles instead of relying on secrets. Yet, here we can't use Managed Identities for GitHub Actions pipelines.",{"type":415,"tag":416,"props":11180,"children":11181},{},[11182],{"type":420,"value":11183},"From a practical standpoint, depending on secrets can quickly become problematic as they expire and thus require rotation. Of course, you can set up alerting or automate secret rotation but that's something you would prefer to avoid managing.",{"type":415,"tag":434,"props":11185,"children":11186},{"icon":1382},[11187],{"type":415,"tag":416,"props":11188,"children":11189},{},[11190],{"type":420,"value":11191},"I recently encountered a situation in Azure DevOps where a deployment failed due to the expiration of an Azure AD Application secret associated with the Service Connection used in the pipeline, and we were not alerted about it. That's the kind of scenario that can easily happen with secrets and that you want to avoid.",{"type":415,"tag":416,"props":11193,"children":11194},{},[11195],{"type":420,"value":11196},"So what can we do about that?",{"type":415,"tag":416,"props":11198,"children":11199},{},[11200,11202,11207,11209,11216],{"type":420,"value":11201},"👉 We can stop using secret credentials and use ",{"type":415,"tag":423,"props":11203,"children":11205},{"href":6815,"rel":11204},[427],[11206],{"type":420,"value":6819},{"type":420,"value":11208}," instead. I suggest you have a look at this ",{"type":415,"tag":423,"props":11210,"children":11213},{"href":11211,"rel":11212},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect",[427],[11214],{"type":420,"value":11215},"GitHub documentation page",{"type":420,"value":11217}," as well to better understand how it works but basically, you can remember the following:",{"type":415,"tag":508,"props":11219,"children":11220},{},[11221,11226,11231],{"type":415,"tag":512,"props":11222,"children":11223},{},[11224],{"type":420,"value":11225},"this mechanism relies on Open ID Connect and trust between Azure and GitHub",{"type":415,"tag":512,"props":11227,"children":11228},{},[11229],{"type":420,"value":11230},"the GitHub pipeline does not need an Azure AD application secret anymore to authenticate to Azure",{"type":415,"tag":512,"props":11232,"children":11233},{},[11234],{"type":420,"value":11235},"it's not an Azure thing only, it's an open standard that also works with other cloud providers and other platforms than Github",{"type":415,"tag":416,"props":11237,"children":11238},{},[11239,11241,11246,11248,11254],{"type":420,"value":11240},"To establish the trust relationship between the Azure AD application and the GitHub repository, a ",{"type":415,"tag":7033,"props":11242,"children":11243},{},[11244],{"type":420,"value":11245},"Federated Identity Credential",{"type":420,"value":11247}," must be created in the Azure Active Directory. You can find how to do that manually from the portal in the ",{"type":415,"tag":423,"props":11249,"children":11252},{"href":11250,"rel":11251},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp",[427],[11253],{"type":420,"value":499},{"type":420,"value":11255}," but we are going to directly automate that 😉.",{"type":415,"tag":3914,"props":11257,"children":11259},{"id":11258},"the-complete-solution-to-implement",[11260],{"type":420,"value":11261},"The complete solution to implement",{"type":415,"tag":416,"props":11263,"children":11264},{},[11265],{"type":415,"tag":3882,"props":11266,"children":11269},{"alt":3884,"className":11267,"src":11268},[3886,3887],"/posts/images/azurereadygithub_overview_2.webp",[],{"type":415,"tag":482,"props":11271,"children":11273},{"id":11272},"why-use-pulumi-in-that-context",[11274],{"type":420,"value":11275},"Why use Pulumi in that context?",{"type":415,"tag":416,"props":11277,"children":11278},{},[11279],{"type":420,"value":11280},"You might wonder why I chose to automate this process using Pulumi instead of writing a Bash or PowerShell script that would execute commands from the GitHub CLI and the Azure CLI.",{"type":415,"tag":434,"props":11282,"children":11283},{"icon":436},[11284],{"type":415,"tag":416,"props":11285,"children":11286},{},[11287,11289,11294,11296,11301],{"type":420,"value":11288},"By the way, you should check ",{"type":415,"tag":423,"props":11290,"children":11292},{"href":3953,"rel":11291},[427],[11293],{"type":420,"value":379},{"type":420,"value":11295}," if you have not done it yet, it's very handy. And if you have read my article about ",{"type":415,"tag":423,"props":11297,"children":11299},{"href":4423,"rel":11298},[427],[11300],{"type":420,"value":225},{"type":420,"value":11302},", you know it's a very convenient tool as well.",{"type":415,"tag":416,"props":11304,"children":11305},{},[11306],{"type":420,"value":11307},"I think Pulumi is a better choice here because:",{"type":415,"tag":508,"props":11309,"children":11310},{},[11311,11316,11321,11326],{"type":415,"tag":512,"props":11312,"children":11313},{},[11314],{"type":420,"value":11315},"a script is imperative by nature, but declarative infrastructure seems more suitable to avoid dealing with idempotency",{"type":415,"tag":512,"props":11317,"children":11318},{},[11319],{"type":420,"value":11320},"Pulumi can interact with both GitHub and Azure using its providers",{"type":415,"tag":512,"props":11322,"children":11323},{},[11324],{"type":420,"value":11325},"the code will be easier to write and maintain",{"type":415,"tag":512,"props":11327,"children":11328},{},[11329],{"type":420,"value":11330},"the code could be integrated into any application (including a future self-service infrastructure portal) using Pulumi Automation API",{"type":415,"tag":416,"props":11332,"children":11333},{},[11334],{"type":420,"value":11335},"In this article, the Pulumi code will be in TypeScript but it would work in any language supported by Pulumi.",{"type":415,"tag":482,"props":11337,"children":11339},{"id":11338},"automate-the-creation-of-the-azure-ready-github-repository",[11340],{"type":420,"value":11341},"Automate the creation of the Azure-Ready GitHub Repository",{"type":415,"tag":3914,"props":11343,"children":11345},{"id":11344},"create-the-pulumi-project",[11346],{"type":420,"value":11347},"Create the Pulumi project",{"type":415,"tag":416,"props":11349,"children":11350},{},[11351],{"type":420,"value":11352},"Let's start by scaffolding a new Pulumi project using TypeScript:",{"type":415,"tag":523,"props":11354,"children":11356},{"className":4059,"code":11355,"language":248,"meta":401,"style":401},"pulumi new typescript -n AzureOIDC -s dev -d \"A program to set up an Azure-Ready GitHub repository\"\n",[11357],{"type":415,"tag":468,"props":11358,"children":11359},{"__ignoreMap":401},[11360],{"type":415,"tag":532,"props":11361,"children":11362},{"class":534,"line":535},[11363,11368,11372,11377,11381,11386,11390,11395,11399,11404],{"type":415,"tag":532,"props":11364,"children":11365},{"style":545},[11366],{"type":420,"value":11367},"pulumi new typescript ",{"type":415,"tag":532,"props":11369,"children":11370},{"style":551},[11371],{"type":420,"value":4216},{"type":415,"tag":532,"props":11373,"children":11374},{"style":545},[11375],{"type":420,"value":11376},"n AzureOIDC ",{"type":415,"tag":532,"props":11378,"children":11379},{"style":551},[11380],{"type":420,"value":4216},{"type":415,"tag":532,"props":11382,"children":11383},{"style":545},[11384],{"type":420,"value":11385},"s dev ",{"type":415,"tag":532,"props":11387,"children":11388},{"style":551},[11389],{"type":420,"value":4216},{"type":415,"tag":532,"props":11391,"children":11392},{"style":545},[11393],{"type":420,"value":11394},"d ",{"type":415,"tag":532,"props":11396,"children":11397},{"style":551},[11398],{"type":420,"value":801},{"type":415,"tag":532,"props":11400,"children":11401},{"style":804},[11402],{"type":420,"value":11403},"A program to set up an Azure-Ready GitHub repository",{"type":415,"tag":532,"props":11405,"children":11406},{"style":551},[11407],{"type":420,"value":4051},{"type":415,"tag":416,"props":11409,"children":11410},{},[11411],{"type":420,"value":11412},"This command creates a new pulumi project and stack from the TypeScript template:",{"type":415,"tag":508,"props":11414,"children":11415},{},[11416,11433,11448],{"type":415,"tag":512,"props":11417,"children":11418},{},[11419,11420,11425,11427,11432],{"type":420,"value":7031},{"type":415,"tag":7033,"props":11421,"children":11422},{},[11423],{"type":420,"value":11424},"AzureOIDC\"",{"type":420,"value":11426}," is specified using the ",{"type":415,"tag":468,"props":11428,"children":11430},{"className":11429},[],[11431],{"type":420,"value":7045},{"type":420,"value":7047},{"type":415,"tag":512,"props":11434,"children":11435},{},[11436,11437,11441,11442,11447],{"type":420,"value":7052},{"type":415,"tag":7033,"props":11438,"children":11439},{},[11440],{"type":420,"value":11403},{"type":420,"value":7039},{"type":415,"tag":468,"props":11443,"children":11445},{"className":11444},[],[11446],{"type":420,"value":7063},{"type":420,"value":7047},{"type":415,"tag":512,"props":11449,"children":11450},{},[11451,11452,11456,11457,11462],{"type":420,"value":7069},{"type":415,"tag":7033,"props":11453,"children":11454},{},[11455],{"type":420,"value":7074},{"type":420,"value":7039},{"type":415,"tag":468,"props":11458,"children":11460},{"className":11459},[],[11461],{"type":420,"value":7081},{"type":420,"value":7047},{"type":415,"tag":434,"props":11464,"children":11465},{"icon":6841},[11466],{"type":415,"tag":416,"props":11467,"children":11468},{},[11469,11471,11477,11479,11485,11487,11492,11494,11500],{"type":420,"value":11470},"By default, the ",{"type":415,"tag":468,"props":11472,"children":11474},{"className":11473},[],[11475],{"type":420,"value":11476},"pulumi new",{"type":420,"value":11478}," command installs the dependencies when creating the project. You can prevent this by specifying the ",{"type":415,"tag":468,"props":11480,"children":11482},{"className":11481},[],[11483],{"type":420,"value":11484},"-g",{"type":420,"value":11486}," option, which is useful when you want to use another package manager than the default one (",{"type":415,"tag":468,"props":11488,"children":11490},{"className":11489},[],[11491],{"type":420,"value":362},{"type":420,"value":11493}," instead of ",{"type":415,"tag":468,"props":11495,"children":11497},{"className":11496},[],[11498],{"type":420,"value":11499},"npm",{"type":420,"value":11501}," for instance).",{"type":415,"tag":416,"props":11503,"children":11504},{},[11505],{"type":420,"value":7087},{"type":415,"tag":508,"props":11507,"children":11508},{},[11509,11518,11527],{"type":415,"tag":512,"props":11510,"children":11511},{},[11512,11513],{"type":420,"value":7095},{"type":415,"tag":423,"props":11514,"children":11516},{"href":7098,"rel":11515},[427],[11517],{"type":420,"value":7102},{"type":415,"tag":512,"props":11519,"children":11520},{},[11521,11522],{"type":420,"value":7095},{"type":415,"tag":423,"props":11523,"children":11525},{"href":7109,"rel":11524},[427],[11526],{"type":420,"value":7113},{"type":415,"tag":512,"props":11528,"children":11529},{},[11530,11531],{"type":420,"value":7095},{"type":415,"tag":423,"props":11532,"children":11535},{"href":11533,"rel":11534},"https://www.pulumi.com/registry/packages/github/",[427],[11536],{"type":420,"value":11537},"GitHub provider",{"type":415,"tag":416,"props":11539,"children":11540},{},[11541,11543,11549],{"type":420,"value":11542},"So we can add the following packages to our ",{"type":415,"tag":468,"props":11544,"children":11546},{"className":11545},[],[11547],{"type":420,"value":11548},"package.json",{"type":420,"value":11550}," file:",{"type":415,"tag":508,"props":11552,"children":11553},{},[11554,11559,11564],{"type":415,"tag":512,"props":11555,"children":11556},{},[11557],{"type":420,"value":11558},"@pulumi/azure-native",{"type":415,"tag":512,"props":11560,"children":11561},{},[11562],{"type":420,"value":11563},"@pulumi/azuread",{"type":415,"tag":512,"props":11565,"children":11566},{},[11567],{"type":420,"value":11568},"@pulumi/github",{"type":415,"tag":3914,"props":11570,"children":11571},{"id":3960},[11572],{"type":420,"value":3963},{"type":415,"tag":416,"props":11574,"children":11575},{},[11576,11578,11585,11587,11594],{"type":420,"value":11577},"To use the GitHub provider, we have to provide GitHub credentials. For that, we can create a personal access token (I prefer to create a ",{"type":415,"tag":423,"props":11579,"children":11582},{"href":11580,"rel":11581},"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens",[427],[11583],{"type":420,"value":11584},"fine-grained personal access token",{"type":420,"value":11586}," although a ",{"type":415,"tag":423,"props":11588,"children":11591},{"href":11589,"rel":11590},"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic",[427],[11592],{"type":420,"value":11593},"classic personal access token",{"type":420,"value":11595}," would also work). Next, we simply set the GitHub token in our Pulumi configuration, and the GitHub provider will automatically use it:",{"type":415,"tag":523,"props":11597,"children":11599},{"className":4059,"code":11598,"language":248,"meta":401,"style":401},"pulumi config set github:token XXXXXXXXXXXXXX --secret\n",[11600],{"type":415,"tag":468,"props":11601,"children":11602},{"__ignoreMap":401},[11603],{"type":415,"tag":532,"props":11604,"children":11605},{"class":534,"line":535},[11606,11611,11615],{"type":415,"tag":532,"props":11607,"children":11608},{"style":545},[11609],{"type":420,"value":11610},"pulumi config set github:token XXXXXXXXXXXXXX ",{"type":415,"tag":532,"props":11612,"children":11613},{"style":551},[11614],{"type":420,"value":4115},{"type":415,"tag":532,"props":11616,"children":11617},{"style":545},[11618],{"type":420,"value":11619},"secret\n",{"type":415,"tag":434,"props":11621,"children":11622},{"icon":7279},[11623],{"type":415,"tag":416,"props":11624,"children":11625},{},[11626,11628,11633],{"type":420,"value":11627},"Don't forget to include the ",{"type":415,"tag":468,"props":11629,"children":11631},{"className":11630},[],[11632],{"type":420,"value":7291},{"type":420,"value":11634}," option when setting sensitive configurations, as this ensures that Pulumi encrypts the information. By doing so, we can safely commit the configuration files without creating security risks.",{"type":415,"tag":416,"props":11636,"children":11637},{},[11638],{"type":420,"value":11639},"Now, it's time to create our GitHub repository!",{"type":415,"tag":523,"props":11641,"children":11644},{"className":11642,"code":11643,"language":357,"meta":401,"style":401},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import * as github from \"@pulumi/github\";\n\nconst repository = new github.Repository(\"azure-ready-repository\", {\n  name: \"azure-ready-repository\",\n  visibility: \"public\",\n  autoInit: true\n});\n\nexport const repositoryCloneUrl = repository.httpCloneUrl;\n",[11645],{"type":415,"tag":468,"props":11646,"children":11647},{"__ignoreMap":401},[11648,11692,11699,11760,11788,11816,11833,11848,11855],{"type":415,"tag":532,"props":11649,"children":11650},{"class":534,"line":535},[11651,11656,11661,11666,11671,11676,11680,11684,11688],{"type":415,"tag":532,"props":11652,"children":11653},{"style":1241},[11654],{"type":420,"value":11655},"import",{"type":415,"tag":532,"props":11657,"children":11658},{"style":551},[11659],{"type":420,"value":11660}," *",{"type":415,"tag":532,"props":11662,"children":11663},{"style":1241},[11664],{"type":420,"value":11665}," as",{"type":415,"tag":532,"props":11667,"children":11668},{"style":545},[11669],{"type":420,"value":11670}," github ",{"type":415,"tag":532,"props":11672,"children":11673},{"style":1241},[11674],{"type":420,"value":11675},"from",{"type":415,"tag":532,"props":11677,"children":11678},{"style":551},[11679],{"type":420,"value":4041},{"type":415,"tag":532,"props":11681,"children":11682},{"style":804},[11683],{"type":420,"value":11568},{"type":415,"tag":532,"props":11685,"children":11686},{"style":551},[11687],{"type":420,"value":801},{"type":415,"tag":532,"props":11689,"children":11690},{"style":551},[11691],{"type":420,"value":563},{"type":415,"tag":532,"props":11693,"children":11694},{"class":534,"line":566},[11695],{"type":415,"tag":532,"props":11696,"children":11697},{"emptyLinePlaceholder":621},[11698],{"type":420,"value":624},{"type":415,"tag":532,"props":11700,"children":11701},{"class":534,"line":583},[11702,11707,11712,11716,11720,11725,11729,11734,11738,11742,11747,11751,11755],{"type":415,"tag":532,"props":11703,"children":11704},{"style":954},[11705],{"type":420,"value":11706},"const",{"type":415,"tag":532,"props":11708,"children":11709},{"style":545},[11710],{"type":420,"value":11711}," repository ",{"type":415,"tag":532,"props":11713,"children":11714},{"style":551},[11715],{"type":420,"value":1134},{"type":415,"tag":532,"props":11717,"children":11718},{"style":551},[11719],{"type":420,"value":3276},{"type":415,"tag":532,"props":11721,"children":11722},{"style":545},[11723],{"type":420,"value":11724}," github",{"type":415,"tag":532,"props":11726,"children":11727},{"style":551},[11728],{"type":420,"value":432},{"type":415,"tag":532,"props":11730,"children":11731},{"style":656},[11732],{"type":420,"value":11733},"Repository",{"type":415,"tag":532,"props":11735,"children":11736},{"style":545},[11737],{"type":420,"value":664},{"type":415,"tag":532,"props":11739,"children":11740},{"style":551},[11741],{"type":420,"value":801},{"type":415,"tag":532,"props":11743,"children":11744},{"style":804},[11745],{"type":420,"value":11746},"azure-ready-repository",{"type":415,"tag":532,"props":11748,"children":11749},{"style":551},[11750],{"type":420,"value":801},{"type":415,"tag":532,"props":11752,"children":11753},{"style":551},[11754],{"type":420,"value":1099},{"type":415,"tag":532,"props":11756,"children":11757},{"style":551},[11758],{"type":420,"value":11759}," {\n",{"type":415,"tag":532,"props":11761,"children":11762},{"class":534,"line":617},[11763,11768,11772,11776,11780,11784],{"type":415,"tag":532,"props":11764,"children":11765},{"style":3532},[11766],{"type":420,"value":11767},"  name",{"type":415,"tag":532,"props":11769,"children":11770},{"style":551},[11771],{"type":420,"value":1290},{"type":415,"tag":532,"props":11773,"children":11774},{"style":551},[11775],{"type":420,"value":4041},{"type":415,"tag":532,"props":11777,"children":11778},{"style":804},[11779],{"type":420,"value":11746},{"type":415,"tag":532,"props":11781,"children":11782},{"style":551},[11783],{"type":420,"value":801},{"type":415,"tag":532,"props":11785,"children":11786},{"style":551},[11787],{"type":420,"value":7400},{"type":415,"tag":532,"props":11789,"children":11790},{"class":534,"line":627},[11791,11796,11800,11804,11808,11812],{"type":415,"tag":532,"props":11792,"children":11793},{"style":3532},[11794],{"type":420,"value":11795},"  visibility",{"type":415,"tag":532,"props":11797,"children":11798},{"style":551},[11799],{"type":420,"value":1290},{"type":415,"tag":532,"props":11801,"children":11802},{"style":551},[11803],{"type":420,"value":4041},{"type":415,"tag":532,"props":11805,"children":11806},{"style":804},[11807],{"type":420,"value":957},{"type":415,"tag":532,"props":11809,"children":11810},{"style":551},[11811],{"type":420,"value":801},{"type":415,"tag":532,"props":11813,"children":11814},{"style":551},[11815],{"type":420,"value":7400},{"type":415,"tag":532,"props":11817,"children":11818},{"class":534,"line":677},[11819,11824,11828],{"type":415,"tag":532,"props":11820,"children":11821},{"style":3532},[11822],{"type":420,"value":11823},"  autoInit",{"type":415,"tag":532,"props":11825,"children":11826},{"style":551},[11827],{"type":420,"value":1290},{"type":415,"tag":532,"props":11829,"children":11830},{"style":1938},[11831],{"type":420,"value":11832}," true\n",{"type":415,"tag":532,"props":11834,"children":11835},{"class":534,"line":719},[11836,11840,11844],{"type":415,"tag":532,"props":11837,"children":11838},{"style":551},[11839],{"type":420,"value":4864},{"type":415,"tag":532,"props":11841,"children":11842},{"style":545},[11843],{"type":420,"value":1349},{"type":415,"tag":532,"props":11845,"children":11846},{"style":551},[11847],{"type":420,"value":563},{"type":415,"tag":532,"props":11849,"children":11850},{"class":534,"line":758},[11851],{"type":415,"tag":532,"props":11852,"children":11853},{"emptyLinePlaceholder":621},[11854],{"type":420,"value":624},{"type":415,"tag":532,"props":11856,"children":11857},{"class":534,"line":767},[11858,11863,11868,11873,11877,11881,11885,11890],{"type":415,"tag":532,"props":11859,"children":11860},{"style":1241},[11861],{"type":420,"value":11862},"export",{"type":415,"tag":532,"props":11864,"children":11865},{"style":954},[11866],{"type":420,"value":11867}," const",{"type":415,"tag":532,"props":11869,"children":11870},{"style":545},[11871],{"type":420,"value":11872}," repositoryCloneUrl ",{"type":415,"tag":532,"props":11874,"children":11875},{"style":551},[11876],{"type":420,"value":1134},{"type":415,"tag":532,"props":11878,"children":11879},{"style":545},[11880],{"type":420,"value":7695},{"type":415,"tag":532,"props":11882,"children":11883},{"style":551},[11884],{"type":420,"value":432},{"type":415,"tag":532,"props":11886,"children":11887},{"style":545},[11888],{"type":420,"value":11889},"httpCloneUrl",{"type":415,"tag":532,"props":11891,"children":11892},{"style":551},[11893],{"type":420,"value":563},{"type":415,"tag":416,"props":11895,"children":11896},{},[11897,11899,11906,11908,11913],{"type":420,"value":11898},"Pulumi has an ",{"type":415,"tag":423,"props":11900,"children":11903},{"href":11901,"rel":11902},"https://www.pulumi.com/docs/concepts/resources/names/#autonaming",[427],[11904],{"type":420,"value":11905},"auto-naming capability",{"type":420,"value":11907}," that is very convenient to prevent name collisions or to ensure zero-downtime resource updates. Yet, in this context, I prefer to avoid a random suffix in my GitHub repository name, that's why I am specifying the ",{"type":415,"tag":468,"props":11909,"children":11911},{"className":11910},[],[11912],{"type":420,"value":3535},{"type":420,"value":11914}," property to override the auto-naming behavior.",{"type":415,"tag":416,"props":11916,"children":11917},{},[11918,11920,11927,11929,11935],{"type":420,"value":11919},"The last line creates a stack ",{"type":415,"tag":423,"props":11921,"children":11924},{"href":11922,"rel":11923},"https://www.pulumi.com/docs/concepts/stack/#outputs",[427],[11925],{"type":420,"value":11926},"output",{"type":420,"value":11928}," named ",{"type":415,"tag":468,"props":11930,"children":11932},{"className":11931},[],[11933],{"type":420,"value":11934},"repositoryCloneUrl",{"type":420,"value":11936}," so that we can easily get the URL to clone our newly created repository.",{"type":415,"tag":434,"props":11938,"children":11939},{"icon":6841},[11940],{"type":415,"tag":416,"props":11941,"children":11942},{},[11943,11945,11951,11953,11959,11961,11967],{"type":420,"value":11944},"I wanted the repository to be initialized, that's why I set the ",{"type":415,"tag":468,"props":11946,"children":11948},{"className":11947},[],[11949],{"type":420,"value":11950},"autoInit",{"type":420,"value":11952}," property to ",{"type":415,"tag":468,"props":11954,"children":11956},{"className":11955},[],[11957],{"type":420,"value":11958},"true",{"type":420,"value":11960}," but you should set it to ",{"type":415,"tag":468,"props":11962,"children":11964},{"className":11963},[],[11965],{"type":420,"value":11966},"false",{"type":420,"value":11968}," if you have an existing local git repository that you want to push on this GitHub repository.",{"type":415,"tag":3914,"props":11970,"children":11972},{"id":11971},"create-the-identity-in-azure-active-directory-for-the-github-actions-workflow",[11973,11975,11979],{"type":420,"value":11974},"Create the ",{"type":415,"tag":7033,"props":11976,"children":11977},{},[11978],{"type":420,"value":11107},{"type":420,"value":11980}," in Azure Active Directory for the GitHub Actions workflow",{"type":415,"tag":416,"props":11982,"children":11983},{},[11984],{"type":420,"value":11985},"Creating an Azure AD application and its service principal is not very complicated:",{"type":415,"tag":523,"props":11987,"children":11989},{"className":11642,"code":11988,"language":357,"meta":401,"style":401},"import * as azuread from \"@pulumi/azuread\";\n\nconst aadApplication = new azuread.Application(\"AzureReadyApp\", { displayName: \"Azure Ready App\" });\nconst servicePrincipal = new azuread.ServicePrincipal(\"AzureReadServicePrincipal\", {\n  applicationId: aadApplication.applicationId,\n});\n",[11990],{"type":415,"tag":468,"props":11991,"children":11992},{"__ignoreMap":401},[11993,12033,12040,12134,12191,12220],{"type":415,"tag":532,"props":11994,"children":11995},{"class":534,"line":535},[11996,12000,12004,12008,12013,12017,12021,12025,12029],{"type":415,"tag":532,"props":11997,"children":11998},{"style":1241},[11999],{"type":420,"value":11655},{"type":415,"tag":532,"props":12001,"children":12002},{"style":551},[12003],{"type":420,"value":11660},{"type":415,"tag":532,"props":12005,"children":12006},{"style":1241},[12007],{"type":420,"value":11665},{"type":415,"tag":532,"props":12009,"children":12010},{"style":545},[12011],{"type":420,"value":12012}," azuread ",{"type":415,"tag":532,"props":12014,"children":12015},{"style":1241},[12016],{"type":420,"value":11675},{"type":415,"tag":532,"props":12018,"children":12019},{"style":551},[12020],{"type":420,"value":4041},{"type":415,"tag":532,"props":12022,"children":12023},{"style":804},[12024],{"type":420,"value":11563},{"type":415,"tag":532,"props":12026,"children":12027},{"style":551},[12028],{"type":420,"value":801},{"type":415,"tag":532,"props":12030,"children":12031},{"style":551},[12032],{"type":420,"value":563},{"type":415,"tag":532,"props":12034,"children":12035},{"class":534,"line":566},[12036],{"type":415,"tag":532,"props":12037,"children":12038},{"emptyLinePlaceholder":621},[12039],{"type":420,"value":624},{"type":415,"tag":532,"props":12041,"children":12042},{"class":534,"line":583},[12043,12047,12052,12056,12060,12065,12069,12074,12078,12082,12087,12091,12095,12099,12104,12108,12112,12117,12121,12126,12130],{"type":415,"tag":532,"props":12044,"children":12045},{"style":954},[12046],{"type":420,"value":11706},{"type":415,"tag":532,"props":12048,"children":12049},{"style":545},[12050],{"type":420,"value":12051}," aadApplication ",{"type":415,"tag":532,"props":12053,"children":12054},{"style":551},[12055],{"type":420,"value":1134},{"type":415,"tag":532,"props":12057,"children":12058},{"style":551},[12059],{"type":420,"value":3276},{"type":415,"tag":532,"props":12061,"children":12062},{"style":545},[12063],{"type":420,"value":12064}," azuread",{"type":415,"tag":532,"props":12066,"children":12067},{"style":551},[12068],{"type":420,"value":432},{"type":415,"tag":532,"props":12070,"children":12071},{"style":656},[12072],{"type":420,"value":12073},"Application",{"type":415,"tag":532,"props":12075,"children":12076},{"style":545},[12077],{"type":420,"value":664},{"type":415,"tag":532,"props":12079,"children":12080},{"style":551},[12081],{"type":420,"value":801},{"type":415,"tag":532,"props":12083,"children":12084},{"style":804},[12085],{"type":420,"value":12086},"AzureReadyApp",{"type":415,"tag":532,"props":12088,"children":12089},{"style":551},[12090],{"type":420,"value":801},{"type":415,"tag":532,"props":12092,"children":12093},{"style":551},[12094],{"type":420,"value":1099},{"type":415,"tag":532,"props":12096,"children":12097},{"style":551},[12098],{"type":420,"value":3347},{"type":415,"tag":532,"props":12100,"children":12101},{"style":3532},[12102],{"type":420,"value":12103}," displayName",{"type":415,"tag":532,"props":12105,"children":12106},{"style":551},[12107],{"type":420,"value":1290},{"type":415,"tag":532,"props":12109,"children":12110},{"style":551},[12111],{"type":420,"value":4041},{"type":415,"tag":532,"props":12113,"children":12114},{"style":804},[12115],{"type":420,"value":12116},"Azure Ready App",{"type":415,"tag":532,"props":12118,"children":12119},{"style":551},[12120],{"type":420,"value":801},{"type":415,"tag":532,"props":12122,"children":12123},{"style":551},[12124],{"type":420,"value":12125}," }",{"type":415,"tag":532,"props":12127,"children":12128},{"style":545},[12129],{"type":420,"value":1349},{"type":415,"tag":532,"props":12131,"children":12132},{"style":551},[12133],{"type":420,"value":563},{"type":415,"tag":532,"props":12135,"children":12136},{"class":534,"line":617},[12137,12141,12146,12150,12154,12158,12162,12166,12170,12174,12179,12183,12187],{"type":415,"tag":532,"props":12138,"children":12139},{"style":954},[12140],{"type":420,"value":11706},{"type":415,"tag":532,"props":12142,"children":12143},{"style":545},[12144],{"type":420,"value":12145}," servicePrincipal ",{"type":415,"tag":532,"props":12147,"children":12148},{"style":551},[12149],{"type":420,"value":1134},{"type":415,"tag":532,"props":12151,"children":12152},{"style":551},[12153],{"type":420,"value":3276},{"type":415,"tag":532,"props":12155,"children":12156},{"style":545},[12157],{"type":420,"value":12064},{"type":415,"tag":532,"props":12159,"children":12160},{"style":551},[12161],{"type":420,"value":432},{"type":415,"tag":532,"props":12163,"children":12164},{"style":656},[12165],{"type":420,"value":9233},{"type":415,"tag":532,"props":12167,"children":12168},{"style":545},[12169],{"type":420,"value":664},{"type":415,"tag":532,"props":12171,"children":12172},{"style":551},[12173],{"type":420,"value":801},{"type":415,"tag":532,"props":12175,"children":12176},{"style":804},[12177],{"type":420,"value":12178},"AzureReadServicePrincipal",{"type":415,"tag":532,"props":12180,"children":12181},{"style":551},[12182],{"type":420,"value":801},{"type":415,"tag":532,"props":12184,"children":12185},{"style":551},[12186],{"type":420,"value":1099},{"type":415,"tag":532,"props":12188,"children":12189},{"style":551},[12190],{"type":420,"value":11759},{"type":415,"tag":532,"props":12192,"children":12193},{"class":534,"line":627},[12194,12199,12203,12207,12211,12216],{"type":415,"tag":532,"props":12195,"children":12196},{"style":3532},[12197],{"type":420,"value":12198},"  applicationId",{"type":415,"tag":532,"props":12200,"children":12201},{"style":551},[12202],{"type":420,"value":1290},{"type":415,"tag":532,"props":12204,"children":12205},{"style":545},[12206],{"type":420,"value":8903},{"type":415,"tag":532,"props":12208,"children":12209},{"style":551},[12210],{"type":420,"value":432},{"type":415,"tag":532,"props":12212,"children":12213},{"style":545},[12214],{"type":420,"value":12215},"applicationId",{"type":415,"tag":532,"props":12217,"children":12218},{"style":551},[12219],{"type":420,"value":7400},{"type":415,"tag":532,"props":12221,"children":12222},{"class":534,"line":677},[12223,12227,12231],{"type":415,"tag":532,"props":12224,"children":12225},{"style":551},[12226],{"type":420,"value":4864},{"type":415,"tag":532,"props":12228,"children":12229},{"style":545},[12230],{"type":420,"value":1349},{"type":415,"tag":532,"props":12232,"children":12233},{"style":551},[12234],{"type":420,"value":563},{"type":415,"tag":416,"props":12236,"children":12237},{},[12238,12240,12249],{"type":420,"value":12239},"The OIDC trust thing is a bit more complex. Fortunately, Microsoft's documentation has a detailed page ",{"type":415,"tag":423,"props":12241,"children":12243},{"href":11250,"rel":12242},[427],[12244],{"type":415,"tag":7033,"props":12245,"children":12246},{},[12247],{"type":420,"value":12248},"Configuring an app to trust an external identity provider",{"type":420,"value":12250}," that explains everything and shows how to add a federated identity for GitHub Actions using the Azure Portal, Azure CLI, or Azure PowerShell.",{"type":415,"tag":416,"props":12252,"children":12253},{},[12254],{"type":420,"value":12255},"Let's do the same thing using TypeScript and Pulumi Azure AD provider:",{"type":415,"tag":523,"props":12257,"children":12259},{"className":11642,"code":12258,"language":357,"meta":401,"style":401},"new azuread.ApplicationFederatedIdentityCredential(\"AzureReadyAppFederatedIdentityCredential\", {\n  applicationObjectId: aadApplication.objectId,\n  displayName: \"AzureReadyDeploys\",\n  description: \"Deployments for azure-ready-repository\",\n  audiences: [\"api://AzureADTokenExchange\"],\n  issuer: \"https://token.actions.githubusercontent.com\",\n  subject: pulumi.interpolate`repo:${repository.fullName}:ref:refs/heads/main`,\n});\n",[12260],{"type":415,"tag":468,"props":12261,"children":12262},{"__ignoreMap":401},[12263,12308,12337,12365,12393,12430,12458,12527],{"type":415,"tag":532,"props":12264,"children":12265},{"class":534,"line":535},[12266,12270,12274,12278,12283,12287,12291,12296,12300,12304],{"type":415,"tag":532,"props":12267,"children":12268},{"style":551},[12269],{"type":420,"value":9142},{"type":415,"tag":532,"props":12271,"children":12272},{"style":545},[12273],{"type":420,"value":12064},{"type":415,"tag":532,"props":12275,"children":12276},{"style":551},[12277],{"type":420,"value":432},{"type":415,"tag":532,"props":12279,"children":12280},{"style":656},[12281],{"type":420,"value":12282},"ApplicationFederatedIdentityCredential",{"type":415,"tag":532,"props":12284,"children":12285},{"style":545},[12286],{"type":420,"value":664},{"type":415,"tag":532,"props":12288,"children":12289},{"style":551},[12290],{"type":420,"value":801},{"type":415,"tag":532,"props":12292,"children":12293},{"style":804},[12294],{"type":420,"value":12295},"AzureReadyAppFederatedIdentityCredential",{"type":415,"tag":532,"props":12297,"children":12298},{"style":551},[12299],{"type":420,"value":801},{"type":415,"tag":532,"props":12301,"children":12302},{"style":551},[12303],{"type":420,"value":1099},{"type":415,"tag":532,"props":12305,"children":12306},{"style":551},[12307],{"type":420,"value":11759},{"type":415,"tag":532,"props":12309,"children":12310},{"class":534,"line":566},[12311,12316,12320,12324,12328,12333],{"type":415,"tag":532,"props":12312,"children":12313},{"style":3532},[12314],{"type":420,"value":12315},"  applicationObjectId",{"type":415,"tag":532,"props":12317,"children":12318},{"style":551},[12319],{"type":420,"value":1290},{"type":415,"tag":532,"props":12321,"children":12322},{"style":545},[12323],{"type":420,"value":8903},{"type":415,"tag":532,"props":12325,"children":12326},{"style":551},[12327],{"type":420,"value":432},{"type":415,"tag":532,"props":12329,"children":12330},{"style":545},[12331],{"type":420,"value":12332},"objectId",{"type":415,"tag":532,"props":12334,"children":12335},{"style":551},[12336],{"type":420,"value":7400},{"type":415,"tag":532,"props":12338,"children":12339},{"class":534,"line":583},[12340,12345,12349,12353,12357,12361],{"type":415,"tag":532,"props":12341,"children":12342},{"style":3532},[12343],{"type":420,"value":12344},"  displayName",{"type":415,"tag":532,"props":12346,"children":12347},{"style":551},[12348],{"type":420,"value":1290},{"type":415,"tag":532,"props":12350,"children":12351},{"style":551},[12352],{"type":420,"value":4041},{"type":415,"tag":532,"props":12354,"children":12355},{"style":804},[12356],{"type":420,"value":9453},{"type":415,"tag":532,"props":12358,"children":12359},{"style":551},[12360],{"type":420,"value":801},{"type":415,"tag":532,"props":12362,"children":12363},{"style":551},[12364],{"type":420,"value":7400},{"type":415,"tag":532,"props":12366,"children":12367},{"class":534,"line":617},[12368,12373,12377,12381,12385,12389],{"type":415,"tag":532,"props":12369,"children":12370},{"style":3532},[12371],{"type":420,"value":12372},"  description",{"type":415,"tag":532,"props":12374,"children":12375},{"style":551},[12376],{"type":420,"value":1290},{"type":415,"tag":532,"props":12378,"children":12379},{"style":551},[12380],{"type":420,"value":4041},{"type":415,"tag":532,"props":12382,"children":12383},{"style":804},[12384],{"type":420,"value":9481},{"type":415,"tag":532,"props":12386,"children":12387},{"style":551},[12388],{"type":420,"value":801},{"type":415,"tag":532,"props":12390,"children":12391},{"style":551},[12392],{"type":420,"value":7400},{"type":415,"tag":532,"props":12394,"children":12395},{"class":534,"line":627},[12396,12401,12405,12410,12414,12418,12422,12426],{"type":415,"tag":532,"props":12397,"children":12398},{"style":3532},[12399],{"type":420,"value":12400},"  audiences",{"type":415,"tag":532,"props":12402,"children":12403},{"style":551},[12404],{"type":420,"value":1290},{"type":415,"tag":532,"props":12406,"children":12407},{"style":545},[12408],{"type":420,"value":12409}," [",{"type":415,"tag":532,"props":12411,"children":12412},{"style":551},[12413],{"type":420,"value":801},{"type":415,"tag":532,"props":12415,"children":12416},{"style":804},[12417],{"type":420,"value":4941},{"type":415,"tag":532,"props":12419,"children":12420},{"style":551},[12421],{"type":420,"value":801},{"type":415,"tag":532,"props":12423,"children":12424},{"style":545},[12425],{"type":420,"value":7449},{"type":415,"tag":532,"props":12427,"children":12428},{"style":551},[12429],{"type":420,"value":7400},{"type":415,"tag":532,"props":12431,"children":12432},{"class":534,"line":677},[12433,12438,12442,12446,12450,12454],{"type":415,"tag":532,"props":12434,"children":12435},{"style":3532},[12436],{"type":420,"value":12437},"  issuer",{"type":415,"tag":532,"props":12439,"children":12440},{"style":551},[12441],{"type":420,"value":1290},{"type":415,"tag":532,"props":12443,"children":12444},{"style":551},[12445],{"type":420,"value":4041},{"type":415,"tag":532,"props":12447,"children":12448},{"style":804},[12449],{"type":420,"value":4826},{"type":415,"tag":532,"props":12451,"children":12452},{"style":551},[12453],{"type":420,"value":801},{"type":415,"tag":532,"props":12455,"children":12456},{"style":551},[12457],{"type":420,"value":7400},{"type":415,"tag":532,"props":12459,"children":12460},{"class":534,"line":719},[12461,12466,12470,12475,12479,12484,12489,12493,12497,12502,12506,12511,12515,12519,12523],{"type":415,"tag":532,"props":12462,"children":12463},{"style":3532},[12464],{"type":420,"value":12465},"  subject",{"type":415,"tag":532,"props":12467,"children":12468},{"style":551},[12469],{"type":420,"value":1290},{"type":415,"tag":532,"props":12471,"children":12472},{"style":545},[12473],{"type":420,"value":12474}," pulumi",{"type":415,"tag":532,"props":12476,"children":12477},{"style":551},[12478],{"type":420,"value":432},{"type":415,"tag":532,"props":12480,"children":12481},{"style":656},[12482],{"type":420,"value":12483},"interpolate",{"type":415,"tag":532,"props":12485,"children":12486},{"style":551},[12487],{"type":420,"value":12488},"`",{"type":415,"tag":532,"props":12490,"children":12491},{"style":804},[12492],{"type":420,"value":4851},{"type":415,"tag":532,"props":12494,"children":12495},{"style":551},[12496],{"type":420,"value":4493},{"type":415,"tag":532,"props":12498,"children":12499},{"style":545},[12500],{"type":420,"value":12501},"repository",{"type":415,"tag":532,"props":12503,"children":12504},{"style":551},[12505],{"type":420,"value":432},{"type":415,"tag":532,"props":12507,"children":12508},{"style":545},[12509],{"type":420,"value":12510},"fullName",{"type":415,"tag":532,"props":12512,"children":12513},{"style":551},[12514],{"type":420,"value":4864},{"type":415,"tag":532,"props":12516,"children":12517},{"style":804},[12518],{"type":420,"value":4869},{"type":415,"tag":532,"props":12520,"children":12521},{"style":551},[12522],{"type":420,"value":12488},{"type":415,"tag":532,"props":12524,"children":12525},{"style":551},[12526],{"type":420,"value":7400},{"type":415,"tag":532,"props":12528,"children":12529},{"class":534,"line":758},[12530,12534,12538],{"type":415,"tag":532,"props":12531,"children":12532},{"style":551},[12533],{"type":420,"value":4864},{"type":415,"tag":532,"props":12535,"children":12536},{"style":545},[12537],{"type":420,"value":1349},{"type":415,"tag":532,"props":12539,"children":12540},{"style":551},[12541],{"type":420,"value":563},{"type":415,"tag":416,"props":12543,"children":12544},{},[12545,12546,12551,12553,12558,12560,12565],{"type":420,"value":4968},{"type":415,"tag":468,"props":12547,"children":12549},{"className":12548},[],[12550],{"type":420,"value":4974},{"type":420,"value":12552}," property is what identifies the repository where the GitHub Actions workflow will be authorized to exchange its GitHub token for an Azure access token. It's worth noting that it will only work if the GitHub Actions workflow is run on the git reference (branch or tag) or the environment you specify in ",{"type":415,"tag":468,"props":12554,"children":12556},{"className":12555},[],[12557],{"type":420,"value":4974},{"type":420,"value":12559},". You can also specify that only workflows triggered by a pull request should be authorized. Here, I have used the ",{"type":415,"tag":468,"props":12561,"children":12563},{"className":12562},[],[12564],{"type":420,"value":11042},{"type":420,"value":12566}," branch but I could create multiple Federated Identity Credentials with different subjects if needed.",{"type":415,"tag":416,"props":12568,"children":12569},{},[12570],{"type":420,"value":12571},"With this configuration, the GitHub Actions workflow we create next will be able to obtain a valid Azure access token.",{"type":415,"tag":416,"props":12573,"children":12574},{},[12575,12577,12584],{"type":420,"value":12576},"If you are interested in gaining a better understanding of how all this works, you can refer to ",{"type":415,"tag":423,"props":12578,"children":12581},{"href":12579,"rel":12580},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation#how-it-works",[427],[12582],{"type":420,"value":12583},"this diagram",{"type":420,"value":12585}," from Microsoft's documentation (with GitHub serving as the external identity provider in our case).",{"type":415,"tag":416,"props":12587,"children":12588},{},[12589],{"type":415,"tag":3882,"props":12590,"children":12594},{"alt":12591,"className":12592,"src":12593},"Sequence diagram explaining Azure OIDC.",[3886,3887],"/posts/images/azurereadygithub_identityfederation.webp",[],{"type":415,"tag":3914,"props":12596,"children":12598},{"id":12597},"authorize-the-service-principal-to-provision-resources-on-the-subscription",[12599],{"type":420,"value":12600},"Authorize the Service Principal to provision resources on the subscription",{"type":415,"tag":416,"props":12602,"children":12603},{},[12604],{"type":420,"value":12605},"We have created everything we need to get a valid Azure access token, but we still have not authorized the application to provision resources on our subscription.",{"type":415,"tag":416,"props":12607,"children":12608},{},[12609],{"type":420,"value":12610},"We can do that by giving the Contributor role to our service principal.",{"type":415,"tag":523,"props":12612,"children":12614},{"className":11642,"code":12613,"language":357,"meta":401,"style":401},"import * as authorization from \"@pulumi/azure-native/authorization\";\nimport { azureBuiltInRoles } from \"./builtInRoles\";\n\nnew authorization.RoleAssignment(\"contributor\", {\n  principalId: servicePrincipal.id,\n  principalType: authorization.PrincipalType.ServicePrincipal,\n  roleDefinitionId: azureBuiltInRoles.contributor,\n  scope: pulumi.interpolate`/subscriptions/${subscriptionId}`,\n});\n",[12615],{"type":415,"tag":468,"props":12616,"children":12617},{"__ignoreMap":401},[12618,12659,12701,12708,12753,12781,12818,12846,12895],{"type":415,"tag":532,"props":12619,"children":12620},{"class":534,"line":535},[12621,12625,12629,12633,12638,12642,12646,12651,12655],{"type":415,"tag":532,"props":12622,"children":12623},{"style":1241},[12624],{"type":420,"value":11655},{"type":415,"tag":532,"props":12626,"children":12627},{"style":551},[12628],{"type":420,"value":11660},{"type":415,"tag":532,"props":12630,"children":12631},{"style":1241},[12632],{"type":420,"value":11665},{"type":415,"tag":532,"props":12634,"children":12635},{"style":545},[12636],{"type":420,"value":12637}," authorization ",{"type":415,"tag":532,"props":12639,"children":12640},{"style":1241},[12641],{"type":420,"value":11675},{"type":415,"tag":532,"props":12643,"children":12644},{"style":551},[12645],{"type":420,"value":4041},{"type":415,"tag":532,"props":12647,"children":12648},{"style":804},[12649],{"type":420,"value":12650},"@pulumi/azure-native/authorization",{"type":415,"tag":532,"props":12652,"children":12653},{"style":551},[12654],{"type":420,"value":801},{"type":415,"tag":532,"props":12656,"children":12657},{"style":551},[12658],{"type":420,"value":563},{"type":415,"tag":532,"props":12660,"children":12661},{"class":534,"line":566},[12662,12666,12670,12675,12679,12684,12688,12693,12697],{"type":415,"tag":532,"props":12663,"children":12664},{"style":1241},[12665],{"type":420,"value":11655},{"type":415,"tag":532,"props":12667,"children":12668},{"style":551},[12669],{"type":420,"value":3347},{"type":415,"tag":532,"props":12671,"children":12672},{"style":545},[12673],{"type":420,"value":12674}," azureBuiltInRoles",{"type":415,"tag":532,"props":12676,"children":12677},{"style":551},[12678],{"type":420,"value":12125},{"type":415,"tag":532,"props":12680,"children":12681},{"style":1241},[12682],{"type":420,"value":12683}," from",{"type":415,"tag":532,"props":12685,"children":12686},{"style":551},[12687],{"type":420,"value":4041},{"type":415,"tag":532,"props":12689,"children":12690},{"style":804},[12691],{"type":420,"value":12692},"./builtInRoles",{"type":415,"tag":532,"props":12694,"children":12695},{"style":551},[12696],{"type":420,"value":801},{"type":415,"tag":532,"props":12698,"children":12699},{"style":551},[12700],{"type":420,"value":563},{"type":415,"tag":532,"props":12702,"children":12703},{"class":534,"line":583},[12704],{"type":415,"tag":532,"props":12705,"children":12706},{"emptyLinePlaceholder":621},[12707],{"type":420,"value":624},{"type":415,"tag":532,"props":12709,"children":12710},{"class":534,"line":617},[12711,12715,12720,12724,12729,12733,12737,12741,12745,12749],{"type":415,"tag":532,"props":12712,"children":12713},{"style":551},[12714],{"type":420,"value":9142},{"type":415,"tag":532,"props":12716,"children":12717},{"style":545},[12718],{"type":420,"value":12719}," authorization",{"type":415,"tag":532,"props":12721,"children":12722},{"style":551},[12723],{"type":420,"value":432},{"type":415,"tag":532,"props":12725,"children":12726},{"style":656},[12727],{"type":420,"value":12728},"RoleAssignment",{"type":415,"tag":532,"props":12730,"children":12731},{"style":545},[12732],{"type":420,"value":664},{"type":415,"tag":532,"props":12734,"children":12735},{"style":551},[12736],{"type":420,"value":801},{"type":415,"tag":532,"props":12738,"children":12739},{"style":804},[12740],{"type":420,"value":9160},{"type":415,"tag":532,"props":12742,"children":12743},{"style":551},[12744],{"type":420,"value":801},{"type":415,"tag":532,"props":12746,"children":12747},{"style":551},[12748],{"type":420,"value":1099},{"type":415,"tag":532,"props":12750,"children":12751},{"style":551},[12752],{"type":420,"value":11759},{"type":415,"tag":532,"props":12754,"children":12755},{"class":534,"line":627},[12756,12761,12765,12769,12773,12777],{"type":415,"tag":532,"props":12757,"children":12758},{"style":3532},[12759],{"type":420,"value":12760},"  principalId",{"type":415,"tag":532,"props":12762,"children":12763},{"style":551},[12764],{"type":420,"value":1290},{"type":415,"tag":532,"props":12766,"children":12767},{"style":545},[12768],{"type":420,"value":8377},{"type":415,"tag":532,"props":12770,"children":12771},{"style":551},[12772],{"type":420,"value":432},{"type":415,"tag":532,"props":12774,"children":12775},{"style":545},[12776],{"type":420,"value":4326},{"type":415,"tag":532,"props":12778,"children":12779},{"style":551},[12780],{"type":420,"value":7400},{"type":415,"tag":532,"props":12782,"children":12783},{"class":534,"line":677},[12784,12789,12793,12797,12801,12806,12810,12814],{"type":415,"tag":532,"props":12785,"children":12786},{"style":3532},[12787],{"type":420,"value":12788},"  principalType",{"type":415,"tag":532,"props":12790,"children":12791},{"style":551},[12792],{"type":420,"value":1290},{"type":415,"tag":532,"props":12794,"children":12795},{"style":545},[12796],{"type":420,"value":12719},{"type":415,"tag":532,"props":12798,"children":12799},{"style":551},[12800],{"type":420,"value":432},{"type":415,"tag":532,"props":12802,"children":12803},{"style":545},[12804],{"type":420,"value":12805},"PrincipalType",{"type":415,"tag":532,"props":12807,"children":12808},{"style":551},[12809],{"type":420,"value":432},{"type":415,"tag":532,"props":12811,"children":12812},{"style":545},[12813],{"type":420,"value":9233},{"type":415,"tag":532,"props":12815,"children":12816},{"style":551},[12817],{"type":420,"value":7400},{"type":415,"tag":532,"props":12819,"children":12820},{"class":534,"line":719},[12821,12826,12830,12834,12838,12842],{"type":415,"tag":532,"props":12822,"children":12823},{"style":3532},[12824],{"type":420,"value":12825},"  roleDefinitionId",{"type":415,"tag":532,"props":12827,"children":12828},{"style":551},[12829],{"type":420,"value":1290},{"type":415,"tag":532,"props":12831,"children":12832},{"style":545},[12833],{"type":420,"value":12674},{"type":415,"tag":532,"props":12835,"children":12836},{"style":551},[12837],{"type":420,"value":432},{"type":415,"tag":532,"props":12839,"children":12840},{"style":545},[12841],{"type":420,"value":9160},{"type":415,"tag":532,"props":12843,"children":12844},{"style":551},[12845],{"type":420,"value":7400},{"type":415,"tag":532,"props":12847,"children":12848},{"class":534,"line":758},[12849,12854,12858,12862,12866,12870,12874,12878,12882,12886,12891],{"type":415,"tag":532,"props":12850,"children":12851},{"style":3532},[12852],{"type":420,"value":12853},"  scope",{"type":415,"tag":532,"props":12855,"children":12856},{"style":551},[12857],{"type":420,"value":1290},{"type":415,"tag":532,"props":12859,"children":12860},{"style":545},[12861],{"type":420,"value":12474},{"type":415,"tag":532,"props":12863,"children":12864},{"style":551},[12865],{"type":420,"value":432},{"type":415,"tag":532,"props":12867,"children":12868},{"style":656},[12869],{"type":420,"value":12483},{"type":415,"tag":532,"props":12871,"children":12872},{"style":551},[12873],{"type":420,"value":12488},{"type":415,"tag":532,"props":12875,"children":12876},{"style":804},[12877],{"type":420,"value":8743},{"type":415,"tag":532,"props":12879,"children":12880},{"style":551},[12881],{"type":420,"value":4493},{"type":415,"tag":532,"props":12883,"children":12884},{"style":545},[12885],{"type":420,"value":4299},{"type":415,"tag":532,"props":12887,"children":12888},{"style":551},[12889],{"type":420,"value":12890},"}`",{"type":415,"tag":532,"props":12892,"children":12893},{"style":551},[12894],{"type":420,"value":7400},{"type":415,"tag":532,"props":12896,"children":12897},{"class":534,"line":767},[12898,12902,12906],{"type":415,"tag":532,"props":12899,"children":12900},{"style":551},[12901],{"type":420,"value":4864},{"type":415,"tag":532,"props":12903,"children":12904},{"style":545},[12905],{"type":420,"value":1349},{"type":415,"tag":532,"props":12907,"children":12908},{"style":551},[12909],{"type":420,"value":563},{"type":415,"tag":416,"props":12911,"children":12912},{},[12913,12915,12920],{"type":420,"value":12914},"I intentionally did not declare the variable ",{"type":415,"tag":468,"props":12916,"children":12918},{"className":12917},[],[12919],{"type":420,"value":4299},{"type":420,"value":12921}," in the code above. It's because it's up to you to choose how you will provide it. You may want to set it in the configuration and retrieve it from it :",{"type":415,"tag":523,"props":12923,"children":12925},{"className":11642,"code":12924,"language":357,"meta":401,"style":401},"const config = new pulumi.Config();\nconst subscriptionId = config.get(\"subscriptionId\");\n",[12926],{"type":415,"tag":468,"props":12927,"children":12928},{"__ignoreMap":401},[12929,12971],{"type":415,"tag":532,"props":12930,"children":12931},{"class":534,"line":535},[12932,12936,12941,12945,12949,12953,12957,12962,12967],{"type":415,"tag":532,"props":12933,"children":12934},{"style":954},[12935],{"type":420,"value":11706},{"type":415,"tag":532,"props":12937,"children":12938},{"style":545},[12939],{"type":420,"value":12940}," config ",{"type":415,"tag":532,"props":12942,"children":12943},{"style":551},[12944],{"type":420,"value":1134},{"type":415,"tag":532,"props":12946,"children":12947},{"style":551},[12948],{"type":420,"value":3276},{"type":415,"tag":532,"props":12950,"children":12951},{"style":545},[12952],{"type":420,"value":12474},{"type":415,"tag":532,"props":12954,"children":12955},{"style":551},[12956],{"type":420,"value":432},{"type":415,"tag":532,"props":12958,"children":12959},{"style":656},[12960],{"type":420,"value":12961},"Config",{"type":415,"tag":532,"props":12963,"children":12964},{"style":545},[12965],{"type":420,"value":12966},"()",{"type":415,"tag":532,"props":12968,"children":12969},{"style":551},[12970],{"type":420,"value":563},{"type":415,"tag":532,"props":12972,"children":12973},{"class":534,"line":566},[12974,12978,12983,12987,12991,12995,13000,13004,13008,13012,13016,13020],{"type":415,"tag":532,"props":12975,"children":12976},{"style":954},[12977],{"type":420,"value":11706},{"type":415,"tag":532,"props":12979,"children":12980},{"style":545},[12981],{"type":420,"value":12982}," subscriptionId ",{"type":415,"tag":532,"props":12984,"children":12985},{"style":551},[12986],{"type":420,"value":1134},{"type":415,"tag":532,"props":12988,"children":12989},{"style":545},[12990],{"type":420,"value":7206},{"type":415,"tag":532,"props":12992,"children":12993},{"style":551},[12994],{"type":420,"value":432},{"type":415,"tag":532,"props":12996,"children":12997},{"style":656},[12998],{"type":420,"value":12999},"get",{"type":415,"tag":532,"props":13001,"children":13002},{"style":545},[13003],{"type":420,"value":664},{"type":415,"tag":532,"props":13005,"children":13006},{"style":551},[13007],{"type":420,"value":801},{"type":415,"tag":532,"props":13009,"children":13010},{"style":804},[13011],{"type":420,"value":4299},{"type":415,"tag":532,"props":13013,"children":13014},{"style":551},[13015],{"type":420,"value":801},{"type":415,"tag":532,"props":13017,"children":13018},{"style":545},[13019],{"type":420,"value":1349},{"type":415,"tag":532,"props":13021,"children":13022},{"style":551},[13023],{"type":420,"value":563},{"type":415,"tag":416,"props":13025,"children":13026},{},[13027],{"type":420,"value":13028},"Or your might want to retrieve it from the current configuration of the Azure native provider :",{"type":415,"tag":523,"props":13030,"children":13032},{"className":11642,"code":13031,"language":357,"meta":401,"style":401},"const azureConfig = pulumi.output(authorization.getClientConfig());\nconst subscriptionId = azureConfig.subscriptionId;\n",[13033],{"type":415,"tag":468,"props":13034,"children":13035},{"__ignoreMap":401},[13036,13087],{"type":415,"tag":532,"props":13037,"children":13038},{"class":534,"line":535},[13039,13043,13048,13052,13056,13060,13064,13069,13073,13078,13083],{"type":415,"tag":532,"props":13040,"children":13041},{"style":954},[13042],{"type":420,"value":11706},{"type":415,"tag":532,"props":13044,"children":13045},{"style":545},[13046],{"type":420,"value":13047}," azureConfig ",{"type":415,"tag":532,"props":13049,"children":13050},{"style":551},[13051],{"type":420,"value":1134},{"type":415,"tag":532,"props":13053,"children":13054},{"style":545},[13055],{"type":420,"value":12474},{"type":415,"tag":532,"props":13057,"children":13058},{"style":551},[13059],{"type":420,"value":432},{"type":415,"tag":532,"props":13061,"children":13062},{"style":656},[13063],{"type":420,"value":11926},{"type":415,"tag":532,"props":13065,"children":13066},{"style":545},[13067],{"type":420,"value":13068},"(authorization",{"type":415,"tag":532,"props":13070,"children":13071},{"style":551},[13072],{"type":420,"value":432},{"type":415,"tag":532,"props":13074,"children":13075},{"style":656},[13076],{"type":420,"value":13077},"getClientConfig",{"type":415,"tag":532,"props":13079,"children":13080},{"style":545},[13081],{"type":420,"value":13082},"())",{"type":415,"tag":532,"props":13084,"children":13085},{"style":551},[13086],{"type":420,"value":563},{"type":415,"tag":532,"props":13088,"children":13089},{"class":534,"line":566},[13090,13094,13098,13102,13106,13110,13114],{"type":415,"tag":532,"props":13091,"children":13092},{"style":954},[13093],{"type":420,"value":11706},{"type":415,"tag":532,"props":13095,"children":13096},{"style":545},[13097],{"type":420,"value":12982},{"type":415,"tag":532,"props":13099,"children":13100},{"style":551},[13101],{"type":420,"value":1134},{"type":415,"tag":532,"props":13103,"children":13104},{"style":545},[13105],{"type":420,"value":8436},{"type":415,"tag":532,"props":13107,"children":13108},{"style":551},[13109],{"type":420,"value":432},{"type":415,"tag":532,"props":13111,"children":13112},{"style":545},[13113],{"type":420,"value":4299},{"type":415,"tag":532,"props":13115,"children":13116},{"style":551},[13117],{"type":420,"value":563},{"type":415,"tag":416,"props":13119,"children":13120},{},[13121,13123,13129,13131,13137],{"type":420,"value":13122},"Concerning, the contributor role definition identifier, I could have dynamically retrieved it using Azure APIs (like ",{"type":415,"tag":423,"props":13124,"children":13127},{"href":13125,"rel":13126},"https://github.com/pulumi/examples/blob/master/azure-ts-call-azure-sdk/index.ts",[427],[13128],{"type":420,"value":4427},{"type":420,"value":13130},"). But honestly, as these identifiers don't change it's much easier to hardcode it in a dedicated ",{"type":415,"tag":468,"props":13132,"children":13134},{"className":13133},[],[13135],{"type":420,"value":13136},"builtInRoles.ts",{"type":420,"value":13138}," file.",{"type":415,"tag":523,"props":13140,"children":13142},{"className":11642,"code":13141,"language":357,"meta":401,"style":401},"export const azureBuiltInRoles = {\n  contributor : \"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c\"\n};\n",[13143],{"type":415,"tag":468,"props":13144,"children":13145},{"__ignoreMap":401},[13146,13170,13195],{"type":415,"tag":532,"props":13147,"children":13148},{"class":534,"line":535},[13149,13153,13157,13162,13166],{"type":415,"tag":532,"props":13150,"children":13151},{"style":1241},[13152],{"type":420,"value":11862},{"type":415,"tag":532,"props":13154,"children":13155},{"style":954},[13156],{"type":420,"value":11867},{"type":415,"tag":532,"props":13158,"children":13159},{"style":545},[13160],{"type":420,"value":13161}," azureBuiltInRoles ",{"type":415,"tag":532,"props":13163,"children":13164},{"style":551},[13165],{"type":420,"value":1134},{"type":415,"tag":532,"props":13167,"children":13168},{"style":551},[13169],{"type":420,"value":11759},{"type":415,"tag":532,"props":13171,"children":13172},{"class":534,"line":566},[13173,13178,13182,13186,13191],{"type":415,"tag":532,"props":13174,"children":13175},{"style":3532},[13176],{"type":420,"value":13177},"  contributor ",{"type":415,"tag":532,"props":13179,"children":13180},{"style":551},[13181],{"type":420,"value":1290},{"type":415,"tag":532,"props":13183,"children":13184},{"style":551},[13185],{"type":420,"value":4041},{"type":415,"tag":532,"props":13187,"children":13188},{"style":804},[13189],{"type":420,"value":13190},"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c",{"type":415,"tag":532,"props":13192,"children":13193},{"style":551},[13194],{"type":420,"value":4051},{"type":415,"tag":532,"props":13196,"children":13197},{"class":534,"line":583},[13198],{"type":415,"tag":532,"props":13199,"children":13200},{"style":551},[13201],{"type":420,"value":10828},{"type":415,"tag":434,"props":13203,"children":13204},{"icon":436},[13205],{"type":415,"tag":416,"props":13206,"children":13207},{},[13208],{"type":420,"value":13209},"Please note that you don't have to work on the subscription scope. If you prefer to assign the contributor role (or any other role) to an existing resource group rather than the entire subscription, you can certainly do that as well.",{"type":415,"tag":3914,"props":13211,"children":13213},{"id":13212},"add-the-configuration-for-the-github-actions-workflow",[13214],{"type":420,"value":13215},"Add the configuration for the GitHub Actions workflow",{"type":415,"tag":416,"props":13217,"children":13218},{},[13219],{"type":420,"value":13220},"The next step is to correctly set the configuration for the GitHub Actions of our Azure-Ready GitHub repository.",{"type":415,"tag":416,"props":13222,"children":13223},{},[13224],{"type":420,"value":13225},"The workflow requires three pieces of information for the OIDC authentication to function properly:",{"type":415,"tag":5188,"props":13227,"children":13228},{},[13229,13233,13237],{"type":415,"tag":512,"props":13230,"children":13231},{},[13232],{"type":420,"value":5195},{"type":415,"tag":512,"props":13234,"children":13235},{},[13236],{"type":420,"value":5200},{"type":415,"tag":512,"props":13238,"children":13239},{},[13240],{"type":420,"value":13241},"The application identifier (also known as client ID) of the previously created Azure AD application",{"type":415,"tag":416,"props":13243,"children":13244},{},[13245],{"type":420,"value":13246},"These identifiers are not secrets, they are just identifiers so we could directly set them as GitHub Actions variables like this:",{"type":415,"tag":523,"props":13248,"children":13250},{"className":11642,"code":13249,"language":357,"meta":401,"style":401},"new github.ActionsVariable(\"tenantId\", {\n  repository: repository.name,\n  variableName: \"ARM_TENANT_ID\",\n  value: azureConfig.tenantId,\n});\n",[13251],{"type":415,"tag":468,"props":13252,"children":13253},{"__ignoreMap":401},[13254,13298,13326,13355,13383],{"type":415,"tag":532,"props":13255,"children":13256},{"class":534,"line":535},[13257,13261,13265,13269,13274,13278,13282,13286,13290,13294],{"type":415,"tag":532,"props":13258,"children":13259},{"style":551},[13260],{"type":420,"value":9142},{"type":415,"tag":532,"props":13262,"children":13263},{"style":545},[13264],{"type":420,"value":11724},{"type":415,"tag":532,"props":13266,"children":13267},{"style":551},[13268],{"type":420,"value":432},{"type":415,"tag":532,"props":13270,"children":13271},{"style":656},[13272],{"type":420,"value":13273},"ActionsVariable",{"type":415,"tag":532,"props":13275,"children":13276},{"style":545},[13277],{"type":420,"value":664},{"type":415,"tag":532,"props":13279,"children":13280},{"style":551},[13281],{"type":420,"value":801},{"type":415,"tag":532,"props":13283,"children":13284},{"style":804},[13285],{"type":420,"value":4356},{"type":415,"tag":532,"props":13287,"children":13288},{"style":551},[13289],{"type":420,"value":801},{"type":415,"tag":532,"props":13291,"children":13292},{"style":551},[13293],{"type":420,"value":1099},{"type":415,"tag":532,"props":13295,"children":13296},{"style":551},[13297],{"type":420,"value":11759},{"type":415,"tag":532,"props":13299,"children":13300},{"class":534,"line":566},[13301,13306,13310,13314,13318,13322],{"type":415,"tag":532,"props":13302,"children":13303},{"style":3532},[13304],{"type":420,"value":13305},"  repository",{"type":415,"tag":532,"props":13307,"children":13308},{"style":551},[13309],{"type":420,"value":1290},{"type":415,"tag":532,"props":13311,"children":13312},{"style":545},[13313],{"type":420,"value":7695},{"type":415,"tag":532,"props":13315,"children":13316},{"style":551},[13317],{"type":420,"value":432},{"type":415,"tag":532,"props":13319,"children":13320},{"style":545},[13321],{"type":420,"value":3535},{"type":415,"tag":532,"props":13323,"children":13324},{"style":551},[13325],{"type":420,"value":7400},{"type":415,"tag":532,"props":13327,"children":13328},{"class":534,"line":583},[13329,13334,13338,13342,13347,13351],{"type":415,"tag":532,"props":13330,"children":13331},{"style":3532},[13332],{"type":420,"value":13333},"  variableName",{"type":415,"tag":532,"props":13335,"children":13336},{"style":551},[13337],{"type":420,"value":1290},{"type":415,"tag":532,"props":13339,"children":13340},{"style":551},[13341],{"type":420,"value":4041},{"type":415,"tag":532,"props":13343,"children":13344},{"style":804},[13345],{"type":420,"value":13346},"ARM_TENANT_ID",{"type":415,"tag":532,"props":13348,"children":13349},{"style":551},[13350],{"type":420,"value":801},{"type":415,"tag":532,"props":13352,"children":13353},{"style":551},[13354],{"type":420,"value":7400},{"type":415,"tag":532,"props":13356,"children":13357},{"class":534,"line":617},[13358,13363,13367,13371,13375,13379],{"type":415,"tag":532,"props":13359,"children":13360},{"style":3532},[13361],{"type":420,"value":13362},"  value",{"type":415,"tag":532,"props":13364,"children":13365},{"style":551},[13366],{"type":420,"value":1290},{"type":415,"tag":532,"props":13368,"children":13369},{"style":545},[13370],{"type":420,"value":8436},{"type":415,"tag":532,"props":13372,"children":13373},{"style":551},[13374],{"type":420,"value":432},{"type":415,"tag":532,"props":13376,"children":13377},{"style":545},[13378],{"type":420,"value":4356},{"type":415,"tag":532,"props":13380,"children":13381},{"style":551},[13382],{"type":420,"value":7400},{"type":415,"tag":532,"props":13384,"children":13385},{"class":534,"line":627},[13386,13390,13394],{"type":415,"tag":532,"props":13387,"children":13388},{"style":551},[13389],{"type":420,"value":4864},{"type":415,"tag":532,"props":13391,"children":13392},{"style":545},[13393],{"type":420,"value":1349},{"type":415,"tag":532,"props":13395,"children":13396},{"style":551},[13397],{"type":420,"value":563},{"type":415,"tag":416,"props":13399,"children":13400},{},[13401],{"type":420,"value":13402},"However, I like to keep my tenant id and my subscription id private so we will store them in GitHub secrets but that's not mandatory at all.",{"type":415,"tag":523,"props":13404,"children":13406},{"className":11642,"code":13405,"language":357,"meta":401,"style":401},"const azureConfig = pulumi.output(authorization.getClientConfig());\n\nnew github.ActionsSecret(\"tenantId\", {\n  repository: repository.name,\n  secretName: \"ARM_TENANT_ID\",\n  plaintextValue: azureConfig.tenantId,\n});\n\nnew github.ActionsSecret(\"subscriptionId\", {\n  repository: repository.name,\n  secretName: \"ARM_SUBSCRIPTION_ID\",\n  plaintextValue: azureConfig.subscriptionId,\n});\n\nnew github.ActionsSecret(\"clientId\", {\n  repository: repository.name,\n  secretName: \"ARM_CLIENT_ID\",\n  plaintextValue: aadApplication.applicationId,\n});\n",[13407],{"type":415,"tag":468,"props":13408,"children":13409},{"__ignoreMap":401},[13410,13457,13464,13508,13535,13563,13591,13606,13613,13656,13683,13711,13738,13753,13760,13804,13831,13859,13886],{"type":415,"tag":532,"props":13411,"children":13412},{"class":534,"line":535},[13413,13417,13421,13425,13429,13433,13437,13441,13445,13449,13453],{"type":415,"tag":532,"props":13414,"children":13415},{"style":954},[13416],{"type":420,"value":11706},{"type":415,"tag":532,"props":13418,"children":13419},{"style":545},[13420],{"type":420,"value":13047},{"type":415,"tag":532,"props":13422,"children":13423},{"style":551},[13424],{"type":420,"value":1134},{"type":415,"tag":532,"props":13426,"children":13427},{"style":545},[13428],{"type":420,"value":12474},{"type":415,"tag":532,"props":13430,"children":13431},{"style":551},[13432],{"type":420,"value":432},{"type":415,"tag":532,"props":13434,"children":13435},{"style":656},[13436],{"type":420,"value":11926},{"type":415,"tag":532,"props":13438,"children":13439},{"style":545},[13440],{"type":420,"value":13068},{"type":415,"tag":532,"props":13442,"children":13443},{"style":551},[13444],{"type":420,"value":432},{"type":415,"tag":532,"props":13446,"children":13447},{"style":656},[13448],{"type":420,"value":13077},{"type":415,"tag":532,"props":13450,"children":13451},{"style":545},[13452],{"type":420,"value":13082},{"type":415,"tag":532,"props":13454,"children":13455},{"style":551},[13456],{"type":420,"value":563},{"type":415,"tag":532,"props":13458,"children":13459},{"class":534,"line":566},[13460],{"type":415,"tag":532,"props":13461,"children":13462},{"emptyLinePlaceholder":621},[13463],{"type":420,"value":624},{"type":415,"tag":532,"props":13465,"children":13466},{"class":534,"line":583},[13467,13471,13475,13479,13484,13488,13492,13496,13500,13504],{"type":415,"tag":532,"props":13468,"children":13469},{"style":551},[13470],{"type":420,"value":9142},{"type":415,"tag":532,"props":13472,"children":13473},{"style":545},[13474],{"type":420,"value":11724},{"type":415,"tag":532,"props":13476,"children":13477},{"style":551},[13478],{"type":420,"value":432},{"type":415,"tag":532,"props":13480,"children":13481},{"style":656},[13482],{"type":420,"value":13483},"ActionsSecret",{"type":415,"tag":532,"props":13485,"children":13486},{"style":545},[13487],{"type":420,"value":664},{"type":415,"tag":532,"props":13489,"children":13490},{"style":551},[13491],{"type":420,"value":801},{"type":415,"tag":532,"props":13493,"children":13494},{"style":804},[13495],{"type":420,"value":4356},{"type":415,"tag":532,"props":13497,"children":13498},{"style":551},[13499],{"type":420,"value":801},{"type":415,"tag":532,"props":13501,"children":13502},{"style":551},[13503],{"type":420,"value":1099},{"type":415,"tag":532,"props":13505,"children":13506},{"style":551},[13507],{"type":420,"value":11759},{"type":415,"tag":532,"props":13509,"children":13510},{"class":534,"line":617},[13511,13515,13519,13523,13527,13531],{"type":415,"tag":532,"props":13512,"children":13513},{"style":3532},[13514],{"type":420,"value":13305},{"type":415,"tag":532,"props":13516,"children":13517},{"style":551},[13518],{"type":420,"value":1290},{"type":415,"tag":532,"props":13520,"children":13521},{"style":545},[13522],{"type":420,"value":7695},{"type":415,"tag":532,"props":13524,"children":13525},{"style":551},[13526],{"type":420,"value":432},{"type":415,"tag":532,"props":13528,"children":13529},{"style":545},[13530],{"type":420,"value":3535},{"type":415,"tag":532,"props":13532,"children":13533},{"style":551},[13534],{"type":420,"value":7400},{"type":415,"tag":532,"props":13536,"children":13537},{"class":534,"line":627},[13538,13543,13547,13551,13555,13559],{"type":415,"tag":532,"props":13539,"children":13540},{"style":3532},[13541],{"type":420,"value":13542},"  secretName",{"type":415,"tag":532,"props":13544,"children":13545},{"style":551},[13546],{"type":420,"value":1290},{"type":415,"tag":532,"props":13548,"children":13549},{"style":551},[13550],{"type":420,"value":4041},{"type":415,"tag":532,"props":13552,"children":13553},{"style":804},[13554],{"type":420,"value":13346},{"type":415,"tag":532,"props":13556,"children":13557},{"style":551},[13558],{"type":420,"value":801},{"type":415,"tag":532,"props":13560,"children":13561},{"style":551},[13562],{"type":420,"value":7400},{"type":415,"tag":532,"props":13564,"children":13565},{"class":534,"line":677},[13566,13571,13575,13579,13583,13587],{"type":415,"tag":532,"props":13567,"children":13568},{"style":3532},[13569],{"type":420,"value":13570},"  plaintextValue",{"type":415,"tag":532,"props":13572,"children":13573},{"style":551},[13574],{"type":420,"value":1290},{"type":415,"tag":532,"props":13576,"children":13577},{"style":545},[13578],{"type":420,"value":8436},{"type":415,"tag":532,"props":13580,"children":13581},{"style":551},[13582],{"type":420,"value":432},{"type":415,"tag":532,"props":13584,"children":13585},{"style":545},[13586],{"type":420,"value":4356},{"type":415,"tag":532,"props":13588,"children":13589},{"style":551},[13590],{"type":420,"value":7400},{"type":415,"tag":532,"props":13592,"children":13593},{"class":534,"line":719},[13594,13598,13602],{"type":415,"tag":532,"props":13595,"children":13596},{"style":551},[13597],{"type":420,"value":4864},{"type":415,"tag":532,"props":13599,"children":13600},{"style":545},[13601],{"type":420,"value":1349},{"type":415,"tag":532,"props":13603,"children":13604},{"style":551},[13605],{"type":420,"value":563},{"type":415,"tag":532,"props":13607,"children":13608},{"class":534,"line":758},[13609],{"type":415,"tag":532,"props":13610,"children":13611},{"emptyLinePlaceholder":621},[13612],{"type":420,"value":624},{"type":415,"tag":532,"props":13614,"children":13615},{"class":534,"line":767},[13616,13620,13624,13628,13632,13636,13640,13644,13648,13652],{"type":415,"tag":532,"props":13617,"children":13618},{"style":551},[13619],{"type":420,"value":9142},{"type":415,"tag":532,"props":13621,"children":13622},{"style":545},[13623],{"type":420,"value":11724},{"type":415,"tag":532,"props":13625,"children":13626},{"style":551},[13627],{"type":420,"value":432},{"type":415,"tag":532,"props":13629,"children":13630},{"style":656},[13631],{"type":420,"value":13483},{"type":415,"tag":532,"props":13633,"children":13634},{"style":545},[13635],{"type":420,"value":664},{"type":415,"tag":532,"props":13637,"children":13638},{"style":551},[13639],{"type":420,"value":801},{"type":415,"tag":532,"props":13641,"children":13642},{"style":804},[13643],{"type":420,"value":4299},{"type":415,"tag":532,"props":13645,"children":13646},{"style":551},[13647],{"type":420,"value":801},{"type":415,"tag":532,"props":13649,"children":13650},{"style":551},[13651],{"type":420,"value":1099},{"type":415,"tag":532,"props":13653,"children":13654},{"style":551},[13655],{"type":420,"value":11759},{"type":415,"tag":532,"props":13657,"children":13658},{"class":534,"line":819},[13659,13663,13667,13671,13675,13679],{"type":415,"tag":532,"props":13660,"children":13661},{"style":3532},[13662],{"type":420,"value":13305},{"type":415,"tag":532,"props":13664,"children":13665},{"style":551},[13666],{"type":420,"value":1290},{"type":415,"tag":532,"props":13668,"children":13669},{"style":545},[13670],{"type":420,"value":7695},{"type":415,"tag":532,"props":13672,"children":13673},{"style":551},[13674],{"type":420,"value":432},{"type":415,"tag":532,"props":13676,"children":13677},{"style":545},[13678],{"type":420,"value":3535},{"type":415,"tag":532,"props":13680,"children":13681},{"style":551},[13682],{"type":420,"value":7400},{"type":415,"tag":532,"props":13684,"children":13685},{"class":534,"line":850},[13686,13690,13694,13698,13703,13707],{"type":415,"tag":532,"props":13687,"children":13688},{"style":3532},[13689],{"type":420,"value":13542},{"type":415,"tag":532,"props":13691,"children":13692},{"style":551},[13693],{"type":420,"value":1290},{"type":415,"tag":532,"props":13695,"children":13696},{"style":551},[13697],{"type":420,"value":4041},{"type":415,"tag":532,"props":13699,"children":13700},{"style":804},[13701],{"type":420,"value":13702},"ARM_SUBSCRIPTION_ID",{"type":415,"tag":532,"props":13704,"children":13705},{"style":551},[13706],{"type":420,"value":801},{"type":415,"tag":532,"props":13708,"children":13709},{"style":551},[13710],{"type":420,"value":7400},{"type":415,"tag":532,"props":13712,"children":13713},{"class":534,"line":859},[13714,13718,13722,13726,13730,13734],{"type":415,"tag":532,"props":13715,"children":13716},{"style":3532},[13717],{"type":420,"value":13570},{"type":415,"tag":532,"props":13719,"children":13720},{"style":551},[13721],{"type":420,"value":1290},{"type":415,"tag":532,"props":13723,"children":13724},{"style":545},[13725],{"type":420,"value":8436},{"type":415,"tag":532,"props":13727,"children":13728},{"style":551},[13729],{"type":420,"value":432},{"type":415,"tag":532,"props":13731,"children":13732},{"style":545},[13733],{"type":420,"value":4299},{"type":415,"tag":532,"props":13735,"children":13736},{"style":551},[13737],{"type":420,"value":7400},{"type":415,"tag":532,"props":13739,"children":13740},{"class":534,"line":867},[13741,13745,13749],{"type":415,"tag":532,"props":13742,"children":13743},{"style":551},[13744],{"type":420,"value":4864},{"type":415,"tag":532,"props":13746,"children":13747},{"style":545},[13748],{"type":420,"value":1349},{"type":415,"tag":532,"props":13750,"children":13751},{"style":551},[13752],{"type":420,"value":563},{"type":415,"tag":532,"props":13754,"children":13755},{"class":534,"line":902},[13756],{"type":415,"tag":532,"props":13757,"children":13758},{"emptyLinePlaceholder":621},[13759],{"type":420,"value":624},{"type":415,"tag":532,"props":13761,"children":13762},{"class":534,"line":1302},[13763,13767,13771,13775,13779,13783,13787,13792,13796,13800],{"type":415,"tag":532,"props":13764,"children":13765},{"style":551},[13766],{"type":420,"value":9142},{"type":415,"tag":532,"props":13768,"children":13769},{"style":545},[13770],{"type":420,"value":11724},{"type":415,"tag":532,"props":13772,"children":13773},{"style":551},[13774],{"type":420,"value":432},{"type":415,"tag":532,"props":13776,"children":13777},{"style":656},[13778],{"type":420,"value":13483},{"type":415,"tag":532,"props":13780,"children":13781},{"style":545},[13782],{"type":420,"value":664},{"type":415,"tag":532,"props":13784,"children":13785},{"style":551},[13786],{"type":420,"value":801},{"type":415,"tag":532,"props":13788,"children":13789},{"style":804},[13790],{"type":420,"value":13791},"clientId",{"type":415,"tag":532,"props":13793,"children":13794},{"style":551},[13795],{"type":420,"value":801},{"type":415,"tag":532,"props":13797,"children":13798},{"style":551},[13799],{"type":420,"value":1099},{"type":415,"tag":532,"props":13801,"children":13802},{"style":551},[13803],{"type":420,"value":11759},{"type":415,"tag":532,"props":13805,"children":13806},{"class":534,"line":1311},[13807,13811,13815,13819,13823,13827],{"type":415,"tag":532,"props":13808,"children":13809},{"style":3532},[13810],{"type":420,"value":13305},{"type":415,"tag":532,"props":13812,"children":13813},{"style":551},[13814],{"type":420,"value":1290},{"type":415,"tag":532,"props":13816,"children":13817},{"style":545},[13818],{"type":420,"value":7695},{"type":415,"tag":532,"props":13820,"children":13821},{"style":551},[13822],{"type":420,"value":432},{"type":415,"tag":532,"props":13824,"children":13825},{"style":545},[13826],{"type":420,"value":3535},{"type":415,"tag":532,"props":13828,"children":13829},{"style":551},[13830],{"type":420,"value":7400},{"type":415,"tag":532,"props":13832,"children":13833},{"class":534,"line":1356},[13834,13838,13842,13846,13851,13855],{"type":415,"tag":532,"props":13835,"children":13836},{"style":3532},[13837],{"type":420,"value":13542},{"type":415,"tag":532,"props":13839,"children":13840},{"style":551},[13841],{"type":420,"value":1290},{"type":415,"tag":532,"props":13843,"children":13844},{"style":551},[13845],{"type":420,"value":4041},{"type":415,"tag":532,"props":13847,"children":13848},{"style":804},[13849],{"type":420,"value":13850},"ARM_CLIENT_ID",{"type":415,"tag":532,"props":13852,"children":13853},{"style":551},[13854],{"type":420,"value":801},{"type":415,"tag":532,"props":13856,"children":13857},{"style":551},[13858],{"type":420,"value":7400},{"type":415,"tag":532,"props":13860,"children":13861},{"class":534,"line":1365},[13862,13866,13870,13874,13878,13882],{"type":415,"tag":532,"props":13863,"children":13864},{"style":3532},[13865],{"type":420,"value":13570},{"type":415,"tag":532,"props":13867,"children":13868},{"style":551},[13869],{"type":420,"value":1290},{"type":415,"tag":532,"props":13871,"children":13872},{"style":545},[13873],{"type":420,"value":8903},{"type":415,"tag":532,"props":13875,"children":13876},{"style":551},[13877],{"type":420,"value":432},{"type":415,"tag":532,"props":13879,"children":13880},{"style":545},[13881],{"type":420,"value":12215},{"type":415,"tag":532,"props":13883,"children":13884},{"style":551},[13885],{"type":420,"value":7400},{"type":415,"tag":532,"props":13887,"children":13888},{"class":534,"line":1373},[13889,13893,13897],{"type":415,"tag":532,"props":13890,"children":13891},{"style":551},[13892],{"type":420,"value":4864},{"type":415,"tag":532,"props":13894,"children":13895},{"style":545},[13896],{"type":420,"value":1349},{"type":415,"tag":532,"props":13898,"children":13899},{"style":551},[13900],{"type":420,"value":563},{"type":415,"tag":434,"props":13902,"children":13903},{"icon":6841},[13904],{"type":415,"tag":416,"props":13905,"children":13906},{},[13907,13909,13916],{"type":420,"value":13908},"Please note that could also use ",{"type":415,"tag":423,"props":13910,"children":13913},{"href":13911,"rel":13912},"https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment",[427],[13914],{"type":420,"value":13915},"environments for deployment",{"type":420,"value":13917}," and their associated secrets and variables.",{"type":415,"tag":3914,"props":13919,"children":13921},{"id":13920},"create-the-github-actions-workflow",[13922],{"type":420,"value":13923},"Create the GitHub Actions workflow",{"type":415,"tag":416,"props":13925,"children":13926},{},[13927],{"type":420,"value":13928},"Everything seems to be properly configured to provision Azure resources from a GitHub Actions workflow in this new repository, except for the workflow itself. The goal here is to have a properly configured pipeline in the repository to get started provisioning Azure infrastructure.",{"type":415,"tag":416,"props":13930,"children":13931},{},[13932],{"type":420,"value":13933},"Here is such a pipeline:",{"type":415,"tag":523,"props":13935,"children":13937},{"className":3520,"code":13936,"language":3522,"meta":401,"style":401},"name: infra\n\non:\n  workflow_dispatch:\n\npermissions:\n      id-token: write\n      contents: read\njobs:\n  provision-infra:\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",[13938],{"type":415,"tag":468,"props":13939,"children":13940},{"__ignoreMap":401},[13941,13957,13964,13975,13986,13993,14004,14020,14036,14047,14059,14074,14085,14112,14127,14138,14153,14168,14183,14190,14217,14232,14239],{"type":415,"tag":532,"props":13942,"children":13943},{"class":534,"line":535},[13944,13948,13952],{"type":415,"tag":532,"props":13945,"children":13946},{"style":3532},[13947],{"type":420,"value":3535},{"type":415,"tag":532,"props":13949,"children":13950},{"style":551},[13951],{"type":420,"value":1290},{"type":415,"tag":532,"props":13953,"children":13954},{"style":804},[13955],{"type":420,"value":13956}," infra\n",{"type":415,"tag":532,"props":13958,"children":13959},{"class":534,"line":566},[13960],{"type":415,"tag":532,"props":13961,"children":13962},{"emptyLinePlaceholder":621},[13963],{"type":420,"value":624},{"type":415,"tag":532,"props":13965,"children":13966},{"class":534,"line":583},[13967,13971],{"type":415,"tag":532,"props":13968,"children":13969},{"style":1938},[13970],{"type":420,"value":3552},{"type":415,"tag":532,"props":13972,"children":13973},{"style":551},[13974],{"type":420,"value":3557},{"type":415,"tag":532,"props":13976,"children":13977},{"class":534,"line":617},[13978,13982],{"type":415,"tag":532,"props":13979,"children":13980},{"style":3532},[13981],{"type":420,"value":3565},{"type":415,"tag":532,"props":13983,"children":13984},{"style":551},[13985],{"type":420,"value":3557},{"type":415,"tag":532,"props":13987,"children":13988},{"class":534,"line":627},[13989],{"type":415,"tag":532,"props":13990,"children":13991},{"emptyLinePlaceholder":621},[13992],{"type":420,"value":624},{"type":415,"tag":532,"props":13994,"children":13995},{"class":534,"line":677},[13996,14000],{"type":415,"tag":532,"props":13997,"children":13998},{"style":3532},[13999],{"type":420,"value":3584},{"type":415,"tag":532,"props":14001,"children":14002},{"style":551},[14003],{"type":420,"value":3557},{"type":415,"tag":532,"props":14005,"children":14006},{"class":534,"line":719},[14007,14012,14016],{"type":415,"tag":532,"props":14008,"children":14009},{"style":3532},[14010],{"type":420,"value":14011},"      id-token",{"type":415,"tag":532,"props":14013,"children":14014},{"style":551},[14015],{"type":420,"value":1290},{"type":415,"tag":532,"props":14017,"children":14018},{"style":804},[14019],{"type":420,"value":3605},{"type":415,"tag":532,"props":14021,"children":14022},{"class":534,"line":758},[14023,14028,14032],{"type":415,"tag":532,"props":14024,"children":14025},{"style":3532},[14026],{"type":420,"value":14027},"      contents",{"type":415,"tag":532,"props":14029,"children":14030},{"style":551},[14031],{"type":420,"value":1290},{"type":415,"tag":532,"props":14033,"children":14034},{"style":804},[14035],{"type":420,"value":3622},{"type":415,"tag":532,"props":14037,"children":14038},{"class":534,"line":767},[14039,14043],{"type":415,"tag":532,"props":14040,"children":14041},{"style":3532},[14042],{"type":420,"value":3630},{"type":415,"tag":532,"props":14044,"children":14045},{"style":551},[14046],{"type":420,"value":3557},{"type":415,"tag":532,"props":14048,"children":14049},{"class":534,"line":819},[14050,14055],{"type":415,"tag":532,"props":14051,"children":14052},{"style":3532},[14053],{"type":420,"value":14054},"  provision-infra",{"type":415,"tag":532,"props":14056,"children":14057},{"style":551},[14058],{"type":420,"value":3557},{"type":415,"tag":532,"props":14060,"children":14061},{"class":534,"line":850},[14062,14066,14070],{"type":415,"tag":532,"props":14063,"children":14064},{"style":3532},[14065],{"type":420,"value":3654},{"type":415,"tag":532,"props":14067,"children":14068},{"style":551},[14069],{"type":420,"value":1290},{"type":415,"tag":532,"props":14071,"children":14072},{"style":804},[14073],{"type":420,"value":3663},{"type":415,"tag":532,"props":14075,"children":14076},{"class":534,"line":859},[14077,14081],{"type":415,"tag":532,"props":14078,"children":14079},{"style":3532},[14080],{"type":420,"value":3671},{"type":415,"tag":532,"props":14082,"children":14083},{"style":551},[14084],{"type":420,"value":3557},{"type":415,"tag":532,"props":14086,"children":14087},{"class":534,"line":867},[14088,14092,14096,14100,14104,14108],{"type":415,"tag":532,"props":14089,"children":14090},{"style":551},[14091],{"type":420,"value":3683},{"type":415,"tag":532,"props":14093,"children":14094},{"style":3532},[14095],{"type":420,"value":3688},{"type":415,"tag":532,"props":14097,"children":14098},{"style":551},[14099],{"type":420,"value":1290},{"type":415,"tag":532,"props":14101,"children":14102},{"style":551},[14103],{"type":420,"value":3697},{"type":415,"tag":532,"props":14105,"children":14106},{"style":804},[14107],{"type":420,"value":3702},{"type":415,"tag":532,"props":14109,"children":14110},{"style":551},[14111],{"type":420,"value":3707},{"type":415,"tag":532,"props":14113,"children":14114},{"class":534,"line":902},[14115,14119,14123],{"type":415,"tag":532,"props":14116,"children":14117},{"style":3532},[14118],{"type":420,"value":3715},{"type":415,"tag":532,"props":14120,"children":14121},{"style":551},[14122],{"type":420,"value":1290},{"type":415,"tag":532,"props":14124,"children":14125},{"style":804},[14126],{"type":420,"value":3724},{"type":415,"tag":532,"props":14128,"children":14129},{"class":534,"line":1302},[14130,14134],{"type":415,"tag":532,"props":14131,"children":14132},{"style":3532},[14133],{"type":420,"value":3732},{"type":415,"tag":532,"props":14135,"children":14136},{"style":551},[14137],{"type":420,"value":3557},{"type":415,"tag":532,"props":14139,"children":14140},{"class":534,"line":1311},[14141,14145,14149],{"type":415,"tag":532,"props":14142,"children":14143},{"style":3532},[14144],{"type":420,"value":3744},{"type":415,"tag":532,"props":14146,"children":14147},{"style":551},[14148],{"type":420,"value":1290},{"type":415,"tag":532,"props":14150,"children":14151},{"style":804},[14152],{"type":420,"value":3753},{"type":415,"tag":532,"props":14154,"children":14155},{"class":534,"line":1356},[14156,14160,14164],{"type":415,"tag":532,"props":14157,"children":14158},{"style":3532},[14159],{"type":420,"value":3761},{"type":415,"tag":532,"props":14161,"children":14162},{"style":551},[14163],{"type":420,"value":1290},{"type":415,"tag":532,"props":14165,"children":14166},{"style":804},[14167],{"type":420,"value":3770},{"type":415,"tag":532,"props":14169,"children":14170},{"class":534,"line":1365},[14171,14175,14179],{"type":415,"tag":532,"props":14172,"children":14173},{"style":3532},[14174],{"type":420,"value":3778},{"type":415,"tag":532,"props":14176,"children":14177},{"style":551},[14178],{"type":420,"value":1290},{"type":415,"tag":532,"props":14180,"children":14181},{"style":804},[14182],{"type":420,"value":3787},{"type":415,"tag":532,"props":14184,"children":14185},{"class":534,"line":1373},[14186],{"type":415,"tag":532,"props":14187,"children":14188},{"emptyLinePlaceholder":621},[14189],{"type":420,"value":624},{"type":415,"tag":532,"props":14191,"children":14192},{"class":534,"line":3825},[14193,14197,14201,14205,14209,14213],{"type":415,"tag":532,"props":14194,"children":14195},{"style":551},[14196],{"type":420,"value":3683},{"type":415,"tag":532,"props":14198,"children":14199},{"style":3532},[14200],{"type":420,"value":3688},{"type":415,"tag":532,"props":14202,"children":14203},{"style":551},[14204],{"type":420,"value":1290},{"type":415,"tag":532,"props":14206,"children":14207},{"style":551},[14208],{"type":420,"value":3697},{"type":415,"tag":532,"props":14210,"children":14211},{"style":804},[14212],{"type":420,"value":3818},{"type":415,"tag":532,"props":14214,"children":14215},{"style":551},[14216],{"type":420,"value":3707},{"type":415,"tag":532,"props":14218,"children":14219},{"class":534,"line":3843},[14220,14224,14228],{"type":415,"tag":532,"props":14221,"children":14222},{"style":3532},[14223],{"type":420,"value":3831},{"type":415,"tag":532,"props":14225,"children":14226},{"style":551},[14227],{"type":420,"value":1290},{"type":415,"tag":532,"props":14229,"children":14230},{"style":1241},[14231],{"type":420,"value":3840},{"type":415,"tag":532,"props":14233,"children":14234},{"class":534,"line":3852},[14235],{"type":415,"tag":532,"props":14236,"children":14237},{"style":804},[14238],{"type":420,"value":3849},{"type":415,"tag":532,"props":14240,"children":14241},{"class":534,"line":5941},[14242],{"type":415,"tag":532,"props":14243,"children":14244},{"style":804},[14245],{"type":420,"value":3858},{"type":415,"tag":416,"props":14247,"children":14248},{},[14249,14251,14257],{"type":420,"value":14250},"This workflow first authenticates to Azure using OIDC with the ",{"type":415,"tag":468,"props":14252,"children":14254},{"className":14253},[],[14255],{"type":420,"value":14256},"azure/login",{"type":420,"value":14258}," action and then performs some Azure CLI commands to interact with Azure resources. That's fine and probably enough to get you started but you surely want to provision your infrastructure using a more declarative solution than an Azure CLI script. So let's see a more interesting pipeline still authenticating via Azure OIDC but using Pulumi to provision the Azure resources.",{"type":415,"tag":523,"props":14260,"children":14262},{"className":3520,"code":14261,"language":3522,"meta":401,"style":401},"name: infra\n\non:\n  workflow_dispatch:\n\npermissions:\n  id-token: write   # required for OIDC auth\n  contents: read    # required to perform a checkout\n\njobs:\n  provision-infra:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n        with:\n          version: latest\n\n      - name: Set node version to 18\n        uses: actions/setup-node@v3\n        with:\n          node-version: 18\n          cache: 'pnpm'\n      \n      - name: Install dependencies\n        run: pnpm install\n      \n      - name: Provision infrastructure\n        uses: pulumi/actions@v4.4.0\n        id: pulumi\n        with:\n          command: up\n          stack-name: dev\n        env:\n          ARM_USE_OIDC: true\n          PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}\n          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}\n          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}\n          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} \n",[14263],{"type":415,"tag":468,"props":14264,"children":14265},{"__ignoreMap":401},[14266,14281,14288,14299,14310,14317,14328,14349,14370,14377,14388,14399,14414,14425,14446,14453,14473,14489,14500,14517,14524,14544,14560,14571,14588,14612,14620,14640,14656,14663,14683,14699,14716,14727,14744,14761,14773,14789,14806,14823,14840],{"type":415,"tag":532,"props":14267,"children":14268},{"class":534,"line":535},[14269,14273,14277],{"type":415,"tag":532,"props":14270,"children":14271},{"style":3532},[14272],{"type":420,"value":3535},{"type":415,"tag":532,"props":14274,"children":14275},{"style":551},[14276],{"type":420,"value":1290},{"type":415,"tag":532,"props":14278,"children":14279},{"style":804},[14280],{"type":420,"value":13956},{"type":415,"tag":532,"props":14282,"children":14283},{"class":534,"line":566},[14284],{"type":415,"tag":532,"props":14285,"children":14286},{"emptyLinePlaceholder":621},[14287],{"type":420,"value":624},{"type":415,"tag":532,"props":14289,"children":14290},{"class":534,"line":583},[14291,14295],{"type":415,"tag":532,"props":14292,"children":14293},{"style":1938},[14294],{"type":420,"value":3552},{"type":415,"tag":532,"props":14296,"children":14297},{"style":551},[14298],{"type":420,"value":3557},{"type":415,"tag":532,"props":14300,"children":14301},{"class":534,"line":617},[14302,14306],{"type":415,"tag":532,"props":14303,"children":14304},{"style":3532},[14305],{"type":420,"value":3565},{"type":415,"tag":532,"props":14307,"children":14308},{"style":551},[14309],{"type":420,"value":3557},{"type":415,"tag":532,"props":14311,"children":14312},{"class":534,"line":627},[14313],{"type":415,"tag":532,"props":14314,"children":14315},{"emptyLinePlaceholder":621},[14316],{"type":420,"value":624},{"type":415,"tag":532,"props":14318,"children":14319},{"class":534,"line":677},[14320,14324],{"type":415,"tag":532,"props":14321,"children":14322},{"style":3532},[14323],{"type":420,"value":3584},{"type":415,"tag":532,"props":14325,"children":14326},{"style":551},[14327],{"type":420,"value":3557},{"type":415,"tag":532,"props":14329,"children":14330},{"class":534,"line":719},[14331,14335,14339,14344],{"type":415,"tag":532,"props":14332,"children":14333},{"style":3532},[14334],{"type":420,"value":3596},{"type":415,"tag":532,"props":14336,"children":14337},{"style":551},[14338],{"type":420,"value":1290},{"type":415,"tag":532,"props":14340,"children":14341},{"style":804},[14342],{"type":420,"value":14343}," write",{"type":415,"tag":532,"props":14345,"children":14346},{"style":5425},[14347],{"type":420,"value":14348},"   # required for OIDC auth\n",{"type":415,"tag":532,"props":14350,"children":14351},{"class":534,"line":758},[14352,14356,14360,14365],{"type":415,"tag":532,"props":14353,"children":14354},{"style":3532},[14355],{"type":420,"value":3613},{"type":415,"tag":532,"props":14357,"children":14358},{"style":551},[14359],{"type":420,"value":1290},{"type":415,"tag":532,"props":14361,"children":14362},{"style":804},[14363],{"type":420,"value":14364}," read",{"type":415,"tag":532,"props":14366,"children":14367},{"style":5425},[14368],{"type":420,"value":14369},"    # required to perform a checkout\n",{"type":415,"tag":532,"props":14371,"children":14372},{"class":534,"line":767},[14373],{"type":415,"tag":532,"props":14374,"children":14375},{"emptyLinePlaceholder":621},[14376],{"type":420,"value":624},{"type":415,"tag":532,"props":14378,"children":14379},{"class":534,"line":819},[14380,14384],{"type":415,"tag":532,"props":14381,"children":14382},{"style":3532},[14383],{"type":420,"value":3630},{"type":415,"tag":532,"props":14385,"children":14386},{"style":551},[14387],{"type":420,"value":3557},{"type":415,"tag":532,"props":14389,"children":14390},{"class":534,"line":850},[14391,14395],{"type":415,"tag":532,"props":14392,"children":14393},{"style":3532},[14394],{"type":420,"value":14054},{"type":415,"tag":532,"props":14396,"children":14397},{"style":551},[14398],{"type":420,"value":3557},{"type":415,"tag":532,"props":14400,"children":14401},{"class":534,"line":859},[14402,14406,14410],{"type":415,"tag":532,"props":14403,"children":14404},{"style":3532},[14405],{"type":420,"value":3654},{"type":415,"tag":532,"props":14407,"children":14408},{"style":551},[14409],{"type":420,"value":1290},{"type":415,"tag":532,"props":14411,"children":14412},{"style":804},[14413],{"type":420,"value":3663},{"type":415,"tag":532,"props":14415,"children":14416},{"class":534,"line":867},[14417,14421],{"type":415,"tag":532,"props":14418,"children":14419},{"style":3532},[14420],{"type":420,"value":3671},{"type":415,"tag":532,"props":14422,"children":14423},{"style":551},[14424],{"type":420,"value":3557},{"type":415,"tag":532,"props":14426,"children":14427},{"class":534,"line":902},[14428,14432,14437,14441],{"type":415,"tag":532,"props":14429,"children":14430},{"style":551},[14431],{"type":420,"value":3683},{"type":415,"tag":532,"props":14433,"children":14434},{"style":3532},[14435],{"type":420,"value":14436}," uses",{"type":415,"tag":532,"props":14438,"children":14439},{"style":551},[14440],{"type":420,"value":1290},{"type":415,"tag":532,"props":14442,"children":14443},{"style":804},[14444],{"type":420,"value":14445}," actions/checkout@v3\n",{"type":415,"tag":532,"props":14447,"children":14448},{"class":534,"line":1302},[14449],{"type":415,"tag":532,"props":14450,"children":14451},{"emptyLinePlaceholder":621},[14452],{"type":420,"value":624},{"type":415,"tag":532,"props":14454,"children":14455},{"class":534,"line":1311},[14456,14460,14464,14468],{"type":415,"tag":532,"props":14457,"children":14458},{"style":551},[14459],{"type":420,"value":3683},{"type":415,"tag":532,"props":14461,"children":14462},{"style":3532},[14463],{"type":420,"value":3688},{"type":415,"tag":532,"props":14465,"children":14466},{"style":551},[14467],{"type":420,"value":1290},{"type":415,"tag":532,"props":14469,"children":14470},{"style":804},[14471],{"type":420,"value":14472}," Install pnpm\n",{"type":415,"tag":532,"props":14474,"children":14475},{"class":534,"line":1356},[14476,14480,14484],{"type":415,"tag":532,"props":14477,"children":14478},{"style":3532},[14479],{"type":420,"value":3715},{"type":415,"tag":532,"props":14481,"children":14482},{"style":551},[14483],{"type":420,"value":1290},{"type":415,"tag":532,"props":14485,"children":14486},{"style":804},[14487],{"type":420,"value":14488}," pnpm/action-setup@v2\n",{"type":415,"tag":532,"props":14490,"children":14491},{"class":534,"line":1365},[14492,14496],{"type":415,"tag":532,"props":14493,"children":14494},{"style":3532},[14495],{"type":420,"value":3732},{"type":415,"tag":532,"props":14497,"children":14498},{"style":551},[14499],{"type":420,"value":3557},{"type":415,"tag":532,"props":14501,"children":14502},{"class":534,"line":1373},[14503,14508,14512],{"type":415,"tag":532,"props":14504,"children":14505},{"style":3532},[14506],{"type":420,"value":14507},"          version",{"type":415,"tag":532,"props":14509,"children":14510},{"style":551},[14511],{"type":420,"value":1290},{"type":415,"tag":532,"props":14513,"children":14514},{"style":804},[14515],{"type":420,"value":14516}," latest\n",{"type":415,"tag":532,"props":14518,"children":14519},{"class":534,"line":3825},[14520],{"type":415,"tag":532,"props":14521,"children":14522},{"emptyLinePlaceholder":621},[14523],{"type":420,"value":624},{"type":415,"tag":532,"props":14525,"children":14526},{"class":534,"line":3843},[14527,14531,14535,14539],{"type":415,"tag":532,"props":14528,"children":14529},{"style":551},[14530],{"type":420,"value":3683},{"type":415,"tag":532,"props":14532,"children":14533},{"style":3532},[14534],{"type":420,"value":3688},{"type":415,"tag":532,"props":14536,"children":14537},{"style":551},[14538],{"type":420,"value":1290},{"type":415,"tag":532,"props":14540,"children":14541},{"style":804},[14542],{"type":420,"value":14543}," Set node version to 18\n",{"type":415,"tag":532,"props":14545,"children":14546},{"class":534,"line":3852},[14547,14551,14555],{"type":415,"tag":532,"props":14548,"children":14549},{"style":3532},[14550],{"type":420,"value":3715},{"type":415,"tag":532,"props":14552,"children":14553},{"style":551},[14554],{"type":420,"value":1290},{"type":415,"tag":532,"props":14556,"children":14557},{"style":804},[14558],{"type":420,"value":14559}," actions/setup-node@v3\n",{"type":415,"tag":532,"props":14561,"children":14562},{"class":534,"line":5941},[14563,14567],{"type":415,"tag":532,"props":14564,"children":14565},{"style":3532},[14566],{"type":420,"value":3732},{"type":415,"tag":532,"props":14568,"children":14569},{"style":551},[14570],{"type":420,"value":3557},{"type":415,"tag":532,"props":14572,"children":14573},{"class":534,"line":6053},[14574,14579,14583],{"type":415,"tag":532,"props":14575,"children":14576},{"style":3532},[14577],{"type":420,"value":14578},"          node-version",{"type":415,"tag":532,"props":14580,"children":14581},{"style":551},[14582],{"type":420,"value":1290},{"type":415,"tag":532,"props":14584,"children":14585},{"style":539},[14586],{"type":420,"value":14587}," 18\n",{"type":415,"tag":532,"props":14589,"children":14590},{"class":534,"line":6061},[14591,14596,14600,14604,14608],{"type":415,"tag":532,"props":14592,"children":14593},{"style":3532},[14594],{"type":420,"value":14595},"          cache",{"type":415,"tag":532,"props":14597,"children":14598},{"style":551},[14599],{"type":420,"value":1290},{"type":415,"tag":532,"props":14601,"children":14602},{"style":551},[14603],{"type":420,"value":3697},{"type":415,"tag":532,"props":14605,"children":14606},{"style":804},[14607],{"type":420,"value":362},{"type":415,"tag":532,"props":14609,"children":14610},{"style":551},[14611],{"type":420,"value":3707},{"type":415,"tag":532,"props":14613,"children":14614},{"class":534,"line":6070},[14615],{"type":415,"tag":532,"props":14616,"children":14617},{"style":545},[14618],{"type":420,"value":14619},"      \n",{"type":415,"tag":532,"props":14621,"children":14622},{"class":534,"line":6094},[14623,14627,14631,14635],{"type":415,"tag":532,"props":14624,"children":14625},{"style":551},[14626],{"type":420,"value":3683},{"type":415,"tag":532,"props":14628,"children":14629},{"style":3532},[14630],{"type":420,"value":3688},{"type":415,"tag":532,"props":14632,"children":14633},{"style":551},[14634],{"type":420,"value":1290},{"type":415,"tag":532,"props":14636,"children":14637},{"style":804},[14638],{"type":420,"value":14639}," Install dependencies\n",{"type":415,"tag":532,"props":14641,"children":14642},{"class":534,"line":6118},[14643,14647,14651],{"type":415,"tag":532,"props":14644,"children":14645},{"style":3532},[14646],{"type":420,"value":3831},{"type":415,"tag":532,"props":14648,"children":14649},{"style":551},[14650],{"type":420,"value":1290},{"type":415,"tag":532,"props":14652,"children":14653},{"style":804},[14654],{"type":420,"value":14655}," pnpm install\n",{"type":415,"tag":532,"props":14657,"children":14658},{"class":534,"line":6142},[14659],{"type":415,"tag":532,"props":14660,"children":14661},{"style":545},[14662],{"type":420,"value":14619},{"type":415,"tag":532,"props":14664,"children":14665},{"class":534,"line":6182},[14666,14670,14674,14678],{"type":415,"tag":532,"props":14667,"children":14668},{"style":551},[14669],{"type":420,"value":3683},{"type":415,"tag":532,"props":14671,"children":14672},{"style":3532},[14673],{"type":420,"value":3688},{"type":415,"tag":532,"props":14675,"children":14676},{"style":551},[14677],{"type":420,"value":1290},{"type":415,"tag":532,"props":14679,"children":14680},{"style":804},[14681],{"type":420,"value":14682}," Provision infrastructure\n",{"type":415,"tag":532,"props":14684,"children":14685},{"class":534,"line":6214},[14686,14690,14694],{"type":415,"tag":532,"props":14687,"children":14688},{"style":3532},[14689],{"type":420,"value":3715},{"type":415,"tag":532,"props":14691,"children":14692},{"style":551},[14693],{"type":420,"value":1290},{"type":415,"tag":532,"props":14695,"children":14696},{"style":804},[14697],{"type":420,"value":14698}," pulumi/actions@v4.4.0\n",{"type":415,"tag":532,"props":14700,"children":14701},{"class":534,"line":6234},[14702,14707,14711],{"type":415,"tag":532,"props":14703,"children":14704},{"style":3532},[14705],{"type":420,"value":14706},"        id",{"type":415,"tag":532,"props":14708,"children":14709},{"style":551},[14710],{"type":420,"value":1290},{"type":415,"tag":532,"props":14712,"children":14713},{"style":804},[14714],{"type":420,"value":14715}," pulumi\n",{"type":415,"tag":532,"props":14717,"children":14718},{"class":534,"line":6250},[14719,14723],{"type":415,"tag":532,"props":14720,"children":14721},{"style":3532},[14722],{"type":420,"value":3732},{"type":415,"tag":532,"props":14724,"children":14725},{"style":551},[14726],{"type":420,"value":3557},{"type":415,"tag":532,"props":14728,"children":14729},{"class":534,"line":6258},[14730,14735,14739],{"type":415,"tag":532,"props":14731,"children":14732},{"style":3532},[14733],{"type":420,"value":14734},"          command",{"type":415,"tag":532,"props":14736,"children":14737},{"style":551},[14738],{"type":420,"value":1290},{"type":415,"tag":532,"props":14740,"children":14741},{"style":804},[14742],{"type":420,"value":14743}," up\n",{"type":415,"tag":532,"props":14745,"children":14746},{"class":534,"line":6266},[14747,14752,14756],{"type":415,"tag":532,"props":14748,"children":14749},{"style":3532},[14750],{"type":420,"value":14751},"          stack-name",{"type":415,"tag":532,"props":14753,"children":14754},{"style":551},[14755],{"type":420,"value":1290},{"type":415,"tag":532,"props":14757,"children":14758},{"style":804},[14759],{"type":420,"value":14760}," dev\n",{"type":415,"tag":532,"props":14762,"children":14763},{"class":534,"line":6274},[14764,14769],{"type":415,"tag":532,"props":14765,"children":14766},{"style":3532},[14767],{"type":420,"value":14768},"        env",{"type":415,"tag":532,"props":14770,"children":14771},{"style":551},[14772],{"type":420,"value":3557},{"type":415,"tag":532,"props":14774,"children":14775},{"class":534,"line":6283},[14776,14781,14785],{"type":415,"tag":532,"props":14777,"children":14778},{"style":3532},[14779],{"type":420,"value":14780},"          ARM_USE_OIDC",{"type":415,"tag":532,"props":14782,"children":14783},{"style":551},[14784],{"type":420,"value":1290},{"type":415,"tag":532,"props":14786,"children":14787},{"style":1938},[14788],{"type":420,"value":11832},{"type":415,"tag":532,"props":14790,"children":14791},{"class":534,"line":6292},[14792,14797,14801],{"type":415,"tag":532,"props":14793,"children":14794},{"style":3532},[14795],{"type":420,"value":14796},"          PULUMI_ACCESS_TOKEN",{"type":415,"tag":532,"props":14798,"children":14799},{"style":551},[14800],{"type":420,"value":1290},{"type":415,"tag":532,"props":14802,"children":14803},{"style":804},[14804],{"type":420,"value":14805}," ${{ secrets.PULUMI_ACCESS_TOKEN }}\n",{"type":415,"tag":532,"props":14807,"children":14808},{"class":534,"line":6392},[14809,14814,14818],{"type":415,"tag":532,"props":14810,"children":14811},{"style":3532},[14812],{"type":420,"value":14813},"          ARM_CLIENT_ID",{"type":415,"tag":532,"props":14815,"children":14816},{"style":551},[14817],{"type":420,"value":1290},{"type":415,"tag":532,"props":14819,"children":14820},{"style":804},[14821],{"type":420,"value":14822}," ${{ secrets.ARM_CLIENT_ID }}\n",{"type":415,"tag":532,"props":14824,"children":14825},{"class":534,"line":6400},[14826,14831,14835],{"type":415,"tag":532,"props":14827,"children":14828},{"style":3532},[14829],{"type":420,"value":14830},"          ARM_TENANT_ID",{"type":415,"tag":532,"props":14832,"children":14833},{"style":551},[14834],{"type":420,"value":1290},{"type":415,"tag":532,"props":14836,"children":14837},{"style":804},[14838],{"type":420,"value":14839}," ${{ secrets.ARM_TENANT_ID }}\n",{"type":415,"tag":532,"props":14841,"children":14842},{"class":534,"line":6409},[14843,14848,14852],{"type":415,"tag":532,"props":14844,"children":14845},{"style":3532},[14846],{"type":420,"value":14847},"          ARM_SUBSCRIPTION_ID",{"type":415,"tag":532,"props":14849,"children":14850},{"style":551},[14851],{"type":420,"value":1290},{"type":415,"tag":532,"props":14853,"children":14854},{"style":804},[14855],{"type":420,"value":14856}," ${{ secrets.ARM_SUBSCRIPTION_ID }}\n",{"type":415,"tag":416,"props":14858,"children":14859},{},[14860,14862,14868],{"type":420,"value":14861},"A permission section is required with 2 settings (more details ",{"type":415,"tag":423,"props":14863,"children":14866},{"href":14864,"rel":14865},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings",[427],[14867],{"type":420,"value":4427},{"type":420,"value":14869},"):",{"type":415,"tag":508,"props":14871,"children":14872},{},[14873,14884],{"type":415,"tag":512,"props":14874,"children":14875},{},[14876,14882],{"type":415,"tag":468,"props":14877,"children":14879},{"className":14878},[],[14880],{"type":420,"value":14881},"id-token: write",{"type":420,"value":14883}," ➡️ needed to request the OIDC token",{"type":415,"tag":512,"props":14885,"children":14886},{},[14887,14893],{"type":415,"tag":468,"props":14888,"children":14890},{"className":14889},[],[14891],{"type":420,"value":14892},"contents: read",{"type":420,"value":14894}," ➡️ needed to perform checkout action",{"type":415,"tag":434,"props":14896,"children":14897},{"icon":6841},[14898],{"type":415,"tag":416,"props":14899,"children":14900},{},[14901],{"type":420,"value":14902},"When you start to specify specific permissions, you have to specify all the permissions you need for the job because the default permissions won't apply anymore.",{"type":415,"tag":416,"props":14904,"children":14905},{},[14906,14908,14914,14916,14922,14924,14930],{"type":420,"value":14907},"The 3 steps following the checkout step are actions to specify the Node.js version to use, install and correctly configure ",{"type":415,"tag":423,"props":14909,"children":14912},{"href":14910,"rel":14911},"https://bordeauxcoders.com/series/pnpm-101",[427],[14913],{"type":420,"value":362},{"type":420,"value":14915},". We assume here the infrastructure will be provisioned using TypeScript (and Pulumi of course) but there would have been similar steps with other runtimes/languages (a ",{"type":415,"tag":468,"props":14917,"children":14919},{"className":14918},[],[14920],{"type":420,"value":14921},"setup-dotnet",{"type":420,"value":14923}," and a ",{"type":415,"tag":468,"props":14925,"children":14927},{"className":14926},[],[14928],{"type":420,"value":14929},"dotnet retore",{"type":420,"value":14931}," action for .NET for instance).",{"type":415,"tag":416,"props":14933,"children":14934},{},[14935,14937,14942,14944,14949,14951,14957,14959,14964],{"type":420,"value":14936},"The last action is the Pulumi action to provision the infrastructure by running the ",{"type":415,"tag":468,"props":14938,"children":14940},{"className":14939},[],[14941],{"type":420,"value":10839},{"type":420,"value":14943}," on the ",{"type":415,"tag":468,"props":14945,"children":14947},{"className":14946},[],[14948],{"type":420,"value":7074},{"type":420,"value":14950}," stack. We can see that this action uses environment variables whose values are based on the GitHub Actions secrets we defined earlier. To tell Pulumi to use OIDC, we just have to set the ",{"type":415,"tag":468,"props":14952,"children":14954},{"className":14953},[],[14955],{"type":420,"value":14956},"ARM_USE_OIDC",{"type":420,"value":14958}," environment variable to ",{"type":415,"tag":468,"props":14960,"children":14962},{"className":14961},[],[14963],{"type":420,"value":11958},{"type":420,"value":432},{"type":415,"tag":523,"props":14966,"children":14968},{"className":3520,"code":14967,"language":3522,"meta":401,"style":401},"        env:\n          ARM_USE_OIDC: true\n          PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}\n          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}\n          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}\n          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} \n",[14969],{"type":415,"tag":468,"props":14970,"children":14971},{"__ignoreMap":401},[14972,14983,14998,15013,15028,15043],{"type":415,"tag":532,"props":14973,"children":14974},{"class":534,"line":535},[14975,14979],{"type":415,"tag":532,"props":14976,"children":14977},{"style":3532},[14978],{"type":420,"value":14768},{"type":415,"tag":532,"props":14980,"children":14981},{"style":551},[14982],{"type":420,"value":3557},{"type":415,"tag":532,"props":14984,"children":14985},{"class":534,"line":566},[14986,14990,14994],{"type":415,"tag":532,"props":14987,"children":14988},{"style":3532},[14989],{"type":420,"value":14780},{"type":415,"tag":532,"props":14991,"children":14992},{"style":551},[14993],{"type":420,"value":1290},{"type":415,"tag":532,"props":14995,"children":14996},{"style":1938},[14997],{"type":420,"value":11832},{"type":415,"tag":532,"props":14999,"children":15000},{"class":534,"line":583},[15001,15005,15009],{"type":415,"tag":532,"props":15002,"children":15003},{"style":3532},[15004],{"type":420,"value":14796},{"type":415,"tag":532,"props":15006,"children":15007},{"style":551},[15008],{"type":420,"value":1290},{"type":415,"tag":532,"props":15010,"children":15011},{"style":804},[15012],{"type":420,"value":14805},{"type":415,"tag":532,"props":15014,"children":15015},{"class":534,"line":617},[15016,15020,15024],{"type":415,"tag":532,"props":15017,"children":15018},{"style":3532},[15019],{"type":420,"value":14813},{"type":415,"tag":532,"props":15021,"children":15022},{"style":551},[15023],{"type":420,"value":1290},{"type":415,"tag":532,"props":15025,"children":15026},{"style":804},[15027],{"type":420,"value":14822},{"type":415,"tag":532,"props":15029,"children":15030},{"class":534,"line":627},[15031,15035,15039],{"type":415,"tag":532,"props":15032,"children":15033},{"style":3532},[15034],{"type":420,"value":14830},{"type":415,"tag":532,"props":15036,"children":15037},{"style":551},[15038],{"type":420,"value":1290},{"type":415,"tag":532,"props":15040,"children":15041},{"style":804},[15042],{"type":420,"value":14839},{"type":415,"tag":532,"props":15044,"children":15045},{"class":534,"line":677},[15046,15050,15054],{"type":415,"tag":532,"props":15047,"children":15048},{"style":3532},[15049],{"type":420,"value":14847},{"type":415,"tag":532,"props":15051,"children":15052},{"style":551},[15053],{"type":420,"value":1290},{"type":415,"tag":532,"props":15055,"children":15056},{"style":804},[15057],{"type":420,"value":14856},{"type":415,"tag":416,"props":15059,"children":15060},{},[15061,15063,15069,15071,15078],{"type":420,"value":15062},"A GitHub Actions secret we did not talk about is ",{"type":415,"tag":468,"props":15064,"children":15066},{"className":15065},[],[15067],{"type":420,"value":15068},"PULUMI_ACCESS_TOKEN",{"type":420,"value":15070}," that is a ",{"type":415,"tag":423,"props":15072,"children":15075},{"href":15073,"rel":15074},"https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/",[427],[15076],{"type":420,"value":15077},"Pulumi access token",{"type":420,"value":15079}," to use Pulumi Cloud as our backend to store the infrastructure state and encrypt secrets. This token should be:",{"type":415,"tag":5188,"props":15081,"children":15082},{},[15083,15095,15106],{"type":415,"tag":512,"props":15084,"children":15085},{},[15086,15088,15094],{"type":420,"value":15087},"Created from Pulumi Cloud (following the documentation ",{"type":415,"tag":423,"props":15089,"children":15092},{"href":15090,"rel":15091},"https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/#personal-access-tokens",[427],[15093],{"type":420,"value":4427},{"type":420,"value":1349},{"type":415,"tag":512,"props":15096,"children":15097},{},[15098,15100],{"type":420,"value":15099},"Stored in the stack configuration using the following command ",{"type":415,"tag":468,"props":15101,"children":15103},{"className":15102},[],[15104],{"type":420,"value":15105},"pulumi config set pulumiTokenForRepository ******* --secret",{"type":415,"tag":512,"props":15107,"children":15108},{},[15109,15111],{"type":420,"value":15110},"Stored in a GitHub Actions secret using this code",{"type":415,"tag":523,"props":15112,"children":15114},{"className":11642,"code":15113,"language":357,"meta":401,"style":401},"new github.ActionsSecret(\"pulumiAccessToken\", {\n  repository: repository.name,\n  secretName: \"PULUMI_ACCESS_TOKEN\",\n  plaintextValue: config.requireSecret(\"pulumiTokenForRepository\"),\n});\n",[15115],{"type":415,"tag":468,"props":15116,"children":15117},{"__ignoreMap":401},[15118,15162,15189,15216,15265],{"type":415,"tag":532,"props":15119,"children":15120},{"class":534,"line":535},[15121,15125,15129,15133,15137,15141,15145,15150,15154,15158],{"type":415,"tag":532,"props":15122,"children":15123},{"style":551},[15124],{"type":420,"value":9142},{"type":415,"tag":532,"props":15126,"children":15127},{"style":545},[15128],{"type":420,"value":11724},{"type":415,"tag":532,"props":15130,"children":15131},{"style":551},[15132],{"type":420,"value":432},{"type":415,"tag":532,"props":15134,"children":15135},{"style":656},[15136],{"type":420,"value":13483},{"type":415,"tag":532,"props":15138,"children":15139},{"style":545},[15140],{"type":420,"value":664},{"type":415,"tag":532,"props":15142,"children":15143},{"style":551},[15144],{"type":420,"value":801},{"type":415,"tag":532,"props":15146,"children":15147},{"style":804},[15148],{"type":420,"value":15149},"pulumiAccessToken",{"type":415,"tag":532,"props":15151,"children":15152},{"style":551},[15153],{"type":420,"value":801},{"type":415,"tag":532,"props":15155,"children":15156},{"style":551},[15157],{"type":420,"value":1099},{"type":415,"tag":532,"props":15159,"children":15160},{"style":551},[15161],{"type":420,"value":11759},{"type":415,"tag":532,"props":15163,"children":15164},{"class":534,"line":566},[15165,15169,15173,15177,15181,15185],{"type":415,"tag":532,"props":15166,"children":15167},{"style":3532},[15168],{"type":420,"value":13305},{"type":415,"tag":532,"props":15170,"children":15171},{"style":551},[15172],{"type":420,"value":1290},{"type":415,"tag":532,"props":15174,"children":15175},{"style":545},[15176],{"type":420,"value":7695},{"type":415,"tag":532,"props":15178,"children":15179},{"style":551},[15180],{"type":420,"value":432},{"type":415,"tag":532,"props":15182,"children":15183},{"style":545},[15184],{"type":420,"value":3535},{"type":415,"tag":532,"props":15186,"children":15187},{"style":551},[15188],{"type":420,"value":7400},{"type":415,"tag":532,"props":15190,"children":15191},{"class":534,"line":583},[15192,15196,15200,15204,15208,15212],{"type":415,"tag":532,"props":15193,"children":15194},{"style":3532},[15195],{"type":420,"value":13542},{"type":415,"tag":532,"props":15197,"children":15198},{"style":551},[15199],{"type":420,"value":1290},{"type":415,"tag":532,"props":15201,"children":15202},{"style":551},[15203],{"type":420,"value":4041},{"type":415,"tag":532,"props":15205,"children":15206},{"style":804},[15207],{"type":420,"value":15068},{"type":415,"tag":532,"props":15209,"children":15210},{"style":551},[15211],{"type":420,"value":801},{"type":415,"tag":532,"props":15213,"children":15214},{"style":551},[15215],{"type":420,"value":7400},{"type":415,"tag":532,"props":15217,"children":15218},{"class":534,"line":617},[15219,15223,15227,15231,15235,15240,15244,15248,15253,15257,15261],{"type":415,"tag":532,"props":15220,"children":15221},{"style":3532},[15222],{"type":420,"value":13570},{"type":415,"tag":532,"props":15224,"children":15225},{"style":551},[15226],{"type":420,"value":1290},{"type":415,"tag":532,"props":15228,"children":15229},{"style":545},[15230],{"type":420,"value":7206},{"type":415,"tag":532,"props":15232,"children":15233},{"style":551},[15234],{"type":420,"value":432},{"type":415,"tag":532,"props":15236,"children":15237},{"style":656},[15238],{"type":420,"value":15239},"requireSecret",{"type":415,"tag":532,"props":15241,"children":15242},{"style":545},[15243],{"type":420,"value":664},{"type":415,"tag":532,"props":15245,"children":15246},{"style":551},[15247],{"type":420,"value":801},{"type":415,"tag":532,"props":15249,"children":15250},{"style":804},[15251],{"type":420,"value":15252},"pulumiTokenForRepository",{"type":415,"tag":532,"props":15254,"children":15255},{"style":551},[15256],{"type":420,"value":801},{"type":415,"tag":532,"props":15258,"children":15259},{"style":545},[15260],{"type":420,"value":1349},{"type":415,"tag":532,"props":15262,"children":15263},{"style":551},[15264],{"type":420,"value":7400},{"type":415,"tag":532,"props":15266,"children":15267},{"class":534,"line":627},[15268,15272,15276],{"type":415,"tag":532,"props":15269,"children":15270},{"style":551},[15271],{"type":420,"value":4864},{"type":415,"tag":532,"props":15273,"children":15274},{"style":545},[15275],{"type":420,"value":1349},{"type":415,"tag":532,"props":15277,"children":15278},{"style":551},[15279],{"type":420,"value":563},{"type":415,"tag":416,"props":15281,"children":15282},{},[15283],{"type":420,"value":15284},"The last thing to do is to add this workflow file to the GitHub repository:",{"type":415,"tag":523,"props":15286,"children":15288},{"className":11642,"code":15287,"language":357,"meta":401,"style":401},"import { readFileSync } from \"fs\";\n\nconst pipelineContent = readFileSync(\"main.yml\", \"utf-8\");\nnew github.RepositoryFile(\"pipelineRepositoryFile\", {\n  repository: repository.name,\n  branch: \"main\",\n  file: \".github/workflows/main.yml\",\n  content: pipelineContent,\n  commitMessage: \"Add preconfigured pipeline file\",\n  commitAuthor: \"Alexandre Nédélec\",\n  commitEmail: \"15186176+TechWatching@users.noreply.github.com\",\n  overwriteOnCreate: true,\n});\n",[15289],{"type":415,"tag":468,"props":15290,"children":15291},{"__ignoreMap":401},[15292,15333,15340,15402,15447,15474,15502,15531,15552,15580,15609,15638,15658],{"type":415,"tag":532,"props":15293,"children":15294},{"class":534,"line":535},[15295,15299,15303,15308,15312,15316,15320,15325,15329],{"type":415,"tag":532,"props":15296,"children":15297},{"style":1241},[15298],{"type":420,"value":11655},{"type":415,"tag":532,"props":15300,"children":15301},{"style":551},[15302],{"type":420,"value":3347},{"type":415,"tag":532,"props":15304,"children":15305},{"style":545},[15306],{"type":420,"value":15307}," readFileSync",{"type":415,"tag":532,"props":15309,"children":15310},{"style":551},[15311],{"type":420,"value":12125},{"type":415,"tag":532,"props":15313,"children":15314},{"style":1241},[15315],{"type":420,"value":12683},{"type":415,"tag":532,"props":15317,"children":15318},{"style":551},[15319],{"type":420,"value":4041},{"type":415,"tag":532,"props":15321,"children":15322},{"style":804},[15323],{"type":420,"value":15324},"fs",{"type":415,"tag":532,"props":15326,"children":15327},{"style":551},[15328],{"type":420,"value":801},{"type":415,"tag":532,"props":15330,"children":15331},{"style":551},[15332],{"type":420,"value":563},{"type":415,"tag":532,"props":15334,"children":15335},{"class":534,"line":566},[15336],{"type":415,"tag":532,"props":15337,"children":15338},{"emptyLinePlaceholder":621},[15339],{"type":420,"value":624},{"type":415,"tag":532,"props":15341,"children":15342},{"class":534,"line":583},[15343,15347,15352,15356,15360,15364,15368,15373,15377,15381,15385,15390,15394,15398],{"type":415,"tag":532,"props":15344,"children":15345},{"style":954},[15346],{"type":420,"value":11706},{"type":415,"tag":532,"props":15348,"children":15349},{"style":545},[15350],{"type":420,"value":15351}," pipelineContent ",{"type":415,"tag":532,"props":15353,"children":15354},{"style":551},[15355],{"type":420,"value":1134},{"type":415,"tag":532,"props":15357,"children":15358},{"style":656},[15359],{"type":420,"value":15307},{"type":415,"tag":532,"props":15361,"children":15362},{"style":545},[15363],{"type":420,"value":664},{"type":415,"tag":532,"props":15365,"children":15366},{"style":551},[15367],{"type":420,"value":801},{"type":415,"tag":532,"props":15369,"children":15370},{"style":804},[15371],{"type":420,"value":15372},"main.yml",{"type":415,"tag":532,"props":15374,"children":15375},{"style":551},[15376],{"type":420,"value":801},{"type":415,"tag":532,"props":15378,"children":15379},{"style":551},[15380],{"type":420,"value":1099},{"type":415,"tag":532,"props":15382,"children":15383},{"style":551},[15384],{"type":420,"value":4041},{"type":415,"tag":532,"props":15386,"children":15387},{"style":804},[15388],{"type":420,"value":15389},"utf-8",{"type":415,"tag":532,"props":15391,"children":15392},{"style":551},[15393],{"type":420,"value":801},{"type":415,"tag":532,"props":15395,"children":15396},{"style":545},[15397],{"type":420,"value":1349},{"type":415,"tag":532,"props":15399,"children":15400},{"style":551},[15401],{"type":420,"value":563},{"type":415,"tag":532,"props":15403,"children":15404},{"class":534,"line":617},[15405,15409,15413,15417,15422,15426,15430,15435,15439,15443],{"type":415,"tag":532,"props":15406,"children":15407},{"style":551},[15408],{"type":420,"value":9142},{"type":415,"tag":532,"props":15410,"children":15411},{"style":545},[15412],{"type":420,"value":11724},{"type":415,"tag":532,"props":15414,"children":15415},{"style":551},[15416],{"type":420,"value":432},{"type":415,"tag":532,"props":15418,"children":15419},{"style":656},[15420],{"type":420,"value":15421},"RepositoryFile",{"type":415,"tag":532,"props":15423,"children":15424},{"style":545},[15425],{"type":420,"value":664},{"type":415,"tag":532,"props":15427,"children":15428},{"style":551},[15429],{"type":420,"value":801},{"type":415,"tag":532,"props":15431,"children":15432},{"style":804},[15433],{"type":420,"value":15434},"pipelineRepositoryFile",{"type":415,"tag":532,"props":15436,"children":15437},{"style":551},[15438],{"type":420,"value":801},{"type":415,"tag":532,"props":15440,"children":15441},{"style":551},[15442],{"type":420,"value":1099},{"type":415,"tag":532,"props":15444,"children":15445},{"style":551},[15446],{"type":420,"value":11759},{"type":415,"tag":532,"props":15448,"children":15449},{"class":534,"line":627},[15450,15454,15458,15462,15466,15470],{"type":415,"tag":532,"props":15451,"children":15452},{"style":3532},[15453],{"type":420,"value":13305},{"type":415,"tag":532,"props":15455,"children":15456},{"style":551},[15457],{"type":420,"value":1290},{"type":415,"tag":532,"props":15459,"children":15460},{"style":545},[15461],{"type":420,"value":7695},{"type":415,"tag":532,"props":15463,"children":15464},{"style":551},[15465],{"type":420,"value":432},{"type":415,"tag":532,"props":15467,"children":15468},{"style":545},[15469],{"type":420,"value":3535},{"type":415,"tag":532,"props":15471,"children":15472},{"style":551},[15473],{"type":420,"value":7400},{"type":415,"tag":532,"props":15475,"children":15476},{"class":534,"line":677},[15477,15482,15486,15490,15494,15498],{"type":415,"tag":532,"props":15478,"children":15479},{"style":3532},[15480],{"type":420,"value":15481},"  branch",{"type":415,"tag":532,"props":15483,"children":15484},{"style":551},[15485],{"type":420,"value":1290},{"type":415,"tag":532,"props":15487,"children":15488},{"style":551},[15489],{"type":420,"value":4041},{"type":415,"tag":532,"props":15491,"children":15492},{"style":804},[15493],{"type":420,"value":11042},{"type":415,"tag":532,"props":15495,"children":15496},{"style":551},[15497],{"type":420,"value":801},{"type":415,"tag":532,"props":15499,"children":15500},{"style":551},[15501],{"type":420,"value":7400},{"type":415,"tag":532,"props":15503,"children":15504},{"class":534,"line":719},[15505,15510,15514,15518,15523,15527],{"type":415,"tag":532,"props":15506,"children":15507},{"style":3532},[15508],{"type":420,"value":15509},"  file",{"type":415,"tag":532,"props":15511,"children":15512},{"style":551},[15513],{"type":420,"value":1290},{"type":415,"tag":532,"props":15515,"children":15516},{"style":551},[15517],{"type":420,"value":4041},{"type":415,"tag":532,"props":15519,"children":15520},{"style":804},[15521],{"type":420,"value":15522},".github/workflows/main.yml",{"type":415,"tag":532,"props":15524,"children":15525},{"style":551},[15526],{"type":420,"value":801},{"type":415,"tag":532,"props":15528,"children":15529},{"style":551},[15530],{"type":420,"value":7400},{"type":415,"tag":532,"props":15532,"children":15533},{"class":534,"line":758},[15534,15539,15543,15548],{"type":415,"tag":532,"props":15535,"children":15536},{"style":3532},[15537],{"type":420,"value":15538},"  content",{"type":415,"tag":532,"props":15540,"children":15541},{"style":551},[15542],{"type":420,"value":1290},{"type":415,"tag":532,"props":15544,"children":15545},{"style":545},[15546],{"type":420,"value":15547}," pipelineContent",{"type":415,"tag":532,"props":15549,"children":15550},{"style":551},[15551],{"type":420,"value":7400},{"type":415,"tag":532,"props":15553,"children":15554},{"class":534,"line":767},[15555,15560,15564,15568,15572,15576],{"type":415,"tag":532,"props":15556,"children":15557},{"style":3532},[15558],{"type":420,"value":15559},"  commitMessage",{"type":415,"tag":532,"props":15561,"children":15562},{"style":551},[15563],{"type":420,"value":1290},{"type":415,"tag":532,"props":15565,"children":15566},{"style":551},[15567],{"type":420,"value":4041},{"type":415,"tag":532,"props":15569,"children":15570},{"style":804},[15571],{"type":420,"value":10108},{"type":415,"tag":532,"props":15573,"children":15574},{"style":551},[15575],{"type":420,"value":801},{"type":415,"tag":532,"props":15577,"children":15578},{"style":551},[15579],{"type":420,"value":7400},{"type":415,"tag":532,"props":15581,"children":15582},{"class":534,"line":819},[15583,15588,15592,15596,15601,15605],{"type":415,"tag":532,"props":15584,"children":15585},{"style":3532},[15586],{"type":420,"value":15587},"  commitAuthor",{"type":415,"tag":532,"props":15589,"children":15590},{"style":551},[15591],{"type":420,"value":1290},{"type":415,"tag":532,"props":15593,"children":15594},{"style":551},[15595],{"type":420,"value":4041},{"type":415,"tag":532,"props":15597,"children":15598},{"style":804},[15599],{"type":420,"value":15600},"Alexandre Nédélec",{"type":415,"tag":532,"props":15602,"children":15603},{"style":551},[15604],{"type":420,"value":801},{"type":415,"tag":532,"props":15606,"children":15607},{"style":551},[15608],{"type":420,"value":7400},{"type":415,"tag":532,"props":15610,"children":15611},{"class":534,"line":850},[15612,15617,15621,15625,15630,15634],{"type":415,"tag":532,"props":15613,"children":15614},{"style":3532},[15615],{"type":420,"value":15616},"  commitEmail",{"type":415,"tag":532,"props":15618,"children":15619},{"style":551},[15620],{"type":420,"value":1290},{"type":415,"tag":532,"props":15622,"children":15623},{"style":551},[15624],{"type":420,"value":4041},{"type":415,"tag":532,"props":15626,"children":15627},{"style":804},[15628],{"type":420,"value":15629},"15186176+TechWatching@users.noreply.github.com",{"type":415,"tag":532,"props":15631,"children":15632},{"style":551},[15633],{"type":420,"value":801},{"type":415,"tag":532,"props":15635,"children":15636},{"style":551},[15637],{"type":420,"value":7400},{"type":415,"tag":532,"props":15639,"children":15640},{"class":534,"line":859},[15641,15646,15650,15654],{"type":415,"tag":532,"props":15642,"children":15643},{"style":3532},[15644],{"type":420,"value":15645},"  overwriteOnCreate",{"type":415,"tag":532,"props":15647,"children":15648},{"style":551},[15649],{"type":420,"value":1290},{"type":415,"tag":532,"props":15651,"children":15652},{"style":1938},[15653],{"type":420,"value":1941},{"type":415,"tag":532,"props":15655,"children":15656},{"style":551},[15657],{"type":420,"value":7400},{"type":415,"tag":532,"props":15659,"children":15660},{"class":534,"line":867},[15661,15665,15669],{"type":415,"tag":532,"props":15662,"children":15663},{"style":551},[15664],{"type":420,"value":4864},{"type":415,"tag":532,"props":15666,"children":15667},{"style":545},[15668],{"type":420,"value":1349},{"type":415,"tag":532,"props":15670,"children":15671},{"style":551},[15672],{"type":420,"value":563},{"type":415,"tag":416,"props":15674,"children":15675},{},[15676],{"type":420,"value":15677},"This code:",{"type":415,"tag":5188,"props":15679,"children":15680},{},[15681,15693,15705],{"type":415,"tag":512,"props":15682,"children":15683},{},[15684,15686,15691],{"type":420,"value":15685},"reads the ",{"type":415,"tag":468,"props":15687,"children":15689},{"className":15688},[],[15690],{"type":420,"value":15372},{"type":420,"value":15692}," file that contains the workflow we saw previously",{"type":415,"tag":512,"props":15694,"children":15695},{},[15696,15698,15703],{"type":420,"value":15697},"creates a file with this content in the repository in the ",{"type":415,"tag":468,"props":15699,"children":15701},{"className":15700},[],[15702],{"type":420,"value":11060},{"type":420,"value":15704}," folder for the GitHub Actions workflows",{"type":415,"tag":512,"props":15706,"children":15707},{},[15708],{"type":420,"value":15709},"makes a commit when creating the file (or modifying it)",{"type":415,"tag":434,"props":15711,"children":15712},{"icon":1382},[15713],{"type":415,"tag":416,"props":15714,"children":15715},{},[15716,15718,15724,15726,15731],{"type":420,"value":15717},"To read the YAML file, I use the ",{"type":415,"tag":468,"props":15719,"children":15721},{"className":15720},[],[15722],{"type":420,"value":15723},"readFileSync",{"type":420,"value":15725}," method from the File System API ",{"type":415,"tag":468,"props":15727,"children":15729},{"className":15728},[],[15730],{"type":420,"value":15324},{"type":420,"value":15732},". That's one of the things I love about Pulumi: you use the things you already know and that already exist in your ecosystem. No need to look for a module or wait for someone to write one, there is probably something standard or a popular community library you can use.",{"type":415,"tag":482,"props":15734,"children":15736},{"id":15735},"test-the-azure-ready-github-repository",[15737],{"type":420,"value":15738},"Test the Azure-Ready GitHub Repository",{"type":415,"tag":416,"props":15740,"children":15741},{},[15742,15744,15749],{"type":420,"value":15743},"Now that the infrastructure code to provision the Azure-Ready GitHub repository is written, let's run it with the ",{"type":415,"tag":468,"props":15745,"children":15747},{"className":15746},[],[15748],{"type":420,"value":10839},{"type":420,"value":15750}," command and see if it works!",{"type":415,"tag":416,"props":15752,"children":15753},{},[15754],{"type":415,"tag":3882,"props":15755,"children":15759},{"alt":15756,"className":15757,"src":15758,"width":6932},"Ouput of the pulumi up command with all the resources created.",[3886,3887],"/posts/images/azurereadygithub_pulumi_1.webp",[],{"type":415,"tag":416,"props":15761,"children":15762},{},[15763],{"type":420,"value":15764},"All the resources are correctly created and our new GitHub repository is ready to be used.",{"type":415,"tag":416,"props":15766,"children":15767},{},[15768],{"type":415,"tag":3882,"props":15769,"children":15773},{"alt":15770,"className":15771,"src":15772},"Picture of the Azure Ready GitHub repository",[3886,3887],"/posts/images/azurereadygithub_github_2.webp",[],{"type":415,"tag":416,"props":15775,"children":15776},{},[15777],{"type":420,"value":15778},"Let's clone it.",{"type":415,"tag":523,"props":15780,"children":15782},{"className":3984,"code":15781,"language":3986,"meta":401,"style":401},"git clone https://github.com/TechWatching/azure-ready-repository; cd azure-ready-repository\n",[15783],{"type":415,"tag":468,"props":15784,"children":15785},{"__ignoreMap":401},[15786],{"type":415,"tag":532,"props":15787,"children":15788},{"class":534,"line":535},[15789,15793,15798,15803,15808,15813],{"type":415,"tag":532,"props":15790,"children":15791},{"style":631},[15792],{"type":420,"value":241},{"type":415,"tag":532,"props":15794,"children":15795},{"style":804},[15796],{"type":420,"value":15797}," clone",{"type":415,"tag":532,"props":15799,"children":15800},{"style":804},[15801],{"type":420,"value":15802}," https://github.com/TechWatching/azure-ready-repository",{"type":415,"tag":532,"props":15804,"children":15805},{"style":551},[15806],{"type":420,"value":15807},";",{"type":415,"tag":532,"props":15809,"children":15810},{"style":656},[15811],{"type":420,"value":15812}," cd",{"type":415,"tag":532,"props":15814,"children":15815},{"style":804},[15816],{"type":420,"value":15817}," azure-ready-repository\n",{"type":415,"tag":416,"props":15819,"children":15820},{},[15821],{"type":420,"value":15822},"We want to verify that the GitHub project is properly configured and can provision Azure resources from its GitHub Actions workflow.",{"type":415,"tag":416,"props":15824,"children":15825},{},[15826],{"type":420,"value":15827},"Let's add some infrastructure code that provisions a few Azure resources to check that:",{"type":415,"tag":523,"props":15829,"children":15831},{"className":3984,"code":15830,"language":3986,"meta":401,"style":401},"pulumi new azure-typescript -n \"AzureReadyGitHuRepository\" -y --force\n",[15832],{"type":415,"tag":468,"props":15833,"children":15834},{"__ignoreMap":401},[15835],{"type":415,"tag":532,"props":15836,"children":15837},{"class":534,"line":535},[15838,15842,15846,15851,15855,15859,15864,15868,15873],{"type":415,"tag":532,"props":15839,"children":15840},{"style":631},[15841],{"type":420,"value":311},{"type":415,"tag":532,"props":15843,"children":15844},{"style":804},[15845],{"type":420,"value":3276},{"type":415,"tag":532,"props":15847,"children":15848},{"style":804},[15849],{"type":420,"value":15850}," azure-typescript",{"type":415,"tag":532,"props":15852,"children":15853},{"style":804},[15854],{"type":420,"value":6978},{"type":415,"tag":532,"props":15856,"children":15857},{"style":551},[15858],{"type":420,"value":4041},{"type":415,"tag":532,"props":15860,"children":15861},{"style":804},[15862],{"type":420,"value":15863},"AzureReadyGitHuRepository",{"type":415,"tag":532,"props":15865,"children":15866},{"style":551},[15867],{"type":420,"value":801},{"type":415,"tag":532,"props":15869,"children":15870},{"style":804},[15871],{"type":420,"value":15872}," -y",{"type":415,"tag":532,"props":15874,"children":15875},{"style":804},[15876],{"type":420,"value":15877}," --force\n",{"type":415,"tag":416,"props":15879,"children":15880},{},[15881,15882,15888],{"type":420,"value":4968},{"type":415,"tag":468,"props":15883,"children":15885},{"className":15884},[],[15886],{"type":420,"value":15887},"--force",{"type":420,"value":15889}," option allows us to create the code within a non-empty directory.",{"type":415,"tag":416,"props":15891,"children":15892},{},[15893,15895,15901],{"type":420,"value":15894},"I used the ",{"type":415,"tag":468,"props":15896,"children":15898},{"className":15897},[],[15899],{"type":420,"value":15900},"azure-typescript",{"type":420,"value":15902}," template that creates a storage account and outputs retrieve its primary access key.",{"type":415,"tag":434,"props":15904,"children":15905},{"icon":7279},[15906],{"type":415,"tag":416,"props":15907,"children":15908},{},[15909,15911,15918],{"type":420,"value":15910},"In the SDK, the outputs of the function that lists the storage access keys are not currently marked as secrets. There is currently an ",{"type":415,"tag":423,"props":15912,"children":15915},{"href":15913,"rel":15914},"https://github.com/pulumi/pulumi-azure-native/issues/2408",[427],[15916],{"type":420,"value":15917},"open issue",{"type":420,"value":15919}," to change that but in the meantime, I have just modified the code to label the stack output as secret ensuring its encryption.",{"type":415,"tag":416,"props":15921,"children":15922},{},[15923,15925,15931,15933,15939],{"type":420,"value":15924},"Let's run a ",{"type":415,"tag":468,"props":15926,"children":15928},{"className":15927},[],[15929],{"type":420,"value":15930},"pnpm install",{"type":420,"value":15932}," to install the dependencies and generate the ",{"type":415,"tag":468,"props":15934,"children":15936},{"className":15935},[],[15937],{"type":420,"value":15938},"pnpm-lock.yaml",{"type":420,"value":15940}," file. Then, we can push the code to GitHub and run the pipeline to see how it goes.",{"type":415,"tag":416,"props":15942,"children":15943},{},[15944],{"type":415,"tag":3882,"props":15945,"children":15949},{"alt":15946,"className":15947,"src":15948},"Logs of the pipeline run showing that the workflow successfully created a storage account.",[3886,3887],"/posts/images/azurereadygithub_github_3.webp",[],{"type":415,"tag":416,"props":15951,"children":15952},{},[15953],{"type":420,"value":15954},"That's it, we succeeded to provision a storage account from our new GitHub repository whose creation and configuration were entirely automated using Pulumi.",{"type":415,"tag":482,"props":15956,"children":15957},{"id":10889},[15958],{"type":420,"value":10892},{"type":415,"tag":3914,"props":15960,"children":15962},{"id":15961},"additional-information",[15963],{"type":420,"value":15964},"Additional information",{"type":415,"tag":416,"props":15966,"children":15967},{},[15968],{"type":420,"value":15969},"There are different platforms you can use to host your Git repositories: GitHub, GitLab, and Azure DevOps to name a few. We use GitHub in this article but you can easily apply the same logic with other platforms (Pulumi has providers for GitLab and Azure DevOps as well).",{"type":415,"tag":416,"props":15971,"children":15972},{},[15973],{"type":420,"value":15974},"Even though the Azure-Ready GitHub repository is provisioned using Pulumi, there's nothing stopping you from using another Infrastructure as Code solution that supports Azure OIDC (such as Azure CLI, which was mentioned in the article, Azure Bicep, or even Terraform) in the GitHub Actions workflow of the created repository. You don't even have to provision infrastructure; you can use this workflow to simply deploy an application to an existing Azure resource.",{"type":415,"tag":3914,"props":15976,"children":15978},{"id":15977},"potential-enhancements",[15979],{"type":420,"value":15980},"Potential Enhancements",{"type":415,"tag":416,"props":15982,"children":15983},{},[15984],{"type":420,"value":15985},"There are many aspects that could be improved in the infrastructure code provisioning the Azure-Ready GitHub repository, but I believe the current solution serves as a good starting point. Nevertheless, here are some ideas for potential enhancements:",{"type":415,"tag":508,"props":15987,"children":15988},{},[15989,15994,15999],{"type":415,"tag":512,"props":15990,"children":15991},{},[15992],{"type":420,"value":15993},"make additional items, such as the commit author, configurable",{"type":415,"tag":512,"props":15995,"children":15996},{},[15997],{"type":420,"value":15998},"authorize an environment and not only a branch to retrieve an Azure token",{"type":415,"tag":512,"props":16000,"children":16001},{},[16002],{"type":420,"value":16003},"use environment variables/secrets instead of variable/secrets at the repository scope",{"type":415,"tag":416,"props":16005,"children":16006},{},[16007],{"type":420,"value":16008},"I think it would be interesting as well to put that code behind an API or a Web application using Pulumi Automation API to have a self-service solution to create Azure-Ready GitHub repository on the fly.",{"type":415,"tag":3914,"props":16010,"children":16012},{"id":16011},"related-articles",[16013],{"type":420,"value":16014},"Related articles",{"type":415,"tag":416,"props":16016,"children":16017},{},[16018],{"type":420,"value":16019},"Here are some articles on the same topic I wanted to mention:",{"type":415,"tag":508,"props":16021,"children":16022},{},[16023,16054,16082],{"type":415,"tag":512,"props":16024,"children":16025},{},[16026,16036,16038,16043,16047,16052],{"type":415,"tag":423,"props":16027,"children":16030},{"href":16028,"rel":16029},"https://leebriggs.co.uk/blog/2022/01/23/gha-cloud-credentials",[427],[16031],{"type":415,"tag":6864,"props":16032,"children":16033},{},[16034],{"type":420,"value":16035},"Stop using static cloud credentials in GitHub Actions",{"type":420,"value":16037}," ",{"type":415,"tag":6864,"props":16039,"children":16040},{},[16041],{"type":420,"value":16042},"by Lee Briggs",{"type":415,"tag":16044,"props":16045,"children":16046},"br",{},[],{"type":415,"tag":6864,"props":16048,"children":16049},{},[16050],{"type":420,"value":16051},"➡️",{"type":420,"value":16053}," This post provides examples for configuring OIDC authentication with GitHub Actions for AWS, Azure, and GCP. The code for Azure is quite similar to the code I showed here. Yet, it doesn't go so far as to initialize a pipeline ready to deploy resources with Pulumi. Anyway, it's awesome to have the code for all 3 major providers.",{"type":415,"tag":512,"props":16055,"children":16056},{},[16057,16067,16068,16073,16076,16080],{"type":415,"tag":423,"props":16058,"children":16061},{"href":16059,"rel":16060},"https://xaviergeerinck.com/2023/05/16/configuring-github-actions-to-azure-authentication-with-oidc/",[427],[16062],{"type":415,"tag":6864,"props":16063,"children":16064},{},[16065],{"type":420,"value":16066},"Configuring GitHub Actions to Azure authentication with OIDC",{"type":420,"value":16037},{"type":415,"tag":6864,"props":16069,"children":16070},{},[16071],{"type":420,"value":16072},"by Xavier Geerinck",{"type":415,"tag":16044,"props":16074,"children":16075},{},[],{"type":415,"tag":6864,"props":16077,"children":16078},{},[16079],{"type":420,"value":16051},{"type":420,"value":16081},"This post also shows how to configure OIDC authentication with GitHub Actions and Azure but using an Azure CLI script. Although the GitHub repository creation and configuration are done manually, automating the Azure part with a few lines of script is nice.",{"type":415,"tag":512,"props":16083,"children":16084},{},[16085,16095,16096,16101,16104],{"type":415,"tag":423,"props":16086,"children":16089},{"href":16087,"rel":16088},"https://samcogan.com/getting-rid-of-passwords-for-deployment-with-pulumi-oidc-support/",[427],[16090],{"type":415,"tag":6864,"props":16091,"children":16092},{},[16093],{"type":420,"value":16094},"Getting Rid of Passwords for Deployment with Pulumi OIDC Support",{"type":420,"value":16037},{"type":415,"tag":6864,"props":16097,"children":16098},{},[16099],{"type":420,"value":16100},"by Sam Cogan",{"type":415,"tag":16044,"props":16102,"children":16103},{},[],{"type":420,"value":16105},"\n➡️ If you don't care about automating everything and simply want to configure OIDC authentication through the Azure portal, that's the post you will want to read. There is also an example of a pipeline to provision Azure infrastructure using a .NET Pulumi program.",{"type":415,"tag":3914,"props":16107,"children":16109},{"id":16108},"complete-code-solution",[16110],{"type":420,"value":16111},"Complete code solution",{"type":415,"tag":416,"props":16113,"children":16114},{},[16115],{"type":420,"value":16116},"In this article, I aimed to provide a step-by-step explanation of how to automate the creation of a GitHub repository with a properly configured workflow to interact with Azure using OpenID Connect. Consequently, the article turned out to be quite lengthy. I apologize for that, but I didn't want to present the code without adequate explanation.",{"type":415,"tag":416,"props":16118,"children":16119},{},[16120],{"type":420,"value":16121},"Anyway, now that we've covered everything, here is the complete code, which is just 75 lines long:",{"type":415,"tag":523,"props":16123,"children":16125},{"className":11642,"code":16124,"language":357,"meta":401,"style":401},"import * as pulumi from \"@pulumi/pulumi\";\nimport * as github from \"@pulumi/github\";\nimport * as azuread from \"@pulumi/azuread\";\nimport * as authorization from \"@pulumi/azure-native/authorization\";\nimport { azureBuiltInRoles } from \"./builtInRoles\";\nimport { readFileSync } from \"fs\";\n\nconst config = new pulumi.Config();\n\nconst repository = new github.Repository(\"azure-ready-repository\", {\n  name: \"azure-ready-repository\",\n  visibility: \"public\",\n  autoInit: true\n});\n\nexport const repositoryCloneUrl = repository.httpCloneUrl;\n\nconst aadApplication = new azuread.Application(\"AzureReadyApp\", { displayName: \"Azure Ready App\" });\nconst servicePrincipal = new azuread.ServicePrincipal(\"AzureReadyServicePrincipal\", {\n  applicationId: aadApplication.applicationId,\n});\nnew azuread.ApplicationFederatedIdentityCredential(\"AzureReadyAppFederatedIdentityCredential\", {\n  applicationObjectId: aadApplication.objectId,\n  displayName: \"AzureReadyDeploys\",\n  description: \"Deployments for azure-ready-repository\",\n  audiences: [\"api://AzureADTokenExchange\"],\n  issuer: \"https://token.actions.githubusercontent.com\",\n  subject: pulumi.interpolate`repo:${repository.fullName}:ref:refs/heads/main`,\n});\n\nconst azureConfig = pulumi.output(authorization.getClientConfig());\nconst subscriptionId = azureConfig.subscriptionId;\n\nnew authorization.RoleAssignment(\"contributor\", {\n  principalId: servicePrincipal.id,\n  principalType: authorization.PrincipalType.ServicePrincipal,\n  roleDefinitionId: azureBuiltInRoles.contributor,\n  scope: pulumi.interpolate`/subscriptions/${subscriptionId}`,\n});\n\nnew github.ActionsSecret(\"tenantId\", {\n  repository: repository.name,\n  secretName: \"ARM_TENANT_ID\",\n  plaintextValue: azureConfig.tenantId,\n});\n\nnew github.ActionsSecret(\"subscriptionId\", {\n  repository: repository.name,\n  secretName: \"ARM_SUBSCRIPTION_ID\",\n  plaintextValue: azureConfig.subscriptionId,\n});\n\nnew github.ActionsSecret(\"clientId\", {\n  repository: repository.name,\n  secretName: \"ARM_CLIENT_ID\",\n  plaintextValue: aadApplication.applicationId,\n});\n\nnew github.ActionsSecret(\"pulumiAccessToken\", {\n  repository: repository.name,\n  secretName: \"PULUMI_ACCESS_TOKEN\",\n  plaintextValue: config.requireSecret(\"pulumiTokenForRepository\"),\n});\n\nconst pipelineContent = readFileSync(\"main.yml\", \"utf-8\");\nnew github.RepositoryFile(\"pipelineRepositoryFile\", {\n  repository: repository.name,\n  branch: \"main\",\n  file: \".github/workflows/main.yml\",\n  content: pipelineContent,\n  commitMessage: \"Add preconfigured pipeline file\",\n  commitAuthor: \"Alexandre Nédélec\",\n  commitEmail: \"15186176+TechWatching@users.noreply.github.com\",\n  overwriteOnCreate: true,\n});\n",[16126],{"type":415,"tag":468,"props":16127,"children":16128},{"__ignoreMap":401},[16129,16170,16209,16248,16287,16326,16365,16372,16411,16418,16473,16500,16527,16542,16557,16564,16599,16606,16693,16748,16775,16790,16833,16860,16887,16914,16949,16976,17039,17054,17061,17108,17139,17146,17189,17216,17251,17278,17325,17340,17347,17390,17417,17444,17471,17486,17493,17536,17563,17590,17617,17632,17639,17682,17709,17737,17765,17781,17789,17833,17861,17889,17937,17953,17961,18021,18065,18093,18121,18149,18169,18197,18225,18253,18273],{"type":415,"tag":532,"props":16130,"children":16131},{"class":534,"line":535},[16132,16136,16140,16144,16149,16153,16157,16162,16166],{"type":415,"tag":532,"props":16133,"children":16134},{"style":1241},[16135],{"type":420,"value":11655},{"type":415,"tag":532,"props":16137,"children":16138},{"style":551},[16139],{"type":420,"value":11660},{"type":415,"tag":532,"props":16141,"children":16142},{"style":1241},[16143],{"type":420,"value":11665},{"type":415,"tag":532,"props":16145,"children":16146},{"style":545},[16147],{"type":420,"value":16148}," pulumi ",{"type":415,"tag":532,"props":16150,"children":16151},{"style":1241},[16152],{"type":420,"value":11675},{"type":415,"tag":532,"props":16154,"children":16155},{"style":551},[16156],{"type":420,"value":4041},{"type":415,"tag":532,"props":16158,"children":16159},{"style":804},[16160],{"type":420,"value":16161},"@pulumi/pulumi",{"type":415,"tag":532,"props":16163,"children":16164},{"style":551},[16165],{"type":420,"value":801},{"type":415,"tag":532,"props":16167,"children":16168},{"style":551},[16169],{"type":420,"value":563},{"type":415,"tag":532,"props":16171,"children":16172},{"class":534,"line":566},[16173,16177,16181,16185,16189,16193,16197,16201,16205],{"type":415,"tag":532,"props":16174,"children":16175},{"style":1241},[16176],{"type":420,"value":11655},{"type":415,"tag":532,"props":16178,"children":16179},{"style":551},[16180],{"type":420,"value":11660},{"type":415,"tag":532,"props":16182,"children":16183},{"style":1241},[16184],{"type":420,"value":11665},{"type":415,"tag":532,"props":16186,"children":16187},{"style":545},[16188],{"type":420,"value":11670},{"type":415,"tag":532,"props":16190,"children":16191},{"style":1241},[16192],{"type":420,"value":11675},{"type":415,"tag":532,"props":16194,"children":16195},{"style":551},[16196],{"type":420,"value":4041},{"type":415,"tag":532,"props":16198,"children":16199},{"style":804},[16200],{"type":420,"value":11568},{"type":415,"tag":532,"props":16202,"children":16203},{"style":551},[16204],{"type":420,"value":801},{"type":415,"tag":532,"props":16206,"children":16207},{"style":551},[16208],{"type":420,"value":563},{"type":415,"tag":532,"props":16210,"children":16211},{"class":534,"line":583},[16212,16216,16220,16224,16228,16232,16236,16240,16244],{"type":415,"tag":532,"props":16213,"children":16214},{"style":1241},[16215],{"type":420,"value":11655},{"type":415,"tag":532,"props":16217,"children":16218},{"style":551},[16219],{"type":420,"value":11660},{"type":415,"tag":532,"props":16221,"children":16222},{"style":1241},[16223],{"type":420,"value":11665},{"type":415,"tag":532,"props":16225,"children":16226},{"style":545},[16227],{"type":420,"value":12012},{"type":415,"tag":532,"props":16229,"children":16230},{"style":1241},[16231],{"type":420,"value":11675},{"type":415,"tag":532,"props":16233,"children":16234},{"style":551},[16235],{"type":420,"value":4041},{"type":415,"tag":532,"props":16237,"children":16238},{"style":804},[16239],{"type":420,"value":11563},{"type":415,"tag":532,"props":16241,"children":16242},{"style":551},[16243],{"type":420,"value":801},{"type":415,"tag":532,"props":16245,"children":16246},{"style":551},[16247],{"type":420,"value":563},{"type":415,"tag":532,"props":16249,"children":16250},{"class":534,"line":617},[16251,16255,16259,16263,16267,16271,16275,16279,16283],{"type":415,"tag":532,"props":16252,"children":16253},{"style":1241},[16254],{"type":420,"value":11655},{"type":415,"tag":532,"props":16256,"children":16257},{"style":551},[16258],{"type":420,"value":11660},{"type":415,"tag":532,"props":16260,"children":16261},{"style":1241},[16262],{"type":420,"value":11665},{"type":415,"tag":532,"props":16264,"children":16265},{"style":545},[16266],{"type":420,"value":12637},{"type":415,"tag":532,"props":16268,"children":16269},{"style":1241},[16270],{"type":420,"value":11675},{"type":415,"tag":532,"props":16272,"children":16273},{"style":551},[16274],{"type":420,"value":4041},{"type":415,"tag":532,"props":16276,"children":16277},{"style":804},[16278],{"type":420,"value":12650},{"type":415,"tag":532,"props":16280,"children":16281},{"style":551},[16282],{"type":420,"value":801},{"type":415,"tag":532,"props":16284,"children":16285},{"style":551},[16286],{"type":420,"value":563},{"type":415,"tag":532,"props":16288,"children":16289},{"class":534,"line":627},[16290,16294,16298,16302,16306,16310,16314,16318,16322],{"type":415,"tag":532,"props":16291,"children":16292},{"style":1241},[16293],{"type":420,"value":11655},{"type":415,"tag":532,"props":16295,"children":16296},{"style":551},[16297],{"type":420,"value":3347},{"type":415,"tag":532,"props":16299,"children":16300},{"style":545},[16301],{"type":420,"value":12674},{"type":415,"tag":532,"props":16303,"children":16304},{"style":551},[16305],{"type":420,"value":12125},{"type":415,"tag":532,"props":16307,"children":16308},{"style":1241},[16309],{"type":420,"value":12683},{"type":415,"tag":532,"props":16311,"children":16312},{"style":551},[16313],{"type":420,"value":4041},{"type":415,"tag":532,"props":16315,"children":16316},{"style":804},[16317],{"type":420,"value":12692},{"type":415,"tag":532,"props":16319,"children":16320},{"style":551},[16321],{"type":420,"value":801},{"type":415,"tag":532,"props":16323,"children":16324},{"style":551},[16325],{"type":420,"value":563},{"type":415,"tag":532,"props":16327,"children":16328},{"class":534,"line":677},[16329,16333,16337,16341,16345,16349,16353,16357,16361],{"type":415,"tag":532,"props":16330,"children":16331},{"style":1241},[16332],{"type":420,"value":11655},{"type":415,"tag":532,"props":16334,"children":16335},{"style":551},[16336],{"type":420,"value":3347},{"type":415,"tag":532,"props":16338,"children":16339},{"style":545},[16340],{"type":420,"value":15307},{"type":415,"tag":532,"props":16342,"children":16343},{"style":551},[16344],{"type":420,"value":12125},{"type":415,"tag":532,"props":16346,"children":16347},{"style":1241},[16348],{"type":420,"value":12683},{"type":415,"tag":532,"props":16350,"children":16351},{"style":551},[16352],{"type":420,"value":4041},{"type":415,"tag":532,"props":16354,"children":16355},{"style":804},[16356],{"type":420,"value":15324},{"type":415,"tag":532,"props":16358,"children":16359},{"style":551},[16360],{"type":420,"value":801},{"type":415,"tag":532,"props":16362,"children":16363},{"style":551},[16364],{"type":420,"value":563},{"type":415,"tag":532,"props":16366,"children":16367},{"class":534,"line":719},[16368],{"type":415,"tag":532,"props":16369,"children":16370},{"emptyLinePlaceholder":621},[16371],{"type":420,"value":624},{"type":415,"tag":532,"props":16373,"children":16374},{"class":534,"line":758},[16375,16379,16383,16387,16391,16395,16399,16403,16407],{"type":415,"tag":532,"props":16376,"children":16377},{"style":954},[16378],{"type":420,"value":11706},{"type":415,"tag":532,"props":16380,"children":16381},{"style":545},[16382],{"type":420,"value":12940},{"type":415,"tag":532,"props":16384,"children":16385},{"style":551},[16386],{"type":420,"value":1134},{"type":415,"tag":532,"props":16388,"children":16389},{"style":551},[16390],{"type":420,"value":3276},{"type":415,"tag":532,"props":16392,"children":16393},{"style":545},[16394],{"type":420,"value":12474},{"type":415,"tag":532,"props":16396,"children":16397},{"style":551},[16398],{"type":420,"value":432},{"type":415,"tag":532,"props":16400,"children":16401},{"style":656},[16402],{"type":420,"value":12961},{"type":415,"tag":532,"props":16404,"children":16405},{"style":545},[16406],{"type":420,"value":12966},{"type":415,"tag":532,"props":16408,"children":16409},{"style":551},[16410],{"type":420,"value":563},{"type":415,"tag":532,"props":16412,"children":16413},{"class":534,"line":767},[16414],{"type":415,"tag":532,"props":16415,"children":16416},{"emptyLinePlaceholder":621},[16417],{"type":420,"value":624},{"type":415,"tag":532,"props":16419,"children":16420},{"class":534,"line":819},[16421,16425,16429,16433,16437,16441,16445,16449,16453,16457,16461,16465,16469],{"type":415,"tag":532,"props":16422,"children":16423},{"style":954},[16424],{"type":420,"value":11706},{"type":415,"tag":532,"props":16426,"children":16427},{"style":545},[16428],{"type":420,"value":11711},{"type":415,"tag":532,"props":16430,"children":16431},{"style":551},[16432],{"type":420,"value":1134},{"type":415,"tag":532,"props":16434,"children":16435},{"style":551},[16436],{"type":420,"value":3276},{"type":415,"tag":532,"props":16438,"children":16439},{"style":545},[16440],{"type":420,"value":11724},{"type":415,"tag":532,"props":16442,"children":16443},{"style":551},[16444],{"type":420,"value":432},{"type":415,"tag":532,"props":16446,"children":16447},{"style":656},[16448],{"type":420,"value":11733},{"type":415,"tag":532,"props":16450,"children":16451},{"style":545},[16452],{"type":420,"value":664},{"type":415,"tag":532,"props":16454,"children":16455},{"style":551},[16456],{"type":420,"value":801},{"type":415,"tag":532,"props":16458,"children":16459},{"style":804},[16460],{"type":420,"value":11746},{"type":415,"tag":532,"props":16462,"children":16463},{"style":551},[16464],{"type":420,"value":801},{"type":415,"tag":532,"props":16466,"children":16467},{"style":551},[16468],{"type":420,"value":1099},{"type":415,"tag":532,"props":16470,"children":16471},{"style":551},[16472],{"type":420,"value":11759},{"type":415,"tag":532,"props":16474,"children":16475},{"class":534,"line":850},[16476,16480,16484,16488,16492,16496],{"type":415,"tag":532,"props":16477,"children":16478},{"style":3532},[16479],{"type":420,"value":11767},{"type":415,"tag":532,"props":16481,"children":16482},{"style":551},[16483],{"type":420,"value":1290},{"type":415,"tag":532,"props":16485,"children":16486},{"style":551},[16487],{"type":420,"value":4041},{"type":415,"tag":532,"props":16489,"children":16490},{"style":804},[16491],{"type":420,"value":11746},{"type":415,"tag":532,"props":16493,"children":16494},{"style":551},[16495],{"type":420,"value":801},{"type":415,"tag":532,"props":16497,"children":16498},{"style":551},[16499],{"type":420,"value":7400},{"type":415,"tag":532,"props":16501,"children":16502},{"class":534,"line":859},[16503,16507,16511,16515,16519,16523],{"type":415,"tag":532,"props":16504,"children":16505},{"style":3532},[16506],{"type":420,"value":11795},{"type":415,"tag":532,"props":16508,"children":16509},{"style":551},[16510],{"type":420,"value":1290},{"type":415,"tag":532,"props":16512,"children":16513},{"style":551},[16514],{"type":420,"value":4041},{"type":415,"tag":532,"props":16516,"children":16517},{"style":804},[16518],{"type":420,"value":957},{"type":415,"tag":532,"props":16520,"children":16521},{"style":551},[16522],{"type":420,"value":801},{"type":415,"tag":532,"props":16524,"children":16525},{"style":551},[16526],{"type":420,"value":7400},{"type":415,"tag":532,"props":16528,"children":16529},{"class":534,"line":867},[16530,16534,16538],{"type":415,"tag":532,"props":16531,"children":16532},{"style":3532},[16533],{"type":420,"value":11823},{"type":415,"tag":532,"props":16535,"children":16536},{"style":551},[16537],{"type":420,"value":1290},{"type":415,"tag":532,"props":16539,"children":16540},{"style":1938},[16541],{"type":420,"value":11832},{"type":415,"tag":532,"props":16543,"children":16544},{"class":534,"line":902},[16545,16549,16553],{"type":415,"tag":532,"props":16546,"children":16547},{"style":551},[16548],{"type":420,"value":4864},{"type":415,"tag":532,"props":16550,"children":16551},{"style":545},[16552],{"type":420,"value":1349},{"type":415,"tag":532,"props":16554,"children":16555},{"style":551},[16556],{"type":420,"value":563},{"type":415,"tag":532,"props":16558,"children":16559},{"class":534,"line":1302},[16560],{"type":415,"tag":532,"props":16561,"children":16562},{"emptyLinePlaceholder":621},[16563],{"type":420,"value":624},{"type":415,"tag":532,"props":16565,"children":16566},{"class":534,"line":1311},[16567,16571,16575,16579,16583,16587,16591,16595],{"type":415,"tag":532,"props":16568,"children":16569},{"style":1241},[16570],{"type":420,"value":11862},{"type":415,"tag":532,"props":16572,"children":16573},{"style":954},[16574],{"type":420,"value":11867},{"type":415,"tag":532,"props":16576,"children":16577},{"style":545},[16578],{"type":420,"value":11872},{"type":415,"tag":532,"props":16580,"children":16581},{"style":551},[16582],{"type":420,"value":1134},{"type":415,"tag":532,"props":16584,"children":16585},{"style":545},[16586],{"type":420,"value":7695},{"type":415,"tag":532,"props":16588,"children":16589},{"style":551},[16590],{"type":420,"value":432},{"type":415,"tag":532,"props":16592,"children":16593},{"style":545},[16594],{"type":420,"value":11889},{"type":415,"tag":532,"props":16596,"children":16597},{"style":551},[16598],{"type":420,"value":563},{"type":415,"tag":532,"props":16600,"children":16601},{"class":534,"line":1356},[16602],{"type":415,"tag":532,"props":16603,"children":16604},{"emptyLinePlaceholder":621},[16605],{"type":420,"value":624},{"type":415,"tag":532,"props":16607,"children":16608},{"class":534,"line":1365},[16609,16613,16617,16621,16625,16629,16633,16637,16641,16645,16649,16653,16657,16661,16665,16669,16673,16677,16681,16685,16689],{"type":415,"tag":532,"props":16610,"children":16611},{"style":954},[16612],{"type":420,"value":11706},{"type":415,"tag":532,"props":16614,"children":16615},{"style":545},[16616],{"type":420,"value":12051},{"type":415,"tag":532,"props":16618,"children":16619},{"style":551},[16620],{"type":420,"value":1134},{"type":415,"tag":532,"props":16622,"children":16623},{"style":551},[16624],{"type":420,"value":3276},{"type":415,"tag":532,"props":16626,"children":16627},{"style":545},[16628],{"type":420,"value":12064},{"type":415,"tag":532,"props":16630,"children":16631},{"style":551},[16632],{"type":420,"value":432},{"type":415,"tag":532,"props":16634,"children":16635},{"style":656},[16636],{"type":420,"value":12073},{"type":415,"tag":532,"props":16638,"children":16639},{"style":545},[16640],{"type":420,"value":664},{"type":415,"tag":532,"props":16642,"children":16643},{"style":551},[16644],{"type":420,"value":801},{"type":415,"tag":532,"props":16646,"children":16647},{"style":804},[16648],{"type":420,"value":12086},{"type":415,"tag":532,"props":16650,"children":16651},{"style":551},[16652],{"type":420,"value":801},{"type":415,"tag":532,"props":16654,"children":16655},{"style":551},[16656],{"type":420,"value":1099},{"type":415,"tag":532,"props":16658,"children":16659},{"style":551},[16660],{"type":420,"value":3347},{"type":415,"tag":532,"props":16662,"children":16663},{"style":3532},[16664],{"type":420,"value":12103},{"type":415,"tag":532,"props":16666,"children":16667},{"style":551},[16668],{"type":420,"value":1290},{"type":415,"tag":532,"props":16670,"children":16671},{"style":551},[16672],{"type":420,"value":4041},{"type":415,"tag":532,"props":16674,"children":16675},{"style":804},[16676],{"type":420,"value":12116},{"type":415,"tag":532,"props":16678,"children":16679},{"style":551},[16680],{"type":420,"value":801},{"type":415,"tag":532,"props":16682,"children":16683},{"style":551},[16684],{"type":420,"value":12125},{"type":415,"tag":532,"props":16686,"children":16687},{"style":545},[16688],{"type":420,"value":1349},{"type":415,"tag":532,"props":16690,"children":16691},{"style":551},[16692],{"type":420,"value":563},{"type":415,"tag":532,"props":16694,"children":16695},{"class":534,"line":1373},[16696,16700,16704,16708,16712,16716,16720,16724,16728,16732,16736,16740,16744],{"type":415,"tag":532,"props":16697,"children":16698},{"style":954},[16699],{"type":420,"value":11706},{"type":415,"tag":532,"props":16701,"children":16702},{"style":545},[16703],{"type":420,"value":12145},{"type":415,"tag":532,"props":16705,"children":16706},{"style":551},[16707],{"type":420,"value":1134},{"type":415,"tag":532,"props":16709,"children":16710},{"style":551},[16711],{"type":420,"value":3276},{"type":415,"tag":532,"props":16713,"children":16714},{"style":545},[16715],{"type":420,"value":12064},{"type":415,"tag":532,"props":16717,"children":16718},{"style":551},[16719],{"type":420,"value":432},{"type":415,"tag":532,"props":16721,"children":16722},{"style":656},[16723],{"type":420,"value":9233},{"type":415,"tag":532,"props":16725,"children":16726},{"style":545},[16727],{"type":420,"value":664},{"type":415,"tag":532,"props":16729,"children":16730},{"style":551},[16731],{"type":420,"value":801},{"type":415,"tag":532,"props":16733,"children":16734},{"style":804},[16735],{"type":420,"value":9018},{"type":415,"tag":532,"props":16737,"children":16738},{"style":551},[16739],{"type":420,"value":801},{"type":415,"tag":532,"props":16741,"children":16742},{"style":551},[16743],{"type":420,"value":1099},{"type":415,"tag":532,"props":16745,"children":16746},{"style":551},[16747],{"type":420,"value":11759},{"type":415,"tag":532,"props":16749,"children":16750},{"class":534,"line":3825},[16751,16755,16759,16763,16767,16771],{"type":415,"tag":532,"props":16752,"children":16753},{"style":3532},[16754],{"type":420,"value":12198},{"type":415,"tag":532,"props":16756,"children":16757},{"style":551},[16758],{"type":420,"value":1290},{"type":415,"tag":532,"props":16760,"children":16761},{"style":545},[16762],{"type":420,"value":8903},{"type":415,"tag":532,"props":16764,"children":16765},{"style":551},[16766],{"type":420,"value":432},{"type":415,"tag":532,"props":16768,"children":16769},{"style":545},[16770],{"type":420,"value":12215},{"type":415,"tag":532,"props":16772,"children":16773},{"style":551},[16774],{"type":420,"value":7400},{"type":415,"tag":532,"props":16776,"children":16777},{"class":534,"line":3843},[16778,16782,16786],{"type":415,"tag":532,"props":16779,"children":16780},{"style":551},[16781],{"type":420,"value":4864},{"type":415,"tag":532,"props":16783,"children":16784},{"style":545},[16785],{"type":420,"value":1349},{"type":415,"tag":532,"props":16787,"children":16788},{"style":551},[16789],{"type":420,"value":563},{"type":415,"tag":532,"props":16791,"children":16792},{"class":534,"line":3852},[16793,16797,16801,16805,16809,16813,16817,16821,16825,16829],{"type":415,"tag":532,"props":16794,"children":16795},{"style":551},[16796],{"type":420,"value":9142},{"type":415,"tag":532,"props":16798,"children":16799},{"style":545},[16800],{"type":420,"value":12064},{"type":415,"tag":532,"props":16802,"children":16803},{"style":551},[16804],{"type":420,"value":432},{"type":415,"tag":532,"props":16806,"children":16807},{"style":656},[16808],{"type":420,"value":12282},{"type":415,"tag":532,"props":16810,"children":16811},{"style":545},[16812],{"type":420,"value":664},{"type":415,"tag":532,"props":16814,"children":16815},{"style":551},[16816],{"type":420,"value":801},{"type":415,"tag":532,"props":16818,"children":16819},{"style":804},[16820],{"type":420,"value":12295},{"type":415,"tag":532,"props":16822,"children":16823},{"style":551},[16824],{"type":420,"value":801},{"type":415,"tag":532,"props":16826,"children":16827},{"style":551},[16828],{"type":420,"value":1099},{"type":415,"tag":532,"props":16830,"children":16831},{"style":551},[16832],{"type":420,"value":11759},{"type":415,"tag":532,"props":16834,"children":16835},{"class":534,"line":5941},[16836,16840,16844,16848,16852,16856],{"type":415,"tag":532,"props":16837,"children":16838},{"style":3532},[16839],{"type":420,"value":12315},{"type":415,"tag":532,"props":16841,"children":16842},{"style":551},[16843],{"type":420,"value":1290},{"type":415,"tag":532,"props":16845,"children":16846},{"style":545},[16847],{"type":420,"value":8903},{"type":415,"tag":532,"props":16849,"children":16850},{"style":551},[16851],{"type":420,"value":432},{"type":415,"tag":532,"props":16853,"children":16854},{"style":545},[16855],{"type":420,"value":12332},{"type":415,"tag":532,"props":16857,"children":16858},{"style":551},[16859],{"type":420,"value":7400},{"type":415,"tag":532,"props":16861,"children":16862},{"class":534,"line":6053},[16863,16867,16871,16875,16879,16883],{"type":415,"tag":532,"props":16864,"children":16865},{"style":3532},[16866],{"type":420,"value":12344},{"type":415,"tag":532,"props":16868,"children":16869},{"style":551},[16870],{"type":420,"value":1290},{"type":415,"tag":532,"props":16872,"children":16873},{"style":551},[16874],{"type":420,"value":4041},{"type":415,"tag":532,"props":16876,"children":16877},{"style":804},[16878],{"type":420,"value":9453},{"type":415,"tag":532,"props":16880,"children":16881},{"style":551},[16882],{"type":420,"value":801},{"type":415,"tag":532,"props":16884,"children":16885},{"style":551},[16886],{"type":420,"value":7400},{"type":415,"tag":532,"props":16888,"children":16889},{"class":534,"line":6061},[16890,16894,16898,16902,16906,16910],{"type":415,"tag":532,"props":16891,"children":16892},{"style":3532},[16893],{"type":420,"value":12372},{"type":415,"tag":532,"props":16895,"children":16896},{"style":551},[16897],{"type":420,"value":1290},{"type":415,"tag":532,"props":16899,"children":16900},{"style":551},[16901],{"type":420,"value":4041},{"type":415,"tag":532,"props":16903,"children":16904},{"style":804},[16905],{"type":420,"value":9481},{"type":415,"tag":532,"props":16907,"children":16908},{"style":551},[16909],{"type":420,"value":801},{"type":415,"tag":532,"props":16911,"children":16912},{"style":551},[16913],{"type":420,"value":7400},{"type":415,"tag":532,"props":16915,"children":16916},{"class":534,"line":6070},[16917,16921,16925,16929,16933,16937,16941,16945],{"type":415,"tag":532,"props":16918,"children":16919},{"style":3532},[16920],{"type":420,"value":12400},{"type":415,"tag":532,"props":16922,"children":16923},{"style":551},[16924],{"type":420,"value":1290},{"type":415,"tag":532,"props":16926,"children":16927},{"style":545},[16928],{"type":420,"value":12409},{"type":415,"tag":532,"props":16930,"children":16931},{"style":551},[16932],{"type":420,"value":801},{"type":415,"tag":532,"props":16934,"children":16935},{"style":804},[16936],{"type":420,"value":4941},{"type":415,"tag":532,"props":16938,"children":16939},{"style":551},[16940],{"type":420,"value":801},{"type":415,"tag":532,"props":16942,"children":16943},{"style":545},[16944],{"type":420,"value":7449},{"type":415,"tag":532,"props":16946,"children":16947},{"style":551},[16948],{"type":420,"value":7400},{"type":415,"tag":532,"props":16950,"children":16951},{"class":534,"line":6094},[16952,16956,16960,16964,16968,16972],{"type":415,"tag":532,"props":16953,"children":16954},{"style":3532},[16955],{"type":420,"value":12437},{"type":415,"tag":532,"props":16957,"children":16958},{"style":551},[16959],{"type":420,"value":1290},{"type":415,"tag":532,"props":16961,"children":16962},{"style":551},[16963],{"type":420,"value":4041},{"type":415,"tag":532,"props":16965,"children":16966},{"style":804},[16967],{"type":420,"value":4826},{"type":415,"tag":532,"props":16969,"children":16970},{"style":551},[16971],{"type":420,"value":801},{"type":415,"tag":532,"props":16973,"children":16974},{"style":551},[16975],{"type":420,"value":7400},{"type":415,"tag":532,"props":16977,"children":16978},{"class":534,"line":6118},[16979,16983,16987,16991,16995,16999,17003,17007,17011,17015,17019,17023,17027,17031,17035],{"type":415,"tag":532,"props":16980,"children":16981},{"style":3532},[16982],{"type":420,"value":12465},{"type":415,"tag":532,"props":16984,"children":16985},{"style":551},[16986],{"type":420,"value":1290},{"type":415,"tag":532,"props":16988,"children":16989},{"style":545},[16990],{"type":420,"value":12474},{"type":415,"tag":532,"props":16992,"children":16993},{"style":551},[16994],{"type":420,"value":432},{"type":415,"tag":532,"props":16996,"children":16997},{"style":656},[16998],{"type":420,"value":12483},{"type":415,"tag":532,"props":17000,"children":17001},{"style":551},[17002],{"type":420,"value":12488},{"type":415,"tag":532,"props":17004,"children":17005},{"style":804},[17006],{"type":420,"value":4851},{"type":415,"tag":532,"props":17008,"children":17009},{"style":551},[17010],{"type":420,"value":4493},{"type":415,"tag":532,"props":17012,"children":17013},{"style":545},[17014],{"type":420,"value":12501},{"type":415,"tag":532,"props":17016,"children":17017},{"style":551},[17018],{"type":420,"value":432},{"type":415,"tag":532,"props":17020,"children":17021},{"style":545},[17022],{"type":420,"value":12510},{"type":415,"tag":532,"props":17024,"children":17025},{"style":551},[17026],{"type":420,"value":4864},{"type":415,"tag":532,"props":17028,"children":17029},{"style":804},[17030],{"type":420,"value":4869},{"type":415,"tag":532,"props":17032,"children":17033},{"style":551},[17034],{"type":420,"value":12488},{"type":415,"tag":532,"props":17036,"children":17037},{"style":551},[17038],{"type":420,"value":7400},{"type":415,"tag":532,"props":17040,"children":17041},{"class":534,"line":6142},[17042,17046,17050],{"type":415,"tag":532,"props":17043,"children":17044},{"style":551},[17045],{"type":420,"value":4864},{"type":415,"tag":532,"props":17047,"children":17048},{"style":545},[17049],{"type":420,"value":1349},{"type":415,"tag":532,"props":17051,"children":17052},{"style":551},[17053],{"type":420,"value":563},{"type":415,"tag":532,"props":17055,"children":17056},{"class":534,"line":6182},[17057],{"type":415,"tag":532,"props":17058,"children":17059},{"emptyLinePlaceholder":621},[17060],{"type":420,"value":624},{"type":415,"tag":532,"props":17062,"children":17063},{"class":534,"line":6214},[17064,17068,17072,17076,17080,17084,17088,17092,17096,17100,17104],{"type":415,"tag":532,"props":17065,"children":17066},{"style":954},[17067],{"type":420,"value":11706},{"type":415,"tag":532,"props":17069,"children":17070},{"style":545},[17071],{"type":420,"value":13047},{"type":415,"tag":532,"props":17073,"children":17074},{"style":551},[17075],{"type":420,"value":1134},{"type":415,"tag":532,"props":17077,"children":17078},{"style":545},[17079],{"type":420,"value":12474},{"type":415,"tag":532,"props":17081,"children":17082},{"style":551},[17083],{"type":420,"value":432},{"type":415,"tag":532,"props":17085,"children":17086},{"style":656},[17087],{"type":420,"value":11926},{"type":415,"tag":532,"props":17089,"children":17090},{"style":545},[17091],{"type":420,"value":13068},{"type":415,"tag":532,"props":17093,"children":17094},{"style":551},[17095],{"type":420,"value":432},{"type":415,"tag":532,"props":17097,"children":17098},{"style":656},[17099],{"type":420,"value":13077},{"type":415,"tag":532,"props":17101,"children":17102},{"style":545},[17103],{"type":420,"value":13082},{"type":415,"tag":532,"props":17105,"children":17106},{"style":551},[17107],{"type":420,"value":563},{"type":415,"tag":532,"props":17109,"children":17110},{"class":534,"line":6234},[17111,17115,17119,17123,17127,17131,17135],{"type":415,"tag":532,"props":17112,"children":17113},{"style":954},[17114],{"type":420,"value":11706},{"type":415,"tag":532,"props":17116,"children":17117},{"style":545},[17118],{"type":420,"value":12982},{"type":415,"tag":532,"props":17120,"children":17121},{"style":551},[17122],{"type":420,"value":1134},{"type":415,"tag":532,"props":17124,"children":17125},{"style":545},[17126],{"type":420,"value":8436},{"type":415,"tag":532,"props":17128,"children":17129},{"style":551},[17130],{"type":420,"value":432},{"type":415,"tag":532,"props":17132,"children":17133},{"style":545},[17134],{"type":420,"value":4299},{"type":415,"tag":532,"props":17136,"children":17137},{"style":551},[17138],{"type":420,"value":563},{"type":415,"tag":532,"props":17140,"children":17141},{"class":534,"line":6250},[17142],{"type":415,"tag":532,"props":17143,"children":17144},{"emptyLinePlaceholder":621},[17145],{"type":420,"value":624},{"type":415,"tag":532,"props":17147,"children":17148},{"class":534,"line":6258},[17149,17153,17157,17161,17165,17169,17173,17177,17181,17185],{"type":415,"tag":532,"props":17150,"children":17151},{"style":551},[17152],{"type":420,"value":9142},{"type":415,"tag":532,"props":17154,"children":17155},{"style":545},[17156],{"type":420,"value":12719},{"type":415,"tag":532,"props":17158,"children":17159},{"style":551},[17160],{"type":420,"value":432},{"type":415,"tag":532,"props":17162,"children":17163},{"style":656},[17164],{"type":420,"value":12728},{"type":415,"tag":532,"props":17166,"children":17167},{"style":545},[17168],{"type":420,"value":664},{"type":415,"tag":532,"props":17170,"children":17171},{"style":551},[17172],{"type":420,"value":801},{"type":415,"tag":532,"props":17174,"children":17175},{"style":804},[17176],{"type":420,"value":9160},{"type":415,"tag":532,"props":17178,"children":17179},{"style":551},[17180],{"type":420,"value":801},{"type":415,"tag":532,"props":17182,"children":17183},{"style":551},[17184],{"type":420,"value":1099},{"type":415,"tag":532,"props":17186,"children":17187},{"style":551},[17188],{"type":420,"value":11759},{"type":415,"tag":532,"props":17190,"children":17191},{"class":534,"line":6266},[17192,17196,17200,17204,17208,17212],{"type":415,"tag":532,"props":17193,"children":17194},{"style":3532},[17195],{"type":420,"value":12760},{"type":415,"tag":532,"props":17197,"children":17198},{"style":551},[17199],{"type":420,"value":1290},{"type":415,"tag":532,"props":17201,"children":17202},{"style":545},[17203],{"type":420,"value":8377},{"type":415,"tag":532,"props":17205,"children":17206},{"style":551},[17207],{"type":420,"value":432},{"type":415,"tag":532,"props":17209,"children":17210},{"style":545},[17211],{"type":420,"value":4326},{"type":415,"tag":532,"props":17213,"children":17214},{"style":551},[17215],{"type":420,"value":7400},{"type":415,"tag":532,"props":17217,"children":17218},{"class":534,"line":6274},[17219,17223,17227,17231,17235,17239,17243,17247],{"type":415,"tag":532,"props":17220,"children":17221},{"style":3532},[17222],{"type":420,"value":12788},{"type":415,"tag":532,"props":17224,"children":17225},{"style":551},[17226],{"type":420,"value":1290},{"type":415,"tag":532,"props":17228,"children":17229},{"style":545},[17230],{"type":420,"value":12719},{"type":415,"tag":532,"props":17232,"children":17233},{"style":551},[17234],{"type":420,"value":432},{"type":415,"tag":532,"props":17236,"children":17237},{"style":545},[17238],{"type":420,"value":12805},{"type":415,"tag":532,"props":17240,"children":17241},{"style":551},[17242],{"type":420,"value":432},{"type":415,"tag":532,"props":17244,"children":17245},{"style":545},[17246],{"type":420,"value":9233},{"type":415,"tag":532,"props":17248,"children":17249},{"style":551},[17250],{"type":420,"value":7400},{"type":415,"tag":532,"props":17252,"children":17253},{"class":534,"line":6283},[17254,17258,17262,17266,17270,17274],{"type":415,"tag":532,"props":17255,"children":17256},{"style":3532},[17257],{"type":420,"value":12825},{"type":415,"tag":532,"props":17259,"children":17260},{"style":551},[17261],{"type":420,"value":1290},{"type":415,"tag":532,"props":17263,"children":17264},{"style":545},[17265],{"type":420,"value":12674},{"type":415,"tag":532,"props":17267,"children":17268},{"style":551},[17269],{"type":420,"value":432},{"type":415,"tag":532,"props":17271,"children":17272},{"style":545},[17273],{"type":420,"value":9160},{"type":415,"tag":532,"props":17275,"children":17276},{"style":551},[17277],{"type":420,"value":7400},{"type":415,"tag":532,"props":17279,"children":17280},{"class":534,"line":6292},[17281,17285,17289,17293,17297,17301,17305,17309,17313,17317,17321],{"type":415,"tag":532,"props":17282,"children":17283},{"style":3532},[17284],{"type":420,"value":12853},{"type":415,"tag":532,"props":17286,"children":17287},{"style":551},[17288],{"type":420,"value":1290},{"type":415,"tag":532,"props":17290,"children":17291},{"style":545},[17292],{"type":420,"value":12474},{"type":415,"tag":532,"props":17294,"children":17295},{"style":551},[17296],{"type":420,"value":432},{"type":415,"tag":532,"props":17298,"children":17299},{"style":656},[17300],{"type":420,"value":12483},{"type":415,"tag":532,"props":17302,"children":17303},{"style":551},[17304],{"type":420,"value":12488},{"type":415,"tag":532,"props":17306,"children":17307},{"style":804},[17308],{"type":420,"value":8743},{"type":415,"tag":532,"props":17310,"children":17311},{"style":551},[17312],{"type":420,"value":4493},{"type":415,"tag":532,"props":17314,"children":17315},{"style":545},[17316],{"type":420,"value":4299},{"type":415,"tag":532,"props":17318,"children":17319},{"style":551},[17320],{"type":420,"value":12890},{"type":415,"tag":532,"props":17322,"children":17323},{"style":551},[17324],{"type":420,"value":7400},{"type":415,"tag":532,"props":17326,"children":17327},{"class":534,"line":6392},[17328,17332,17336],{"type":415,"tag":532,"props":17329,"children":17330},{"style":551},[17331],{"type":420,"value":4864},{"type":415,"tag":532,"props":17333,"children":17334},{"style":545},[17335],{"type":420,"value":1349},{"type":415,"tag":532,"props":17337,"children":17338},{"style":551},[17339],{"type":420,"value":563},{"type":415,"tag":532,"props":17341,"children":17342},{"class":534,"line":6400},[17343],{"type":415,"tag":532,"props":17344,"children":17345},{"emptyLinePlaceholder":621},[17346],{"type":420,"value":624},{"type":415,"tag":532,"props":17348,"children":17349},{"class":534,"line":6409},[17350,17354,17358,17362,17366,17370,17374,17378,17382,17386],{"type":415,"tag":532,"props":17351,"children":17352},{"style":551},[17353],{"type":420,"value":9142},{"type":415,"tag":532,"props":17355,"children":17356},{"style":545},[17357],{"type":420,"value":11724},{"type":415,"tag":532,"props":17359,"children":17360},{"style":551},[17361],{"type":420,"value":432},{"type":415,"tag":532,"props":17363,"children":17364},{"style":656},[17365],{"type":420,"value":13483},{"type":415,"tag":532,"props":17367,"children":17368},{"style":545},[17369],{"type":420,"value":664},{"type":415,"tag":532,"props":17371,"children":17372},{"style":551},[17373],{"type":420,"value":801},{"type":415,"tag":532,"props":17375,"children":17376},{"style":804},[17377],{"type":420,"value":4356},{"type":415,"tag":532,"props":17379,"children":17380},{"style":551},[17381],{"type":420,"value":801},{"type":415,"tag":532,"props":17383,"children":17384},{"style":551},[17385],{"type":420,"value":1099},{"type":415,"tag":532,"props":17387,"children":17388},{"style":551},[17389],{"type":420,"value":11759},{"type":415,"tag":532,"props":17391,"children":17392},{"class":534,"line":6457},[17393,17397,17401,17405,17409,17413],{"type":415,"tag":532,"props":17394,"children":17395},{"style":3532},[17396],{"type":420,"value":13305},{"type":415,"tag":532,"props":17398,"children":17399},{"style":551},[17400],{"type":420,"value":1290},{"type":415,"tag":532,"props":17402,"children":17403},{"style":545},[17404],{"type":420,"value":7695},{"type":415,"tag":532,"props":17406,"children":17407},{"style":551},[17408],{"type":420,"value":432},{"type":415,"tag":532,"props":17410,"children":17411},{"style":545},[17412],{"type":420,"value":3535},{"type":415,"tag":532,"props":17414,"children":17415},{"style":551},[17416],{"type":420,"value":7400},{"type":415,"tag":532,"props":17418,"children":17419},{"class":534,"line":6465},[17420,17424,17428,17432,17436,17440],{"type":415,"tag":532,"props":17421,"children":17422},{"style":3532},[17423],{"type":420,"value":13542},{"type":415,"tag":532,"props":17425,"children":17426},{"style":551},[17427],{"type":420,"value":1290},{"type":415,"tag":532,"props":17429,"children":17430},{"style":551},[17431],{"type":420,"value":4041},{"type":415,"tag":532,"props":17433,"children":17434},{"style":804},[17435],{"type":420,"value":13346},{"type":415,"tag":532,"props":17437,"children":17438},{"style":551},[17439],{"type":420,"value":801},{"type":415,"tag":532,"props":17441,"children":17442},{"style":551},[17443],{"type":420,"value":7400},{"type":415,"tag":532,"props":17445,"children":17446},{"class":534,"line":6474},[17447,17451,17455,17459,17463,17467],{"type":415,"tag":532,"props":17448,"children":17449},{"style":3532},[17450],{"type":420,"value":13570},{"type":415,"tag":532,"props":17452,"children":17453},{"style":551},[17454],{"type":420,"value":1290},{"type":415,"tag":532,"props":17456,"children":17457},{"style":545},[17458],{"type":420,"value":8436},{"type":415,"tag":532,"props":17460,"children":17461},{"style":551},[17462],{"type":420,"value":432},{"type":415,"tag":532,"props":17464,"children":17465},{"style":545},[17466],{"type":420,"value":4356},{"type":415,"tag":532,"props":17468,"children":17469},{"style":551},[17470],{"type":420,"value":7400},{"type":415,"tag":532,"props":17472,"children":17473},{"class":534,"line":6498},[17474,17478,17482],{"type":415,"tag":532,"props":17475,"children":17476},{"style":551},[17477],{"type":420,"value":4864},{"type":415,"tag":532,"props":17479,"children":17480},{"style":545},[17481],{"type":420,"value":1349},{"type":415,"tag":532,"props":17483,"children":17484},{"style":551},[17485],{"type":420,"value":563},{"type":415,"tag":532,"props":17487,"children":17488},{"class":534,"line":6522},[17489],{"type":415,"tag":532,"props":17490,"children":17491},{"emptyLinePlaceholder":621},[17492],{"type":420,"value":624},{"type":415,"tag":532,"props":17494,"children":17495},{"class":534,"line":6546},[17496,17500,17504,17508,17512,17516,17520,17524,17528,17532],{"type":415,"tag":532,"props":17497,"children":17498},{"style":551},[17499],{"type":420,"value":9142},{"type":415,"tag":532,"props":17501,"children":17502},{"style":545},[17503],{"type":420,"value":11724},{"type":415,"tag":532,"props":17505,"children":17506},{"style":551},[17507],{"type":420,"value":432},{"type":415,"tag":532,"props":17509,"children":17510},{"style":656},[17511],{"type":420,"value":13483},{"type":415,"tag":532,"props":17513,"children":17514},{"style":545},[17515],{"type":420,"value":664},{"type":415,"tag":532,"props":17517,"children":17518},{"style":551},[17519],{"type":420,"value":801},{"type":415,"tag":532,"props":17521,"children":17522},{"style":804},[17523],{"type":420,"value":4299},{"type":415,"tag":532,"props":17525,"children":17526},{"style":551},[17527],{"type":420,"value":801},{"type":415,"tag":532,"props":17529,"children":17530},{"style":551},[17531],{"type":420,"value":1099},{"type":415,"tag":532,"props":17533,"children":17534},{"style":551},[17535],{"type":420,"value":11759},{"type":415,"tag":532,"props":17537,"children":17538},{"class":534,"line":6554},[17539,17543,17547,17551,17555,17559],{"type":415,"tag":532,"props":17540,"children":17541},{"style":3532},[17542],{"type":420,"value":13305},{"type":415,"tag":532,"props":17544,"children":17545},{"style":551},[17546],{"type":420,"value":1290},{"type":415,"tag":532,"props":17548,"children":17549},{"style":545},[17550],{"type":420,"value":7695},{"type":415,"tag":532,"props":17552,"children":17553},{"style":551},[17554],{"type":420,"value":432},{"type":415,"tag":532,"props":17556,"children":17557},{"style":545},[17558],{"type":420,"value":3535},{"type":415,"tag":532,"props":17560,"children":17561},{"style":551},[17562],{"type":420,"value":7400},{"type":415,"tag":532,"props":17564,"children":17565},{"class":534,"line":6563},[17566,17570,17574,17578,17582,17586],{"type":415,"tag":532,"props":17567,"children":17568},{"style":3532},[17569],{"type":420,"value":13542},{"type":415,"tag":532,"props":17571,"children":17572},{"style":551},[17573],{"type":420,"value":1290},{"type":415,"tag":532,"props":17575,"children":17576},{"style":551},[17577],{"type":420,"value":4041},{"type":415,"tag":532,"props":17579,"children":17580},{"style":804},[17581],{"type":420,"value":13702},{"type":415,"tag":532,"props":17583,"children":17584},{"style":551},[17585],{"type":420,"value":801},{"type":415,"tag":532,"props":17587,"children":17588},{"style":551},[17589],{"type":420,"value":7400},{"type":415,"tag":532,"props":17591,"children":17592},{"class":534,"line":6571},[17593,17597,17601,17605,17609,17613],{"type":415,"tag":532,"props":17594,"children":17595},{"style":3532},[17596],{"type":420,"value":13570},{"type":415,"tag":532,"props":17598,"children":17599},{"style":551},[17600],{"type":420,"value":1290},{"type":415,"tag":532,"props":17602,"children":17603},{"style":545},[17604],{"type":420,"value":8436},{"type":415,"tag":532,"props":17606,"children":17607},{"style":551},[17608],{"type":420,"value":432},{"type":415,"tag":532,"props":17610,"children":17611},{"style":545},[17612],{"type":420,"value":4299},{"type":415,"tag":532,"props":17614,"children":17615},{"style":551},[17616],{"type":420,"value":7400},{"type":415,"tag":532,"props":17618,"children":17619},{"class":534,"line":6639},[17620,17624,17628],{"type":415,"tag":532,"props":17621,"children":17622},{"style":551},[17623],{"type":420,"value":4864},{"type":415,"tag":532,"props":17625,"children":17626},{"style":545},[17627],{"type":420,"value":1349},{"type":415,"tag":532,"props":17629,"children":17630},{"style":551},[17631],{"type":420,"value":563},{"type":415,"tag":532,"props":17633,"children":17634},{"class":534,"line":6655},[17635],{"type":415,"tag":532,"props":17636,"children":17637},{"emptyLinePlaceholder":621},[17638],{"type":420,"value":624},{"type":415,"tag":532,"props":17640,"children":17641},{"class":534,"line":6663},[17642,17646,17650,17654,17658,17662,17666,17670,17674,17678],{"type":415,"tag":532,"props":17643,"children":17644},{"style":551},[17645],{"type":420,"value":9142},{"type":415,"tag":532,"props":17647,"children":17648},{"style":545},[17649],{"type":420,"value":11724},{"type":415,"tag":532,"props":17651,"children":17652},{"style":551},[17653],{"type":420,"value":432},{"type":415,"tag":532,"props":17655,"children":17656},{"style":656},[17657],{"type":420,"value":13483},{"type":415,"tag":532,"props":17659,"children":17660},{"style":545},[17661],{"type":420,"value":664},{"type":415,"tag":532,"props":17663,"children":17664},{"style":551},[17665],{"type":420,"value":801},{"type":415,"tag":532,"props":17667,"children":17668},{"style":804},[17669],{"type":420,"value":13791},{"type":415,"tag":532,"props":17671,"children":17672},{"style":551},[17673],{"type":420,"value":801},{"type":415,"tag":532,"props":17675,"children":17676},{"style":551},[17677],{"type":420,"value":1099},{"type":415,"tag":532,"props":17679,"children":17680},{"style":551},[17681],{"type":420,"value":11759},{"type":415,"tag":532,"props":17683,"children":17684},{"class":534,"line":6672},[17685,17689,17693,17697,17701,17705],{"type":415,"tag":532,"props":17686,"children":17687},{"style":3532},[17688],{"type":420,"value":13305},{"type":415,"tag":532,"props":17690,"children":17691},{"style":551},[17692],{"type":420,"value":1290},{"type":415,"tag":532,"props":17694,"children":17695},{"style":545},[17696],{"type":420,"value":7695},{"type":415,"tag":532,"props":17698,"children":17699},{"style":551},[17700],{"type":420,"value":432},{"type":415,"tag":532,"props":17702,"children":17703},{"style":545},[17704],{"type":420,"value":3535},{"type":415,"tag":532,"props":17706,"children":17707},{"style":551},[17708],{"type":420,"value":7400},{"type":415,"tag":532,"props":17710,"children":17712},{"class":534,"line":17711},55,[17713,17717,17721,17725,17729,17733],{"type":415,"tag":532,"props":17714,"children":17715},{"style":3532},[17716],{"type":420,"value":13542},{"type":415,"tag":532,"props":17718,"children":17719},{"style":551},[17720],{"type":420,"value":1290},{"type":415,"tag":532,"props":17722,"children":17723},{"style":551},[17724],{"type":420,"value":4041},{"type":415,"tag":532,"props":17726,"children":17727},{"style":804},[17728],{"type":420,"value":13850},{"type":415,"tag":532,"props":17730,"children":17731},{"style":551},[17732],{"type":420,"value":801},{"type":415,"tag":532,"props":17734,"children":17735},{"style":551},[17736],{"type":420,"value":7400},{"type":415,"tag":532,"props":17738,"children":17740},{"class":534,"line":17739},56,[17741,17745,17749,17753,17757,17761],{"type":415,"tag":532,"props":17742,"children":17743},{"style":3532},[17744],{"type":420,"value":13570},{"type":415,"tag":532,"props":17746,"children":17747},{"style":551},[17748],{"type":420,"value":1290},{"type":415,"tag":532,"props":17750,"children":17751},{"style":545},[17752],{"type":420,"value":8903},{"type":415,"tag":532,"props":17754,"children":17755},{"style":551},[17756],{"type":420,"value":432},{"type":415,"tag":532,"props":17758,"children":17759},{"style":545},[17760],{"type":420,"value":12215},{"type":415,"tag":532,"props":17762,"children":17763},{"style":551},[17764],{"type":420,"value":7400},{"type":415,"tag":532,"props":17766,"children":17768},{"class":534,"line":17767},57,[17769,17773,17777],{"type":415,"tag":532,"props":17770,"children":17771},{"style":551},[17772],{"type":420,"value":4864},{"type":415,"tag":532,"props":17774,"children":17775},{"style":545},[17776],{"type":420,"value":1349},{"type":415,"tag":532,"props":17778,"children":17779},{"style":551},[17780],{"type":420,"value":563},{"type":415,"tag":532,"props":17782,"children":17784},{"class":534,"line":17783},58,[17785],{"type":415,"tag":532,"props":17786,"children":17787},{"emptyLinePlaceholder":621},[17788],{"type":420,"value":624},{"type":415,"tag":532,"props":17790,"children":17792},{"class":534,"line":17791},59,[17793,17797,17801,17805,17809,17813,17817,17821,17825,17829],{"type":415,"tag":532,"props":17794,"children":17795},{"style":551},[17796],{"type":420,"value":9142},{"type":415,"tag":532,"props":17798,"children":17799},{"style":545},[17800],{"type":420,"value":11724},{"type":415,"tag":532,"props":17802,"children":17803},{"style":551},[17804],{"type":420,"value":432},{"type":415,"tag":532,"props":17806,"children":17807},{"style":656},[17808],{"type":420,"value":13483},{"type":415,"tag":532,"props":17810,"children":17811},{"style":545},[17812],{"type":420,"value":664},{"type":415,"tag":532,"props":17814,"children":17815},{"style":551},[17816],{"type":420,"value":801},{"type":415,"tag":532,"props":17818,"children":17819},{"style":804},[17820],{"type":420,"value":15149},{"type":415,"tag":532,"props":17822,"children":17823},{"style":551},[17824],{"type":420,"value":801},{"type":415,"tag":532,"props":17826,"children":17827},{"style":551},[17828],{"type":420,"value":1099},{"type":415,"tag":532,"props":17830,"children":17831},{"style":551},[17832],{"type":420,"value":11759},{"type":415,"tag":532,"props":17834,"children":17836},{"class":534,"line":17835},60,[17837,17841,17845,17849,17853,17857],{"type":415,"tag":532,"props":17838,"children":17839},{"style":3532},[17840],{"type":420,"value":13305},{"type":415,"tag":532,"props":17842,"children":17843},{"style":551},[17844],{"type":420,"value":1290},{"type":415,"tag":532,"props":17846,"children":17847},{"style":545},[17848],{"type":420,"value":7695},{"type":415,"tag":532,"props":17850,"children":17851},{"style":551},[17852],{"type":420,"value":432},{"type":415,"tag":532,"props":17854,"children":17855},{"style":545},[17856],{"type":420,"value":3535},{"type":415,"tag":532,"props":17858,"children":17859},{"style":551},[17860],{"type":420,"value":7400},{"type":415,"tag":532,"props":17862,"children":17864},{"class":534,"line":17863},61,[17865,17869,17873,17877,17881,17885],{"type":415,"tag":532,"props":17866,"children":17867},{"style":3532},[17868],{"type":420,"value":13542},{"type":415,"tag":532,"props":17870,"children":17871},{"style":551},[17872],{"type":420,"value":1290},{"type":415,"tag":532,"props":17874,"children":17875},{"style":551},[17876],{"type":420,"value":4041},{"type":415,"tag":532,"props":17878,"children":17879},{"style":804},[17880],{"type":420,"value":15068},{"type":415,"tag":532,"props":17882,"children":17883},{"style":551},[17884],{"type":420,"value":801},{"type":415,"tag":532,"props":17886,"children":17887},{"style":551},[17888],{"type":420,"value":7400},{"type":415,"tag":532,"props":17890,"children":17892},{"class":534,"line":17891},62,[17893,17897,17901,17905,17909,17913,17917,17921,17925,17929,17933],{"type":415,"tag":532,"props":17894,"children":17895},{"style":3532},[17896],{"type":420,"value":13570},{"type":415,"tag":532,"props":17898,"children":17899},{"style":551},[17900],{"type":420,"value":1290},{"type":415,"tag":532,"props":17902,"children":17903},{"style":545},[17904],{"type":420,"value":7206},{"type":415,"tag":532,"props":17906,"children":17907},{"style":551},[17908],{"type":420,"value":432},{"type":415,"tag":532,"props":17910,"children":17911},{"style":656},[17912],{"type":420,"value":15239},{"type":415,"tag":532,"props":17914,"children":17915},{"style":545},[17916],{"type":420,"value":664},{"type":415,"tag":532,"props":17918,"children":17919},{"style":551},[17920],{"type":420,"value":801},{"type":415,"tag":532,"props":17922,"children":17923},{"style":804},[17924],{"type":420,"value":15252},{"type":415,"tag":532,"props":17926,"children":17927},{"style":551},[17928],{"type":420,"value":801},{"type":415,"tag":532,"props":17930,"children":17931},{"style":545},[17932],{"type":420,"value":1349},{"type":415,"tag":532,"props":17934,"children":17935},{"style":551},[17936],{"type":420,"value":7400},{"type":415,"tag":532,"props":17938,"children":17940},{"class":534,"line":17939},63,[17941,17945,17949],{"type":415,"tag":532,"props":17942,"children":17943},{"style":551},[17944],{"type":420,"value":4864},{"type":415,"tag":532,"props":17946,"children":17947},{"style":545},[17948],{"type":420,"value":1349},{"type":415,"tag":532,"props":17950,"children":17951},{"style":551},[17952],{"type":420,"value":563},{"type":415,"tag":532,"props":17954,"children":17956},{"class":534,"line":17955},64,[17957],{"type":415,"tag":532,"props":17958,"children":17959},{"emptyLinePlaceholder":621},[17960],{"type":420,"value":624},{"type":415,"tag":532,"props":17962,"children":17964},{"class":534,"line":17963},65,[17965,17969,17973,17977,17981,17985,17989,17993,17997,18001,18005,18009,18013,18017],{"type":415,"tag":532,"props":17966,"children":17967},{"style":954},[17968],{"type":420,"value":11706},{"type":415,"tag":532,"props":17970,"children":17971},{"style":545},[17972],{"type":420,"value":15351},{"type":415,"tag":532,"props":17974,"children":17975},{"style":551},[17976],{"type":420,"value":1134},{"type":415,"tag":532,"props":17978,"children":17979},{"style":656},[17980],{"type":420,"value":15307},{"type":415,"tag":532,"props":17982,"children":17983},{"style":545},[17984],{"type":420,"value":664},{"type":415,"tag":532,"props":17986,"children":17987},{"style":551},[17988],{"type":420,"value":801},{"type":415,"tag":532,"props":17990,"children":17991},{"style":804},[17992],{"type":420,"value":15372},{"type":415,"tag":532,"props":17994,"children":17995},{"style":551},[17996],{"type":420,"value":801},{"type":415,"tag":532,"props":17998,"children":17999},{"style":551},[18000],{"type":420,"value":1099},{"type":415,"tag":532,"props":18002,"children":18003},{"style":551},[18004],{"type":420,"value":4041},{"type":415,"tag":532,"props":18006,"children":18007},{"style":804},[18008],{"type":420,"value":15389},{"type":415,"tag":532,"props":18010,"children":18011},{"style":551},[18012],{"type":420,"value":801},{"type":415,"tag":532,"props":18014,"children":18015},{"style":545},[18016],{"type":420,"value":1349},{"type":415,"tag":532,"props":18018,"children":18019},{"style":551},[18020],{"type":420,"value":563},{"type":415,"tag":532,"props":18022,"children":18024},{"class":534,"line":18023},66,[18025,18029,18033,18037,18041,18045,18049,18053,18057,18061],{"type":415,"tag":532,"props":18026,"children":18027},{"style":551},[18028],{"type":420,"value":9142},{"type":415,"tag":532,"props":18030,"children":18031},{"style":545},[18032],{"type":420,"value":11724},{"type":415,"tag":532,"props":18034,"children":18035},{"style":551},[18036],{"type":420,"value":432},{"type":415,"tag":532,"props":18038,"children":18039},{"style":656},[18040],{"type":420,"value":15421},{"type":415,"tag":532,"props":18042,"children":18043},{"style":545},[18044],{"type":420,"value":664},{"type":415,"tag":532,"props":18046,"children":18047},{"style":551},[18048],{"type":420,"value":801},{"type":415,"tag":532,"props":18050,"children":18051},{"style":804},[18052],{"type":420,"value":15434},{"type":415,"tag":532,"props":18054,"children":18055},{"style":551},[18056],{"type":420,"value":801},{"type":415,"tag":532,"props":18058,"children":18059},{"style":551},[18060],{"type":420,"value":1099},{"type":415,"tag":532,"props":18062,"children":18063},{"style":551},[18064],{"type":420,"value":11759},{"type":415,"tag":532,"props":18066,"children":18068},{"class":534,"line":18067},67,[18069,18073,18077,18081,18085,18089],{"type":415,"tag":532,"props":18070,"children":18071},{"style":3532},[18072],{"type":420,"value":13305},{"type":415,"tag":532,"props":18074,"children":18075},{"style":551},[18076],{"type":420,"value":1290},{"type":415,"tag":532,"props":18078,"children":18079},{"style":545},[18080],{"type":420,"value":7695},{"type":415,"tag":532,"props":18082,"children":18083},{"style":551},[18084],{"type":420,"value":432},{"type":415,"tag":532,"props":18086,"children":18087},{"style":545},[18088],{"type":420,"value":3535},{"type":415,"tag":532,"props":18090,"children":18091},{"style":551},[18092],{"type":420,"value":7400},{"type":415,"tag":532,"props":18094,"children":18096},{"class":534,"line":18095},68,[18097,18101,18105,18109,18113,18117],{"type":415,"tag":532,"props":18098,"children":18099},{"style":3532},[18100],{"type":420,"value":15481},{"type":415,"tag":532,"props":18102,"children":18103},{"style":551},[18104],{"type":420,"value":1290},{"type":415,"tag":532,"props":18106,"children":18107},{"style":551},[18108],{"type":420,"value":4041},{"type":415,"tag":532,"props":18110,"children":18111},{"style":804},[18112],{"type":420,"value":11042},{"type":415,"tag":532,"props":18114,"children":18115},{"style":551},[18116],{"type":420,"value":801},{"type":415,"tag":532,"props":18118,"children":18119},{"style":551},[18120],{"type":420,"value":7400},{"type":415,"tag":532,"props":18122,"children":18124},{"class":534,"line":18123},69,[18125,18129,18133,18137,18141,18145],{"type":415,"tag":532,"props":18126,"children":18127},{"style":3532},[18128],{"type":420,"value":15509},{"type":415,"tag":532,"props":18130,"children":18131},{"style":551},[18132],{"type":420,"value":1290},{"type":415,"tag":532,"props":18134,"children":18135},{"style":551},[18136],{"type":420,"value":4041},{"type":415,"tag":532,"props":18138,"children":18139},{"style":804},[18140],{"type":420,"value":15522},{"type":415,"tag":532,"props":18142,"children":18143},{"style":551},[18144],{"type":420,"value":801},{"type":415,"tag":532,"props":18146,"children":18147},{"style":551},[18148],{"type":420,"value":7400},{"type":415,"tag":532,"props":18150,"children":18152},{"class":534,"line":18151},70,[18153,18157,18161,18165],{"type":415,"tag":532,"props":18154,"children":18155},{"style":3532},[18156],{"type":420,"value":15538},{"type":415,"tag":532,"props":18158,"children":18159},{"style":551},[18160],{"type":420,"value":1290},{"type":415,"tag":532,"props":18162,"children":18163},{"style":545},[18164],{"type":420,"value":15547},{"type":415,"tag":532,"props":18166,"children":18167},{"style":551},[18168],{"type":420,"value":7400},{"type":415,"tag":532,"props":18170,"children":18172},{"class":534,"line":18171},71,[18173,18177,18181,18185,18189,18193],{"type":415,"tag":532,"props":18174,"children":18175},{"style":3532},[18176],{"type":420,"value":15559},{"type":415,"tag":532,"props":18178,"children":18179},{"style":551},[18180],{"type":420,"value":1290},{"type":415,"tag":532,"props":18182,"children":18183},{"style":551},[18184],{"type":420,"value":4041},{"type":415,"tag":532,"props":18186,"children":18187},{"style":804},[18188],{"type":420,"value":10108},{"type":415,"tag":532,"props":18190,"children":18191},{"style":551},[18192],{"type":420,"value":801},{"type":415,"tag":532,"props":18194,"children":18195},{"style":551},[18196],{"type":420,"value":7400},{"type":415,"tag":532,"props":18198,"children":18200},{"class":534,"line":18199},72,[18201,18205,18209,18213,18217,18221],{"type":415,"tag":532,"props":18202,"children":18203},{"style":3532},[18204],{"type":420,"value":15587},{"type":415,"tag":532,"props":18206,"children":18207},{"style":551},[18208],{"type":420,"value":1290},{"type":415,"tag":532,"props":18210,"children":18211},{"style":551},[18212],{"type":420,"value":4041},{"type":415,"tag":532,"props":18214,"children":18215},{"style":804},[18216],{"type":420,"value":15600},{"type":415,"tag":532,"props":18218,"children":18219},{"style":551},[18220],{"type":420,"value":801},{"type":415,"tag":532,"props":18222,"children":18223},{"style":551},[18224],{"type":420,"value":7400},{"type":415,"tag":532,"props":18226,"children":18228},{"class":534,"line":18227},73,[18229,18233,18237,18241,18245,18249],{"type":415,"tag":532,"props":18230,"children":18231},{"style":3532},[18232],{"type":420,"value":15616},{"type":415,"tag":532,"props":18234,"children":18235},{"style":551},[18236],{"type":420,"value":1290},{"type":415,"tag":532,"props":18238,"children":18239},{"style":551},[18240],{"type":420,"value":4041},{"type":415,"tag":532,"props":18242,"children":18243},{"style":804},[18244],{"type":420,"value":15629},{"type":415,"tag":532,"props":18246,"children":18247},{"style":551},[18248],{"type":420,"value":801},{"type":415,"tag":532,"props":18250,"children":18251},{"style":551},[18252],{"type":420,"value":7400},{"type":415,"tag":532,"props":18254,"children":18256},{"class":534,"line":18255},74,[18257,18261,18265,18269],{"type":415,"tag":532,"props":18258,"children":18259},{"style":3532},[18260],{"type":420,"value":15645},{"type":415,"tag":532,"props":18262,"children":18263},{"style":551},[18264],{"type":420,"value":1290},{"type":415,"tag":532,"props":18266,"children":18267},{"style":1938},[18268],{"type":420,"value":1941},{"type":415,"tag":532,"props":18270,"children":18271},{"style":551},[18272],{"type":420,"value":7400},{"type":415,"tag":532,"props":18274,"children":18276},{"class":534,"line":18275},75,[18277,18281,18285],{"type":415,"tag":532,"props":18278,"children":18279},{"style":551},[18280],{"type":420,"value":4864},{"type":415,"tag":532,"props":18282,"children":18283},{"style":545},[18284],{"type":420,"value":1349},{"type":415,"tag":532,"props":18286,"children":18287},{"style":551},[18288],{"type":420,"value":563},{"type":415,"tag":416,"props":18290,"children":18291},{},[18292,18293,18299],{"type":420,"value":10925},{"type":415,"tag":423,"props":18294,"children":18297},{"href":18295,"rel":18296},"https://github.com/TechWatching/AzureOIDC",[427],[18298],{"type":420,"value":10935},{"type":420,"value":432},{"type":415,"tag":416,"props":18301,"children":18302},{},[18303],{"type":420,"value":18304},"I hope you enjoyed this article. Please feel free to share your thoughts in the comments, ask questions, or make suggestions. Keep learning.",{"type":415,"tag":3470,"props":18306,"children":18307},{},[18308],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":18310},[18311,18317,18318,18327,18328],{"id":10989,"depth":566,"text":10992,"children":18312},[18313,18314,18315,18316],{"id":11014,"depth":583,"text":11017},{"id":11074,"depth":583,"text":11077},{"id":11157,"depth":583,"text":11160},{"id":11258,"depth":583,"text":11261},{"id":11272,"depth":566,"text":11275},{"id":11338,"depth":566,"text":11341,"children":18319},[18320,18321,18322,18324,18325,18326],{"id":11344,"depth":583,"text":11347},{"id":3960,"depth":583,"text":3963},{"id":11971,"depth":583,"text":18323},"Create the identity in Azure Active Directory for the GitHub Actions workflow",{"id":12597,"depth":583,"text":12600},{"id":13212,"depth":583,"text":13215},{"id":13920,"depth":583,"text":13923},{"id":15735,"depth":566,"text":15738},{"id":10889,"depth":566,"text":10892,"children":18329},[18330,18331,18332,18333],{"id":15961,"depth":583,"text":15964},{"id":15977,"depth":583,"text":15980},{"id":16011,"depth":583,"text":16014},{"id":16108,"depth":583,"text":16111},"content:1.posts:53.azure-ready-github-repository.md","1.posts/53.azure-ready-github-repository.md",{"_path":142,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":141,"description":18337,"lead":18338,"date":18339,"image":18340,"badge":18342,"tags":18343,"body":18344,"_type":3483,"_id":22678,"_source":3485,"_file":22679,"_extension":3487},"Today is a great time to be a developer:","Pushing an ASP.NET Core API to Azure using .NET from provisioning to deployment","2022-12-18T00:00:00.000Z",{"src":18341},"/images/trees_1.jpg",{"label":266},[239,365,312,368,315,266,228],{"type":412,"children":18345,"toc":22649},[18346,18350,18373,18378,18383,18388,18394,18399,18404,18409,18415,18420,18430,18435,18456,18465,18470,18479,18484,18492,18501,18506,18512,18518,18523,18541,18546,18569,18575,18580,18589,18594,18617,18626,18631,18649,18661,18680,18689,18695,18700,18709,18714,18719,18735,18741,18747,18752,18761,18783,18791,18796,18802,18807,19021,19026,19178,19184,19206,19332,19338,19367,19570,19576,19596,19910,19927,19956,20021,20040,20046,20052,20072,20081,20089,20101,20107,20112,20137,20775,20780,20788,20794,20799,20812,20826,20944,20961,20974,21256,21269,21275,21287,21563,21569,21582,21595,21803,21808,22424,22441,22446,22451,22457,22462,22471,22484,22493,22501,22506,22515,22520,22529,22535,22541,22546,22578,22592,22598,22603,22624,22629,22634,22640,22645],{"type":415,"tag":416,"props":18347,"children":18348},{},[18349],{"type":420,"value":18337},{"type":415,"tag":508,"props":18351,"children":18352},{},[18353,18358,18363,18368],{"type":415,"tag":512,"props":18354,"children":18355},{},[18356],{"type":420,"value":18357},"there are plenty of languages and frameworks to choose from to build an application",{"type":415,"tag":512,"props":18359,"children":18360},{},[18361],{"type":420,"value":18362},"there are very powerful IDEs and tools to help us write, analyze, refactor, test and debug code",{"type":415,"tag":512,"props":18364,"children":18365},{},[18366],{"type":420,"value":18367},"there are many nice CI/CD platforms that allow us to package and deploy our applications anywhere",{"type":415,"tag":512,"props":18369,"children":18370},{},[18371],{"type":420,"value":18372},"thanks to cloud platforms and infrastructure as code we can provision infrastructure on-demand in an automated way",{"type":415,"tag":416,"props":18374,"children":18375},{},[18376],{"type":420,"value":18377},"Yet, sometimes it seems quite complex and time-consuming to deploy an application in the cloud.",{"type":415,"tag":416,"props":18379,"children":18380},{},[18381],{"type":420,"value":18382},"As a .NET developer, do I really need to master YAML, and Domain Specific Languages like HCL to deploy a simple ASP.NET Core API in Azure? Should I forget about local debugging when developing CI/CD pipelines? Do I have to learn everything from scratch each time I use another CI/CD platform?",{"type":415,"tag":416,"props":18384,"children":18385},{},[18386],{"type":420,"value":18387},"Thanks to Nuke and Pulumi, I don't think so and that is what we are going to talk about in this article.",{"type":415,"tag":482,"props":18389,"children":18391},{"id":18390},"the-scenario",[18392],{"type":420,"value":18393},"The scenario",{"type":415,"tag":416,"props":18395,"children":18396},{},[18397],{"type":420,"value":18398},"They are already lots of great articles about Pulumi or Nuke, so I won't spend time explaining what they are and why you should use them. Instead, I will show you how you can use them together with an example.",{"type":415,"tag":416,"props":18400,"children":18401},{},[18402],{"type":420,"value":18403},"My scenario is the following: I have a very basic ASP.NET Core API that I want to deploy to Azure App Service using a CI/CD pipeline.",{"type":415,"tag":416,"props":18405,"children":18406},{},[18407],{"type":420,"value":18408},"To do that, I want to use my existing .NET skills and code everything with the language and tools I know and love.",{"type":415,"tag":482,"props":18410,"children":18412},{"id":18411},"steps-of-the-cicd-pipeline",[18413],{"type":420,"value":18414},"Steps of the CI/CD pipeline",{"type":415,"tag":416,"props":18416,"children":18417},{},[18418],{"type":420,"value":18419},"There are often two main steps (or stages or whatever you call them) in a CI / CD pipeline: the packaging and the deployment.",{"type":415,"tag":416,"props":18421,"children":18422},{},[18423],{"type":415,"tag":3882,"props":18424,"children":18429},{"alt":18425,"className":18426,"src":18427,"width":18428},"Diagram with package and deploy steps.",[3886,3887],"/posts/images/pulumi_met_nuke_1.png",600,[],{"type":415,"tag":416,"props":18431,"children":18432},{},[18433],{"type":420,"value":18434},"To package a .NET application, we have to first restore the dependencies, then compile the application and publish it. So my Package step is composed of 3 steps.",{"type":415,"tag":434,"props":18436,"children":18437},{"icon":1382},[18438],{"type":415,"tag":416,"props":18439,"children":18440},{},[18441,18443,18454],{"type":420,"value":18442},"A ",{"type":415,"tag":423,"props":18444,"children":18447},{"href":18445,"rel":18446},"https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish#description",[427],[18448],{"type":415,"tag":468,"props":18449,"children":18451},{"className":18450},[],[18452],{"type":420,"value":18453},"dotnet publish",{"type":420,"value":18455}," does an implicit restore and build the application so only one step could be used but I like separating these steps for clarity. Moreover it is sometimes needed, for instance when you are restoring packages from private Nuget feeds.",{"type":415,"tag":416,"props":18457,"children":18458},{},[18459],{"type":415,"tag":3882,"props":18460,"children":18464},{"alt":18461,"className":18462,"src":18463,"width":6932},"Diagram with restore, compile, publish and deploy steps.",[3886,3887],"/posts/images/pulumi_met_nuke_2.png",[],{"type":415,"tag":416,"props":18466,"children":18467},{},[18468],{"type":420,"value":18469},"I said the application needed to be deployed to Azure App Service but I don't have an existing Azure App Service resource, and I don't want to manually create one. So I also need a step to deploy the infrastructure",{"type":415,"tag":416,"props":18471,"children":18472},{},[18473],{"type":415,"tag":3882,"props":18474,"children":18478},{"alt":18475,"className":18476,"src":18477,"width":6932},"Diagram with restore, compile, publish, deploy and provision infra steps.",[3886,3887],"/posts/images/pulumi_met_nuke_3.png",[],{"type":415,"tag":416,"props":18480,"children":18481},{},[18482],{"type":420,"value":18483},"It seems fine. I will just add another optional step at the beginning to clean the temporary files I could have created on previous builds.",{"type":415,"tag":434,"props":18485,"children":18486},{"icon":436},[18487],{"type":415,"tag":416,"props":18488,"children":18489},{},[18490],{"type":420,"value":18491},"If your pipeline runs on a hosted agent/runner (managed by the CI/CD platform you use), the Clean step might not be very useful but I intend to also run this pipeline locally.",{"type":415,"tag":416,"props":18493,"children":18494},{},[18495],{"type":415,"tag":3882,"props":18496,"children":18500},{"alt":18497,"className":18498,"src":18499},"Diagram with clean, restore, compile, publish, deploy and provision infra steps.",[3886,3887],"/posts/images/pulumi_met_nuke_4.png",[],{"type":415,"tag":416,"props":18502,"children":18503},{},[18504],{"type":420,"value":18505},"Now, that we know the different steps of our pipeline, let's get to the code.",{"type":415,"tag":482,"props":18507,"children":18509},{"id":18508},"getting-started-with-the-code",[18510],{"type":420,"value":18511},"Getting started with the code",{"type":415,"tag":3914,"props":18513,"children":18515},{"id":18514},"code-organization",[18516],{"type":420,"value":18517},"Code organization",{"type":415,"tag":416,"props":18519,"children":18520},{},[18521],{"type":420,"value":18522},"I put all the code in the same Git repository because:",{"type":415,"tag":508,"props":18524,"children":18525},{},[18526,18531,18536],{"type":415,"tag":512,"props":18527,"children":18528},{},[18529],{"type":420,"value":18530},"it makes sense as everything is linked",{"type":415,"tag":512,"props":18532,"children":18533},{},[18534],{"type":420,"value":18535},"it's easier to maintain (all the code in one place)",{"type":415,"tag":512,"props":18537,"children":18538},{},[18539],{"type":420,"value":18540},"it's easier to version (one tag on one commit in one repository)",{"type":415,"tag":416,"props":18542,"children":18543},{},[18544],{"type":420,"value":18545},"I chose to organize my repository with the following folders:",{"type":415,"tag":508,"props":18547,"children":18548},{},[18549,18554,18559,18564],{"type":415,"tag":512,"props":18550,"children":18551},{},[18552],{"type":420,"value":18553},"📁 src ➡️ for the application code of the API",{"type":415,"tag":512,"props":18555,"children":18556},{},[18557],{"type":420,"value":18558},"📁 infra ➡️ for the infrastructure code that provisions the App Service",{"type":415,"tag":512,"props":18560,"children":18561},{},[18562],{"type":420,"value":18563},"📁 build ➡️ for pipeline code that builds and deploys the application",{"type":415,"tag":512,"props":18565,"children":18566},{},[18567],{"type":420,"value":18568},"📁 artifacts ➡️ for the package created by the pipeline",{"type":415,"tag":3914,"props":18570,"children":18572},{"id":18571},"create-the-c-projects",[18573],{"type":420,"value":18574},"Create the C# projects",{"type":415,"tag":416,"props":18576,"children":18577},{},[18578],{"type":420,"value":18579},"To create the API project, we just use the default ASP.NET Core API template in .NET 7 that creates a simple Weather API.",{"type":415,"tag":416,"props":18581,"children":18582},{},[18583],{"type":415,"tag":3882,"props":18584,"children":18588},{"alt":18585,"className":18586,"src":18587},"IDE folder explorer of an ASP.NET Core API template.",[3886,3887],"/posts/images/pulumi_met_nuke_5.png",[],{"type":415,"tag":416,"props":18590,"children":18591},{},[18592],{"type":420,"value":18593},"I can initialize the infrastructure project using the Pulumi CLI new command with the azure C# template:",{"type":415,"tag":523,"props":18595,"children":18597},{"className":3984,"code":18596,"language":3986,"meta":401,"style":401},"pulumi new azure-csharp\n",[18598],{"type":415,"tag":468,"props":18599,"children":18600},{"__ignoreMap":401},[18601],{"type":415,"tag":532,"props":18602,"children":18603},{"class":534,"line":535},[18604,18608,18612],{"type":415,"tag":532,"props":18605,"children":18606},{"style":631},[18607],{"type":420,"value":311},{"type":415,"tag":532,"props":18609,"children":18610},{"style":804},[18611],{"type":420,"value":3276},{"type":415,"tag":532,"props":18613,"children":18614},{"style":804},[18615],{"type":420,"value":18616}," azure-csharp\n",{"type":415,"tag":416,"props":18618,"children":18619},{},[18620],{"type":415,"tag":3882,"props":18621,"children":18625},{"alt":18622,"className":18623,"src":18624},"IDE folder explorer focused on the infra folder containing the Pulumi project.",[3886,3887],"/posts/images/pulumi_met_nuke_6.png",[],{"type":415,"tag":416,"props":18627,"children":18628},{},[18629],{"type":420,"value":18630},"I will show later how to modify the code of the template to provision an App Service.",{"type":415,"tag":18632,"props":18633,"children":18634},"blockquote",{},[18635],{"type":415,"tag":416,"props":18636,"children":18637},{},[18638,18640,18647],{"type":420,"value":18639},"You can check Pulumi ",{"type":415,"tag":423,"props":18641,"children":18644},{"href":18642,"rel":18643},"https://www.pulumi.com/docs/get-started/azure/",[427],[18645],{"type":420,"value":18646},"Getting Started with Azure",{"type":420,"value":18648}," tutorial to see how to set up your environment and start creating Azure resources in C# (or in another language).",{"type":415,"tag":416,"props":18650,"children":18651},{},[18652,18654,18660],{"type":420,"value":18653},"To initialize the build project, we can use Nuke's .NET global tool as explained in the ",{"type":415,"tag":423,"props":18655,"children":18658},{"href":18656,"rel":18657},"https://nuke.build/docs/getting-started/setup/",[427],[18659],{"type":420,"value":499},{"type":420,"value":1290},{"type":415,"tag":523,"props":18662,"children":18664},{"className":3984,"code":18663,"language":3986,"meta":401,"style":401},"nuke :setup\n",[18665],{"type":415,"tag":468,"props":18666,"children":18667},{"__ignoreMap":401},[18668],{"type":415,"tag":532,"props":18669,"children":18670},{"class":534,"line":535},[18671,18675],{"type":415,"tag":532,"props":18672,"children":18673},{"style":631},[18674],{"type":420,"value":364},{"type":415,"tag":532,"props":18676,"children":18677},{"style":804},[18678],{"type":420,"value":18679}," :setup\n",{"type":415,"tag":416,"props":18681,"children":18682},{},[18683],{"type":415,"tag":3882,"props":18684,"children":18688},{"alt":18685,"className":18686,"src":18687},"IDE folder explorer focused on the build folder containing the Nuke project.",[3886,3887],"/posts/images/pulumi_met_nuke_7.png",[],{"type":415,"tag":3914,"props":18690,"children":18692},{"id":18691},"everything-in-net",[18693],{"type":420,"value":18694},"Everything in .NET",{"type":415,"tag":416,"props":18696,"children":18697},{},[18698],{"type":420,"value":18699},"What I like about using Pulumi (in .NET) and Nuke is that all the code is just C# code.  My infrastructure project and my build project are standard .NET console applications. And I can open the 3 projects (API, infrastructure, and build) in the same solution in my preferred IDE.",{"type":415,"tag":416,"props":18701,"children":18702},{},[18703],{"type":415,"tag":3882,"props":18704,"children":18708},{"alt":18705,"className":18706,"src":18707},"IDE solution explorer witht the infra, build and api projects.",[3886,3887],"/posts/images/pulumi_met_nuke_8.png",[],{"type":415,"tag":416,"props":18710,"children":18711},{},[18712],{"type":420,"value":18713},"Why does it matter? Because any .NET developer in a team would be able to understand and maintain this code. How many times have you seen a project slow down because the person responsible for the infrastructure code written in YAML, JSON, Bicep, or HCL was on vacation or ill? How often have you been stuck because the only few people in the team that knew how to modify the YAML pipelines were not available?",{"type":415,"tag":416,"props":18715,"children":18716},{},[18717],{"type":420,"value":18718},"But it's not a question of knowledge only. It's also because the developer experience of writing build or infrastructure code in .NET is much better than writing code in YAML or other declarative \"languages\".",{"type":415,"tag":434,"props":18720,"children":18721},{"icon":1382},[18722],{"type":415,"tag":416,"props":18723,"children":18724},{},[18725,18727,18733],{"type":420,"value":18726},"I talk a lot about the benefits of using programming languages for infrastructure code in my article \"",{"type":415,"tag":423,"props":18728,"children":18731},{"href":18729,"rel":18730},"https://www.techwatching.dev/posts/pulumi-vs-terraform",[427],[18732],{"type":420,"value":114},{"type":420,"value":18734},"\" if you have not read it yet.",{"type":415,"tag":482,"props":18736,"children":18738},{"id":18737},"implementing-the-pipeline-steps-from-clean-to-publish",[18739],{"type":420,"value":18740},"Implementing the pipeline steps from Clean to Publish",{"type":415,"tag":3914,"props":18742,"children":18744},{"id":18743},"the-nuke-pipeline",[18745],{"type":420,"value":18746},"The Nuke pipeline",{"type":415,"tag":416,"props":18748,"children":18749},{},[18750],{"type":420,"value":18751},"Here is what looks like the default build project after its creation:",{"type":415,"tag":416,"props":18753,"children":18754},{},[18755],{"type":415,"tag":3882,"props":18756,"children":18760},{"alt":18757,"className":18758,"src":18759},"Buidl code file with the build steps opened in the IDE.",[3886,3887],"/posts/images/pulumi_met_nuke_9.png",[],{"type":415,"tag":416,"props":18762,"children":18763},{},[18764,18766,18772,18774,18781],{"type":420,"value":18765},"The main method is contained in a ",{"type":415,"tag":468,"props":18767,"children":18769},{"className":18768},[],[18770],{"type":420,"value":18771},"Build.cs",{"type":420,"value":18773}," file. This file contains the steps of the pipeline that are called ",{"type":415,"tag":423,"props":18775,"children":18778},{"href":18776,"rel":18777},"https://nuke.build/docs/fundamentals/targets/",[427],[18779],{"type":420,"value":18780},"Target",{"type":420,"value":18782}," in Nuke. We can set the dependencies between targets.",{"type":415,"tag":434,"props":18784,"children":18785},{"icon":436},[18786],{"type":415,"tag":416,"props":18787,"children":18788},{},[18789],{"type":420,"value":18790},"The build project is a .NET console application so it works out of the box in any .NET IDE or from the command line. But to be more productive you can install a plugin for your IDE that will add snippets and a way to easily debug each target individually.",{"type":415,"tag":416,"props":18792,"children":18793},{},[18794],{"type":420,"value":18795},"As you see we can define properties with the attribute Parameter if we need to pass parameters to our pipeline, like the Configuration parameter.",{"type":415,"tag":3914,"props":18797,"children":18799},{"id":18798},"the-clean-target",[18800],{"type":420,"value":18801},"The Clean target",{"type":415,"tag":416,"props":18803,"children":18804},{},[18805],{"type":420,"value":18806},"We can define the Clean target like that:",{"type":415,"tag":523,"props":18808,"children":18810},{"className":525,"code":18809,"language":326,"meta":401,"style":401},"Target Clean => _ => _  \n    .Before(Restore)  \n    .Executes(() =>  \n    {  \n        SourceDirectory.GlobDirectories(\"*/bin\", \"*/obj\").ForEach(DeleteDirectory);  \n        EnsureCleanDirectory(ArtifactsDirectory);  \n    });\n",[18811],{"type":415,"tag":468,"props":18812,"children":18813},{"__ignoreMap":401},[18814,18843,18874,18899,18911,18989,19014],{"type":415,"tag":532,"props":18815,"children":18816},{"class":534,"line":535},[18817,18822,18826,18830,18834,18838],{"type":415,"tag":532,"props":18818,"children":18819},{"style":545},[18820],{"type":420,"value":18821},"Target ",{"type":415,"tag":532,"props":18823,"children":18824},{"style":631},[18825],{"type":420,"value":7935},{"type":415,"tag":532,"props":18827,"children":18828},{"style":551},[18829],{"type":420,"value":8499},{"type":415,"tag":532,"props":18831,"children":18832},{"style":631},[18833],{"type":420,"value":3178},{"type":415,"tag":532,"props":18835,"children":18836},{"style":551},[18837],{"type":420,"value":8499},{"type":415,"tag":532,"props":18839,"children":18840},{"style":545},[18841],{"type":420,"value":18842}," _  \n",{"type":415,"tag":532,"props":18844,"children":18845},{"class":534,"line":566},[18846,18851,18856,18860,18865,18869],{"type":415,"tag":532,"props":18847,"children":18848},{"style":551},[18849],{"type":420,"value":18850},"    .",{"type":415,"tag":532,"props":18852,"children":18853},{"style":656},[18854],{"type":420,"value":18855},"Before",{"type":415,"tag":532,"props":18857,"children":18858},{"style":551},[18859],{"type":420,"value":664},{"type":415,"tag":532,"props":18861,"children":18862},{"style":545},[18863],{"type":420,"value":18864},"Restore",{"type":415,"tag":532,"props":18866,"children":18867},{"style":551},[18868],{"type":420,"value":1349},{"type":415,"tag":532,"props":18870,"children":18871},{"style":545},[18872],{"type":420,"value":18873},"  \n",{"type":415,"tag":532,"props":18875,"children":18876},{"class":534,"line":583},[18877,18881,18886,18891,18895],{"type":415,"tag":532,"props":18878,"children":18879},{"style":551},[18880],{"type":420,"value":18850},{"type":415,"tag":532,"props":18882,"children":18883},{"style":656},[18884],{"type":420,"value":18885},"Executes",{"type":415,"tag":532,"props":18887,"children":18888},{"style":551},[18889],{"type":420,"value":18890},"(()",{"type":415,"tag":532,"props":18892,"children":18893},{"style":551},[18894],{"type":420,"value":8499},{"type":415,"tag":532,"props":18896,"children":18897},{"style":545},[18898],{"type":420,"value":18873},{"type":415,"tag":532,"props":18900,"children":18901},{"class":534,"line":617},[18902,18907],{"type":415,"tag":532,"props":18903,"children":18904},{"style":551},[18905],{"type":420,"value":18906},"    {",{"type":415,"tag":532,"props":18908,"children":18909},{"style":545},[18910],{"type":420,"value":18873},{"type":415,"tag":532,"props":18912,"children":18913},{"class":534,"line":627},[18914,18919,18923,18928,18932,18936,18941,18945,18949,18953,18958,18962,18966,18971,18975,18980,18985],{"type":415,"tag":532,"props":18915,"children":18916},{"style":545},[18917],{"type":420,"value":18918},"        SourceDirectory",{"type":415,"tag":532,"props":18920,"children":18921},{"style":551},[18922],{"type":420,"value":432},{"type":415,"tag":532,"props":18924,"children":18925},{"style":656},[18926],{"type":420,"value":18927},"GlobDirectories",{"type":415,"tag":532,"props":18929,"children":18930},{"style":551},[18931],{"type":420,"value":664},{"type":415,"tag":532,"props":18933,"children":18934},{"style":551},[18935],{"type":420,"value":801},{"type":415,"tag":532,"props":18937,"children":18938},{"style":804},[18939],{"type":420,"value":18940},"*/bin",{"type":415,"tag":532,"props":18942,"children":18943},{"style":551},[18944],{"type":420,"value":801},{"type":415,"tag":532,"props":18946,"children":18947},{"style":551},[18948],{"type":420,"value":1099},{"type":415,"tag":532,"props":18950,"children":18951},{"style":551},[18952],{"type":420,"value":4041},{"type":415,"tag":532,"props":18954,"children":18955},{"style":804},[18956],{"type":420,"value":18957},"*/obj",{"type":415,"tag":532,"props":18959,"children":18960},{"style":551},[18961],{"type":420,"value":801},{"type":415,"tag":532,"props":18963,"children":18964},{"style":551},[18965],{"type":420,"value":6886},{"type":415,"tag":532,"props":18967,"children":18968},{"style":656},[18969],{"type":420,"value":18970},"ForEach",{"type":415,"tag":532,"props":18972,"children":18973},{"style":551},[18974],{"type":420,"value":664},{"type":415,"tag":532,"props":18976,"children":18977},{"style":545},[18978],{"type":420,"value":18979},"DeleteDirectory",{"type":415,"tag":532,"props":18981,"children":18982},{"style":551},[18983],{"type":420,"value":18984},");",{"type":415,"tag":532,"props":18986,"children":18987},{"style":545},[18988],{"type":420,"value":18873},{"type":415,"tag":532,"props":18990,"children":18991},{"class":534,"line":677},[18992,18997,19001,19006,19010],{"type":415,"tag":532,"props":18993,"children":18994},{"style":656},[18995],{"type":420,"value":18996},"        EnsureCleanDirectory",{"type":415,"tag":532,"props":18998,"children":18999},{"style":551},[19000],{"type":420,"value":664},{"type":415,"tag":532,"props":19002,"children":19003},{"style":545},[19004],{"type":420,"value":19005},"ArtifactsDirectory",{"type":415,"tag":532,"props":19007,"children":19008},{"style":551},[19009],{"type":420,"value":18984},{"type":415,"tag":532,"props":19011,"children":19012},{"style":545},[19013],{"type":420,"value":18873},{"type":415,"tag":532,"props":19015,"children":19016},{"class":534,"line":719},[19017],{"type":415,"tag":532,"props":19018,"children":19019},{"style":551},[19020],{"type":420,"value":2468},{"type":415,"tag":416,"props":19022,"children":19023},{},[19024],{"type":420,"value":19025},"This code deletes all the bin and obj directories of the source directory. It also deletes the content in the artifacts directory. Nuke overloads the division operator to allow us to easily define paths in the project.",{"type":415,"tag":523,"props":19027,"children":19029},{"className":525,"code":19028,"language":326,"meta":401,"style":401},"AbsolutePath SourceDirectory => RootDirectory / \"src\";  \n  \nAbsolutePath InfrastructureDirectory => RootDirectory / \"infra\";  \n  \nAbsolutePath ArtifactsDirectory => RootDirectory / \"artifacts\";\n",[19030],{"type":415,"tag":468,"props":19031,"children":19032},{"__ignoreMap":401},[19033,19080,19087,19132,19139],{"type":415,"tag":532,"props":19034,"children":19035},{"class":534,"line":535},[19036,19041,19046,19050,19055,19059,19063,19068,19072,19076],{"type":415,"tag":532,"props":19037,"children":19038},{"style":545},[19039],{"type":420,"value":19040},"AbsolutePath ",{"type":415,"tag":532,"props":19042,"children":19043},{"style":631},[19044],{"type":420,"value":19045},"SourceDirectory",{"type":415,"tag":532,"props":19047,"children":19048},{"style":551},[19049],{"type":420,"value":8499},{"type":415,"tag":532,"props":19051,"children":19052},{"style":545},[19053],{"type":420,"value":19054}," RootDirectory ",{"type":415,"tag":532,"props":19056,"children":19057},{"style":551},[19058],{"type":420,"value":4728},{"type":415,"tag":532,"props":19060,"children":19061},{"style":551},[19062],{"type":420,"value":4041},{"type":415,"tag":532,"props":19064,"children":19065},{"style":804},[19066],{"type":420,"value":19067},"src",{"type":415,"tag":532,"props":19069,"children":19070},{"style":551},[19071],{"type":420,"value":801},{"type":415,"tag":532,"props":19073,"children":19074},{"style":551},[19075],{"type":420,"value":15807},{"type":415,"tag":532,"props":19077,"children":19078},{"style":545},[19079],{"type":420,"value":18873},{"type":415,"tag":532,"props":19081,"children":19082},{"class":534,"line":566},[19083],{"type":415,"tag":532,"props":19084,"children":19085},{"style":545},[19086],{"type":420,"value":18873},{"type":415,"tag":532,"props":19088,"children":19089},{"class":534,"line":583},[19090,19094,19099,19103,19107,19111,19115,19120,19124,19128],{"type":415,"tag":532,"props":19091,"children":19092},{"style":545},[19093],{"type":420,"value":19040},{"type":415,"tag":532,"props":19095,"children":19096},{"style":631},[19097],{"type":420,"value":19098},"InfrastructureDirectory",{"type":415,"tag":532,"props":19100,"children":19101},{"style":551},[19102],{"type":420,"value":8499},{"type":415,"tag":532,"props":19104,"children":19105},{"style":545},[19106],{"type":420,"value":19054},{"type":415,"tag":532,"props":19108,"children":19109},{"style":551},[19110],{"type":420,"value":4728},{"type":415,"tag":532,"props":19112,"children":19113},{"style":551},[19114],{"type":420,"value":4041},{"type":415,"tag":532,"props":19116,"children":19117},{"style":804},[19118],{"type":420,"value":19119},"infra",{"type":415,"tag":532,"props":19121,"children":19122},{"style":551},[19123],{"type":420,"value":801},{"type":415,"tag":532,"props":19125,"children":19126},{"style":551},[19127],{"type":420,"value":15807},{"type":415,"tag":532,"props":19129,"children":19130},{"style":545},[19131],{"type":420,"value":18873},{"type":415,"tag":532,"props":19133,"children":19134},{"class":534,"line":617},[19135],{"type":415,"tag":532,"props":19136,"children":19137},{"style":545},[19138],{"type":420,"value":18873},{"type":415,"tag":532,"props":19140,"children":19141},{"class":534,"line":627},[19142,19146,19150,19154,19158,19162,19166,19170,19174],{"type":415,"tag":532,"props":19143,"children":19144},{"style":545},[19145],{"type":420,"value":19040},{"type":415,"tag":532,"props":19147,"children":19148},{"style":631},[19149],{"type":420,"value":19005},{"type":415,"tag":532,"props":19151,"children":19152},{"style":551},[19153],{"type":420,"value":8499},{"type":415,"tag":532,"props":19155,"children":19156},{"style":545},[19157],{"type":420,"value":19054},{"type":415,"tag":532,"props":19159,"children":19160},{"style":551},[19161],{"type":420,"value":4728},{"type":415,"tag":532,"props":19163,"children":19164},{"style":551},[19165],{"type":420,"value":4041},{"type":415,"tag":532,"props":19167,"children":19168},{"style":804},[19169],{"type":420,"value":7618},{"type":415,"tag":532,"props":19171,"children":19172},{"style":551},[19173],{"type":420,"value":801},{"type":415,"tag":532,"props":19175,"children":19176},{"style":551},[19177],{"type":420,"value":563},{"type":415,"tag":3914,"props":19179,"children":19181},{"id":19180},"the-restore-target",[19182],{"type":420,"value":19183},"The Restore target",{"type":415,"tag":416,"props":19185,"children":19186},{},[19187,19189,19195,19197,19204],{"type":420,"value":19188},"To restore .NET dependencies, we can use the ",{"type":415,"tag":468,"props":19190,"children":19192},{"className":19191},[],[19193],{"type":420,"value":19194},"dotnet restore",{"type":420,"value":19196}," command. Nuke supports ",{"type":415,"tag":423,"props":19198,"children":19201},{"href":19199,"rel":19200},"https://nuke.build/docs/common/cli-tools/",[427],[19202],{"type":420,"value":19203},"executing CLI tools",{"type":420,"value":19205}," and has even auto-generated CLI wrappers for some common tools like dotnet CLI to use a Fluent API instead of string interpolation to pass parameters.",{"type":415,"tag":523,"props":19207,"children":19209},{"className":525,"code":19208,"language":326,"meta":401,"style":401},"Target Restore => _ => _  \n    .Executes(() =>  \n    {  \n        DotNetRestore(_ => _.SetProjectFile(Solution));  \n    });\n",[19210],{"type":415,"tag":468,"props":19211,"children":19212},{"__ignoreMap":401},[19213,19240,19263,19274,19325],{"type":415,"tag":532,"props":19214,"children":19215},{"class":534,"line":535},[19216,19220,19224,19228,19232,19236],{"type":415,"tag":532,"props":19217,"children":19218},{"style":545},[19219],{"type":420,"value":18821},{"type":415,"tag":532,"props":19221,"children":19222},{"style":631},[19223],{"type":420,"value":18864},{"type":415,"tag":532,"props":19225,"children":19226},{"style":551},[19227],{"type":420,"value":8499},{"type":415,"tag":532,"props":19229,"children":19230},{"style":631},[19231],{"type":420,"value":3178},{"type":415,"tag":532,"props":19233,"children":19234},{"style":551},[19235],{"type":420,"value":8499},{"type":415,"tag":532,"props":19237,"children":19238},{"style":545},[19239],{"type":420,"value":18842},{"type":415,"tag":532,"props":19241,"children":19242},{"class":534,"line":566},[19243,19247,19251,19255,19259],{"type":415,"tag":532,"props":19244,"children":19245},{"style":551},[19246],{"type":420,"value":18850},{"type":415,"tag":532,"props":19248,"children":19249},{"style":656},[19250],{"type":420,"value":18885},{"type":415,"tag":532,"props":19252,"children":19253},{"style":551},[19254],{"type":420,"value":18890},{"type":415,"tag":532,"props":19256,"children":19257},{"style":551},[19258],{"type":420,"value":8499},{"type":415,"tag":532,"props":19260,"children":19261},{"style":545},[19262],{"type":420,"value":18873},{"type":415,"tag":532,"props":19264,"children":19265},{"class":534,"line":583},[19266,19270],{"type":415,"tag":532,"props":19267,"children":19268},{"style":551},[19269],{"type":420,"value":18906},{"type":415,"tag":532,"props":19271,"children":19272},{"style":545},[19273],{"type":420,"value":18873},{"type":415,"tag":532,"props":19275,"children":19276},{"class":534,"line":617},[19277,19282,19286,19290,19294,19298,19302,19307,19311,19316,19321],{"type":415,"tag":532,"props":19278,"children":19279},{"style":656},[19280],{"type":420,"value":19281},"        DotNetRestore",{"type":415,"tag":532,"props":19283,"children":19284},{"style":551},[19285],{"type":420,"value":664},{"type":415,"tag":532,"props":19287,"children":19288},{"style":631},[19289],{"type":420,"value":3169},{"type":415,"tag":532,"props":19291,"children":19292},{"style":551},[19293],{"type":420,"value":8499},{"type":415,"tag":532,"props":19295,"children":19296},{"style":545},[19297],{"type":420,"value":3178},{"type":415,"tag":532,"props":19299,"children":19300},{"style":551},[19301],{"type":420,"value":432},{"type":415,"tag":532,"props":19303,"children":19304},{"style":656},[19305],{"type":420,"value":19306},"SetProjectFile",{"type":415,"tag":532,"props":19308,"children":19309},{"style":551},[19310],{"type":420,"value":664},{"type":415,"tag":532,"props":19312,"children":19313},{"style":545},[19314],{"type":420,"value":19315},"Solution",{"type":415,"tag":532,"props":19317,"children":19318},{"style":551},[19319],{"type":420,"value":19320},"));",{"type":415,"tag":532,"props":19322,"children":19323},{"style":545},[19324],{"type":420,"value":18873},{"type":415,"tag":532,"props":19326,"children":19327},{"class":534,"line":627},[19328],{"type":415,"tag":532,"props":19329,"children":19330},{"style":551},[19331],{"type":420,"value":2468},{"type":415,"tag":3914,"props":19333,"children":19335},{"id":19334},"the-compile-target",[19336],{"type":420,"value":19337},"The Compile target",{"type":415,"tag":416,"props":19339,"children":19340},{},[19341,19343,19349,19351,19357,19359,19365],{"type":420,"value":19342},"The compile target uses the ",{"type":415,"tag":468,"props":19344,"children":19346},{"className":19345},[],[19347],{"type":420,"value":19348},"dotnet build",{"type":420,"value":19350}," command. We can start to see the benefits of using this Fluent API that provides us with autocompletion and documentation. For instance, as we already restored the dependencies in the previous step, we can set the ",{"type":415,"tag":468,"props":19352,"children":19354},{"className":19353},[],[19355],{"type":420,"value":19356},"--no-restore",{"type":420,"value":19358}," option using the ",{"type":415,"tag":468,"props":19360,"children":19362},{"className":19361},[],[19363],{"type":420,"value":19364},"EnableNoRestore",{"type":420,"value":19366}," auto-generated method.",{"type":415,"tag":523,"props":19368,"children":19370},{"className":525,"code":19369,"language":326,"meta":401,"style":401},"Target Compile => _ => _  \n    .DependsOn(Restore)  \n    .Executes(() =>  \n    {  \n        DotNetBuild(_ => _  \n            .SetProjectFile(Solution)  \n            .SetConfiguration(Configuration)  \n            .EnableNoRestore());  \n    });\n",[19371],{"type":415,"tag":468,"props":19372,"children":19373},{"__ignoreMap":401},[19374,19402,19430,19453,19464,19488,19515,19543,19563],{"type":415,"tag":532,"props":19375,"children":19376},{"class":534,"line":535},[19377,19381,19386,19390,19394,19398],{"type":415,"tag":532,"props":19378,"children":19379},{"style":545},[19380],{"type":420,"value":18821},{"type":415,"tag":532,"props":19382,"children":19383},{"style":631},[19384],{"type":420,"value":19385},"Compile",{"type":415,"tag":532,"props":19387,"children":19388},{"style":551},[19389],{"type":420,"value":8499},{"type":415,"tag":532,"props":19391,"children":19392},{"style":631},[19393],{"type":420,"value":3178},{"type":415,"tag":532,"props":19395,"children":19396},{"style":551},[19397],{"type":420,"value":8499},{"type":415,"tag":532,"props":19399,"children":19400},{"style":545},[19401],{"type":420,"value":18842},{"type":415,"tag":532,"props":19403,"children":19404},{"class":534,"line":566},[19405,19409,19414,19418,19422,19426],{"type":415,"tag":532,"props":19406,"children":19407},{"style":551},[19408],{"type":420,"value":18850},{"type":415,"tag":532,"props":19410,"children":19411},{"style":656},[19412],{"type":420,"value":19413},"DependsOn",{"type":415,"tag":532,"props":19415,"children":19416},{"style":551},[19417],{"type":420,"value":664},{"type":415,"tag":532,"props":19419,"children":19420},{"style":545},[19421],{"type":420,"value":18864},{"type":415,"tag":532,"props":19423,"children":19424},{"style":551},[19425],{"type":420,"value":1349},{"type":415,"tag":532,"props":19427,"children":19428},{"style":545},[19429],{"type":420,"value":18873},{"type":415,"tag":532,"props":19431,"children":19432},{"class":534,"line":583},[19433,19437,19441,19445,19449],{"type":415,"tag":532,"props":19434,"children":19435},{"style":551},[19436],{"type":420,"value":18850},{"type":415,"tag":532,"props":19438,"children":19439},{"style":656},[19440],{"type":420,"value":18885},{"type":415,"tag":532,"props":19442,"children":19443},{"style":551},[19444],{"type":420,"value":18890},{"type":415,"tag":532,"props":19446,"children":19447},{"style":551},[19448],{"type":420,"value":8499},{"type":415,"tag":532,"props":19450,"children":19451},{"style":545},[19452],{"type":420,"value":18873},{"type":415,"tag":532,"props":19454,"children":19455},{"class":534,"line":617},[19456,19460],{"type":415,"tag":532,"props":19457,"children":19458},{"style":551},[19459],{"type":420,"value":18906},{"type":415,"tag":532,"props":19461,"children":19462},{"style":545},[19463],{"type":420,"value":18873},{"type":415,"tag":532,"props":19465,"children":19466},{"class":534,"line":627},[19467,19472,19476,19480,19484],{"type":415,"tag":532,"props":19468,"children":19469},{"style":656},[19470],{"type":420,"value":19471},"        DotNetBuild",{"type":415,"tag":532,"props":19473,"children":19474},{"style":551},[19475],{"type":420,"value":664},{"type":415,"tag":532,"props":19477,"children":19478},{"style":631},[19479],{"type":420,"value":3169},{"type":415,"tag":532,"props":19481,"children":19482},{"style":551},[19483],{"type":420,"value":8499},{"type":415,"tag":532,"props":19485,"children":19486},{"style":545},[19487],{"type":420,"value":18842},{"type":415,"tag":532,"props":19489,"children":19490},{"class":534,"line":677},[19491,19495,19499,19503,19507,19511],{"type":415,"tag":532,"props":19492,"children":19493},{"style":551},[19494],{"type":420,"value":3328},{"type":415,"tag":532,"props":19496,"children":19497},{"style":656},[19498],{"type":420,"value":19306},{"type":415,"tag":532,"props":19500,"children":19501},{"style":551},[19502],{"type":420,"value":664},{"type":415,"tag":532,"props":19504,"children":19505},{"style":545},[19506],{"type":420,"value":19315},{"type":415,"tag":532,"props":19508,"children":19509},{"style":551},[19510],{"type":420,"value":1349},{"type":415,"tag":532,"props":19512,"children":19513},{"style":545},[19514],{"type":420,"value":18873},{"type":415,"tag":532,"props":19516,"children":19517},{"class":534,"line":719},[19518,19522,19527,19531,19535,19539],{"type":415,"tag":532,"props":19519,"children":19520},{"style":551},[19521],{"type":420,"value":3328},{"type":415,"tag":532,"props":19523,"children":19524},{"style":656},[19525],{"type":420,"value":19526},"SetConfiguration",{"type":415,"tag":532,"props":19528,"children":19529},{"style":551},[19530],{"type":420,"value":664},{"type":415,"tag":532,"props":19532,"children":19533},{"style":545},[19534],{"type":420,"value":263},{"type":415,"tag":532,"props":19536,"children":19537},{"style":551},[19538],{"type":420,"value":1349},{"type":415,"tag":532,"props":19540,"children":19541},{"style":545},[19542],{"type":420,"value":18873},{"type":415,"tag":532,"props":19544,"children":19545},{"class":534,"line":758},[19546,19550,19554,19559],{"type":415,"tag":532,"props":19547,"children":19548},{"style":551},[19549],{"type":420,"value":3328},{"type":415,"tag":532,"props":19551,"children":19552},{"style":656},[19553],{"type":420,"value":19364},{"type":415,"tag":532,"props":19555,"children":19556},{"style":551},[19557],{"type":420,"value":19558},"());",{"type":415,"tag":532,"props":19560,"children":19561},{"style":545},[19562],{"type":420,"value":18873},{"type":415,"tag":532,"props":19564,"children":19565},{"class":534,"line":767},[19566],{"type":415,"tag":532,"props":19567,"children":19568},{"style":551},[19569],{"type":420,"value":2468},{"type":415,"tag":3914,"props":19571,"children":19573},{"id":19572},"the-publish-target",[19574],{"type":420,"value":19575},"The Publish target",{"type":415,"tag":416,"props":19577,"children":19578},{},[19579,19581,19586,19588,19594],{"type":420,"value":19580},"The publish target uses the ",{"type":415,"tag":468,"props":19582,"children":19584},{"className":19583},[],[19585],{"type":420,"value":18453},{"type":420,"value":19587}," command and then creates a zip ",{"type":415,"tag":468,"props":19589,"children":19591},{"className":19590},[],[19592],{"type":420,"value":19593},"api.zip",{"type":420,"value":19595}," of the resulting package in the artifacts directory.",{"type":415,"tag":523,"props":19597,"children":19599},{"className":525,"code":19598,"language":326,"meta":401,"style":401},"Target Publish => _ => _  \n    .DependsOn(Clean, Compile)  \n    .Executes(() =>  \n    {  \n        DotNetPublish(_ => _  \n            .SetProject(Solution.CSharpEverything_Api)  \n            .SetConfiguration(Configuration)  \n            .EnableNoBuild()  \n            .SetOutput(ApiPackageDirectory));  \n  \n        ZipFile.CreateFromDirectory(ApiPackageDirectory, ArtifactsDirectory / \"api.zip\");  \n    });\n",[19600],{"type":415,"tag":468,"props":19601,"children":19602},{"__ignoreMap":401},[19603,19631,19667,19690,19701,19725,19762,19789,19809,19838,19845,19903],{"type":415,"tag":532,"props":19604,"children":19605},{"class":534,"line":535},[19606,19610,19615,19619,19623,19627],{"type":415,"tag":532,"props":19607,"children":19608},{"style":545},[19609],{"type":420,"value":18821},{"type":415,"tag":532,"props":19611,"children":19612},{"style":631},[19613],{"type":420,"value":19614},"Publish",{"type":415,"tag":532,"props":19616,"children":19617},{"style":551},[19618],{"type":420,"value":8499},{"type":415,"tag":532,"props":19620,"children":19621},{"style":631},[19622],{"type":420,"value":3178},{"type":415,"tag":532,"props":19624,"children":19625},{"style":551},[19626],{"type":420,"value":8499},{"type":415,"tag":532,"props":19628,"children":19629},{"style":545},[19630],{"type":420,"value":18842},{"type":415,"tag":532,"props":19632,"children":19633},{"class":534,"line":566},[19634,19638,19642,19646,19650,19654,19659,19663],{"type":415,"tag":532,"props":19635,"children":19636},{"style":551},[19637],{"type":420,"value":18850},{"type":415,"tag":532,"props":19639,"children":19640},{"style":656},[19641],{"type":420,"value":19413},{"type":415,"tag":532,"props":19643,"children":19644},{"style":551},[19645],{"type":420,"value":664},{"type":415,"tag":532,"props":19647,"children":19648},{"style":545},[19649],{"type":420,"value":7935},{"type":415,"tag":532,"props":19651,"children":19652},{"style":551},[19653],{"type":420,"value":1099},{"type":415,"tag":532,"props":19655,"children":19656},{"style":545},[19657],{"type":420,"value":19658}," Compile",{"type":415,"tag":532,"props":19660,"children":19661},{"style":551},[19662],{"type":420,"value":1349},{"type":415,"tag":532,"props":19664,"children":19665},{"style":545},[19666],{"type":420,"value":18873},{"type":415,"tag":532,"props":19668,"children":19669},{"class":534,"line":583},[19670,19674,19678,19682,19686],{"type":415,"tag":532,"props":19671,"children":19672},{"style":551},[19673],{"type":420,"value":18850},{"type":415,"tag":532,"props":19675,"children":19676},{"style":656},[19677],{"type":420,"value":18885},{"type":415,"tag":532,"props":19679,"children":19680},{"style":551},[19681],{"type":420,"value":18890},{"type":415,"tag":532,"props":19683,"children":19684},{"style":551},[19685],{"type":420,"value":8499},{"type":415,"tag":532,"props":19687,"children":19688},{"style":545},[19689],{"type":420,"value":18873},{"type":415,"tag":532,"props":19691,"children":19692},{"class":534,"line":617},[19693,19697],{"type":415,"tag":532,"props":19694,"children":19695},{"style":551},[19696],{"type":420,"value":18906},{"type":415,"tag":532,"props":19698,"children":19699},{"style":545},[19700],{"type":420,"value":18873},{"type":415,"tag":532,"props":19702,"children":19703},{"class":534,"line":627},[19704,19709,19713,19717,19721],{"type":415,"tag":532,"props":19705,"children":19706},{"style":656},[19707],{"type":420,"value":19708},"        DotNetPublish",{"type":415,"tag":532,"props":19710,"children":19711},{"style":551},[19712],{"type":420,"value":664},{"type":415,"tag":532,"props":19714,"children":19715},{"style":631},[19716],{"type":420,"value":3169},{"type":415,"tag":532,"props":19718,"children":19719},{"style":551},[19720],{"type":420,"value":8499},{"type":415,"tag":532,"props":19722,"children":19723},{"style":545},[19724],{"type":420,"value":18842},{"type":415,"tag":532,"props":19726,"children":19727},{"class":534,"line":677},[19728,19732,19737,19741,19745,19749,19754,19758],{"type":415,"tag":532,"props":19729,"children":19730},{"style":551},[19731],{"type":420,"value":3328},{"type":415,"tag":532,"props":19733,"children":19734},{"style":656},[19735],{"type":420,"value":19736},"SetProject",{"type":415,"tag":532,"props":19738,"children":19739},{"style":551},[19740],{"type":420,"value":664},{"type":415,"tag":532,"props":19742,"children":19743},{"style":545},[19744],{"type":420,"value":19315},{"type":415,"tag":532,"props":19746,"children":19747},{"style":551},[19748],{"type":420,"value":432},{"type":415,"tag":532,"props":19750,"children":19751},{"style":545},[19752],{"type":420,"value":19753},"CSharpEverything_Api",{"type":415,"tag":532,"props":19755,"children":19756},{"style":551},[19757],{"type":420,"value":1349},{"type":415,"tag":532,"props":19759,"children":19760},{"style":545},[19761],{"type":420,"value":18873},{"type":415,"tag":532,"props":19763,"children":19764},{"class":534,"line":719},[19765,19769,19773,19777,19781,19785],{"type":415,"tag":532,"props":19766,"children":19767},{"style":551},[19768],{"type":420,"value":3328},{"type":415,"tag":532,"props":19770,"children":19771},{"style":656},[19772],{"type":420,"value":19526},{"type":415,"tag":532,"props":19774,"children":19775},{"style":551},[19776],{"type":420,"value":664},{"type":415,"tag":532,"props":19778,"children":19779},{"style":545},[19780],{"type":420,"value":263},{"type":415,"tag":532,"props":19782,"children":19783},{"style":551},[19784],{"type":420,"value":1349},{"type":415,"tag":532,"props":19786,"children":19787},{"style":545},[19788],{"type":420,"value":18873},{"type":415,"tag":532,"props":19790,"children":19791},{"class":534,"line":758},[19792,19796,19801,19805],{"type":415,"tag":532,"props":19793,"children":19794},{"style":551},[19795],{"type":420,"value":3328},{"type":415,"tag":532,"props":19797,"children":19798},{"style":656},[19799],{"type":420,"value":19800},"EnableNoBuild",{"type":415,"tag":532,"props":19802,"children":19803},{"style":551},[19804],{"type":420,"value":12966},{"type":415,"tag":532,"props":19806,"children":19807},{"style":545},[19808],{"type":420,"value":18873},{"type":415,"tag":532,"props":19810,"children":19811},{"class":534,"line":767},[19812,19816,19821,19825,19830,19834],{"type":415,"tag":532,"props":19813,"children":19814},{"style":551},[19815],{"type":420,"value":3328},{"type":415,"tag":532,"props":19817,"children":19818},{"style":656},[19819],{"type":420,"value":19820},"SetOutput",{"type":415,"tag":532,"props":19822,"children":19823},{"style":551},[19824],{"type":420,"value":664},{"type":415,"tag":532,"props":19826,"children":19827},{"style":545},[19828],{"type":420,"value":19829},"ApiPackageDirectory",{"type":415,"tag":532,"props":19831,"children":19832},{"style":551},[19833],{"type":420,"value":19320},{"type":415,"tag":532,"props":19835,"children":19836},{"style":545},[19837],{"type":420,"value":18873},{"type":415,"tag":532,"props":19839,"children":19840},{"class":534,"line":819},[19841],{"type":415,"tag":532,"props":19842,"children":19843},{"style":545},[19844],{"type":420,"value":18873},{"type":415,"tag":532,"props":19846,"children":19847},{"class":534,"line":850},[19848,19853,19857,19862,19866,19870,19874,19879,19883,19887,19891,19895,19899],{"type":415,"tag":532,"props":19849,"children":19850},{"style":545},[19851],{"type":420,"value":19852},"        ZipFile",{"type":415,"tag":532,"props":19854,"children":19855},{"style":551},[19856],{"type":420,"value":432},{"type":415,"tag":532,"props":19858,"children":19859},{"style":656},[19860],{"type":420,"value":19861},"CreateFromDirectory",{"type":415,"tag":532,"props":19863,"children":19864},{"style":551},[19865],{"type":420,"value":664},{"type":415,"tag":532,"props":19867,"children":19868},{"style":545},[19869],{"type":420,"value":19829},{"type":415,"tag":532,"props":19871,"children":19872},{"style":551},[19873],{"type":420,"value":1099},{"type":415,"tag":532,"props":19875,"children":19876},{"style":545},[19877],{"type":420,"value":19878}," ArtifactsDirectory ",{"type":415,"tag":532,"props":19880,"children":19881},{"style":551},[19882],{"type":420,"value":4728},{"type":415,"tag":532,"props":19884,"children":19885},{"style":551},[19886],{"type":420,"value":4041},{"type":415,"tag":532,"props":19888,"children":19889},{"style":804},[19890],{"type":420,"value":19593},{"type":415,"tag":532,"props":19892,"children":19893},{"style":551},[19894],{"type":420,"value":801},{"type":415,"tag":532,"props":19896,"children":19897},{"style":551},[19898],{"type":420,"value":18984},{"type":415,"tag":532,"props":19900,"children":19901},{"style":545},[19902],{"type":420,"value":18873},{"type":415,"tag":532,"props":19904,"children":19905},{"class":534,"line":859},[19906],{"type":415,"tag":532,"props":19907,"children":19908},{"style":551},[19909],{"type":420,"value":2468},{"type":415,"tag":434,"props":19911,"children":19912},{"icon":436},[19913],{"type":415,"tag":416,"props":19914,"children":19915},{},[19916,19918,19925],{"type":420,"value":19917},"If you need more compressing archives options, you can check ",{"type":415,"tag":423,"props":19919,"children":19922},{"href":19920,"rel":19921},"https://nuke.build/docs/common/compression/#compressing-archives",[427],[19923],{"type":420,"value":19924},"Nuke documentation",{"type":420,"value":19926},", they have some utilities to do more complex scenarios.",{"type":415,"tag":416,"props":19928,"children":19929},{},[19930,19932,19939,19941,19946,19948,19954],{"type":420,"value":19931},"You may have noted on the line where I set the project that I have ",{"type":415,"tag":423,"props":19933,"children":19936},{"href":19934,"rel":19935},"https://nuke.build/docs/common/solution-project-model/#strong-typed-project-access",[427],[19937],{"type":420,"value":19938},"strong-typed access to the projects in my solution",{"type":420,"value":19940},". This is possible by adding this field with the ",{"type":415,"tag":468,"props":19942,"children":19944},{"className":19943},[],[19945],{"type":420,"value":19315},{"type":420,"value":19947}," attribute and its ",{"type":415,"tag":468,"props":19949,"children":19951},{"className":19950},[],[19952],{"type":420,"value":19953},"GenerateProjects",{"type":420,"value":19955}," property set to true.",{"type":415,"tag":523,"props":19957,"children":19959},{"className":525,"code":19958,"language":326,"meta":401,"style":401},"[Solution(GenerateProjects = true)]  \nreadonly Solution Solution;\n",[19960],{"type":415,"tag":468,"props":19961,"children":19962},{"__ignoreMap":401},[19963,20000],{"type":415,"tag":532,"props":19964,"children":19965},{"class":534,"line":535},[19966,19971,19975,19979,19983,19987,19991,19996],{"type":415,"tag":532,"props":19967,"children":19968},{"style":551},[19969],{"type":420,"value":19970},"[",{"type":415,"tag":532,"props":19972,"children":19973},{"style":631},[19974],{"type":420,"value":19315},{"type":415,"tag":532,"props":19976,"children":19977},{"style":551},[19978],{"type":420,"value":664},{"type":415,"tag":532,"props":19980,"children":19981},{"style":631},[19982],{"type":420,"value":19953},{"type":415,"tag":532,"props":19984,"children":19985},{"style":551},[19986],{"type":420,"value":644},{"type":415,"tag":532,"props":19988,"children":19989},{"style":1938},[19990],{"type":420,"value":1941},{"type":415,"tag":532,"props":19992,"children":19993},{"style":551},[19994],{"type":420,"value":19995},")]",{"type":415,"tag":532,"props":19997,"children":19998},{"style":545},[19999],{"type":420,"value":18873},{"type":415,"tag":532,"props":20001,"children":20002},{"class":534,"line":566},[20003,20008,20013,20017],{"type":415,"tag":532,"props":20004,"children":20005},{"style":954},[20006],{"type":420,"value":20007},"readonly",{"type":415,"tag":532,"props":20009,"children":20010},{"style":631},[20011],{"type":420,"value":20012}," Solution",{"type":415,"tag":532,"props":20014,"children":20015},{"style":631},[20016],{"type":420,"value":20012},{"type":415,"tag":532,"props":20018,"children":20019},{"style":551},[20020],{"type":420,"value":563},{"type":415,"tag":20022,"props":20023,"children":20025},"calout",{"icon":20024},"i-fluent-emoji-magic-wand",[20026],{"type":415,"tag":416,"props":20027,"children":20028},{},[20029,20031,20038],{"type":420,"value":20030},"It looks like magic but it's not! Nuke uses a ",{"type":415,"tag":423,"props":20032,"children":20035},{"href":20033,"rel":20034},"https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview",[427],[20036],{"type":420,"value":20037},"source generator",{"type":420,"value":20039},"  to do that behind the scenes.",{"type":415,"tag":482,"props":20041,"children":20043},{"id":20042},"provisioning-the-app-service-with-pulumi",[20044],{"type":420,"value":20045},"Provisioning the App Service with Pulumi",{"type":415,"tag":3914,"props":20047,"children":20049},{"id":20048},"the-pulumi-project",[20050],{"type":420,"value":20051},"The Pulumi project",{"type":415,"tag":416,"props":20053,"children":20054},{},[20055,20057,20063,20065,20071],{"type":420,"value":20056},"By default, the infrastructure code is contained in the ",{"type":415,"tag":468,"props":20058,"children":20060},{"className":20059},[],[20061],{"type":420,"value":20062},"Program.cs",{"type":420,"value":20064}," file of our project. The resources to provision are declared in the lambda in parameter of the ",{"type":415,"tag":468,"props":20066,"children":20068},{"className":20067},[],[20069],{"type":420,"value":20070},"Deployment.RunAsync",{"type":420,"value":1766},{"type":415,"tag":416,"props":20073,"children":20074},{},[20075],{"type":415,"tag":3882,"props":20076,"children":20080},{"alt":20077,"className":20078,"src":20079},"Pulumi program file opened in the IDE.",[3886,3887],"/posts/images/pulumi_met_nuke_10.png",[],{"type":415,"tag":434,"props":20082,"children":20083},{"icon":1382},[20084],{"type":415,"tag":416,"props":20085,"children":20086},{},[20087],{"type":420,"value":20088},"The project uses the top-level statement feature of C#.",{"type":415,"tag":416,"props":20090,"children":20091},{},[20092,20094,20099],{"type":420,"value":20093},"As we don't have many resources to declare for our scenario we will keep all the code in the ",{"type":415,"tag":468,"props":20095,"children":20097},{"className":20096},[],[20098],{"type":420,"value":20062},{"type":420,"value":20100}," file but that is not what you would do in a more complex project.",{"type":415,"tag":3914,"props":20102,"children":20104},{"id":20103},"azure-resources-to-provision",[20105],{"type":420,"value":20106},"Azure resources to provision",{"type":415,"tag":416,"props":20108,"children":20109},{},[20110],{"type":420,"value":20111},"There are 3 Azure resources we need to create in our stack (instance of a Pulumi program):",{"type":415,"tag":508,"props":20113,"children":20114},{},[20115,20120,20132],{"type":415,"tag":512,"props":20116,"children":20117},{},[20118],{"type":420,"value":20119},"a resource group to contain the different Azure resources",{"type":415,"tag":512,"props":20121,"children":20122},{},[20123,20125],{"type":420,"value":20124},"an App Service Plan which ",{"type":415,"tag":423,"props":20126,"children":20129},{"href":20127,"rel":20128},"https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans",[427],[20130],{"type":420,"value":20131},"defines the set of compute resources for a web app to run",{"type":415,"tag":512,"props":20133,"children":20134},{},[20135],{"type":420,"value":20136},"a Web App / App Service which is where the API will be deployed",{"type":415,"tag":523,"props":20138,"children":20140},{"className":525,"code":20139,"language":326,"meta":401,"style":401},"var resourceGroup = new ResourceGroup($\"rg-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\");  \n  \nvar appServicePlan = new AppServicePlan($\"plan-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\", new AppServicePlanArgs  \n{  \n    ResourceGroupName = resourceGroup.Name,  \n    Kind = \"App\",  \n    Sku = new SkuDescriptionArgs  \n    {  \n        Tier = \"Basic\",  \n        Name = \"B1\",  \n    },  \n});  \n  \nvar appService = new WebApp($\"app-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\", new WebAppArgs   \n{   \n    ResourceGroupName = resourceGroup.Name,  \n    ServerFarmId = appServicePlan.Id  \n});\n",[20141],{"type":415,"tag":468,"props":20142,"children":20143},{"__ignoreMap":401},[20144,20254,20261,20376,20387,20419,20452,20477,20488,20521,20554,20566,20578,20585,20701,20712,20743,20768],{"type":415,"tag":532,"props":20145,"children":20146},{"class":534,"line":535},[20147,20151,20156,20160,20164,20169,20173,20177,20182,20186,20191,20195,20200,20204,20209,20213,20217,20221,20225,20229,20233,20237,20242,20246,20250],{"type":415,"tag":532,"props":20148,"children":20149},{"style":631},[20150],{"type":420,"value":634},{"type":415,"tag":532,"props":20152,"children":20153},{"style":631},[20154],{"type":420,"value":20155}," resourceGroup",{"type":415,"tag":532,"props":20157,"children":20158},{"style":551},[20159],{"type":420,"value":644},{"type":415,"tag":532,"props":20161,"children":20162},{"style":551},[20163],{"type":420,"value":3276},{"type":415,"tag":532,"props":20165,"children":20166},{"style":631},[20167],{"type":420,"value":20168}," ResourceGroup",{"type":415,"tag":532,"props":20170,"children":20171},{"style":551},[20172],{"type":420,"value":664},{"type":415,"tag":532,"props":20174,"children":20175},{"style":551},[20176],{"type":420,"value":8738},{"type":415,"tag":532,"props":20178,"children":20179},{"style":804},[20180],{"type":420,"value":20181},"rg-",{"type":415,"tag":532,"props":20183,"children":20184},{"style":551},[20185],{"type":420,"value":8748},{"type":415,"tag":532,"props":20187,"children":20188},{"style":545},[20189],{"type":420,"value":20190},"Deployment",{"type":415,"tag":532,"props":20192,"children":20193},{"style":551},[20194],{"type":420,"value":432},{"type":415,"tag":532,"props":20196,"children":20197},{"style":545},[20198],{"type":420,"value":20199},"Instance",{"type":415,"tag":532,"props":20201,"children":20202},{"style":551},[20203],{"type":420,"value":432},{"type":415,"tag":532,"props":20205,"children":20206},{"style":545},[20207],{"type":420,"value":20208},"ProjectName",{"type":415,"tag":532,"props":20210,"children":20211},{"style":551},[20212],{"type":420,"value":4864},{"type":415,"tag":532,"props":20214,"children":20215},{"style":804},[20216],{"type":420,"value":4216},{"type":415,"tag":532,"props":20218,"children":20219},{"style":551},[20220],{"type":420,"value":8748},{"type":415,"tag":532,"props":20222,"children":20223},{"style":545},[20224],{"type":420,"value":20190},{"type":415,"tag":532,"props":20226,"children":20227},{"style":551},[20228],{"type":420,"value":432},{"type":415,"tag":532,"props":20230,"children":20231},{"style":545},[20232],{"type":420,"value":20199},{"type":415,"tag":532,"props":20234,"children":20235},{"style":551},[20236],{"type":420,"value":432},{"type":415,"tag":532,"props":20238,"children":20239},{"style":545},[20240],{"type":420,"value":20241},"StackName",{"type":415,"tag":532,"props":20243,"children":20244},{"style":551},[20245],{"type":420,"value":4502},{"type":415,"tag":532,"props":20247,"children":20248},{"style":551},[20249],{"type":420,"value":18984},{"type":415,"tag":532,"props":20251,"children":20252},{"style":545},[20253],{"type":420,"value":18873},{"type":415,"tag":532,"props":20255,"children":20256},{"class":534,"line":566},[20257],{"type":415,"tag":532,"props":20258,"children":20259},{"style":545},[20260],{"type":420,"value":18873},{"type":415,"tag":532,"props":20262,"children":20263},{"class":534,"line":583},[20264,20268,20273,20277,20281,20286,20290,20294,20299,20303,20307,20311,20315,20319,20323,20327,20331,20335,20339,20343,20347,20351,20355,20359,20363,20367,20372],{"type":415,"tag":532,"props":20265,"children":20266},{"style":631},[20267],{"type":420,"value":634},{"type":415,"tag":532,"props":20269,"children":20270},{"style":631},[20271],{"type":420,"value":20272}," appServicePlan",{"type":415,"tag":532,"props":20274,"children":20275},{"style":551},[20276],{"type":420,"value":644},{"type":415,"tag":532,"props":20278,"children":20279},{"style":551},[20280],{"type":420,"value":3276},{"type":415,"tag":532,"props":20282,"children":20283},{"style":631},[20284],{"type":420,"value":20285}," AppServicePlan",{"type":415,"tag":532,"props":20287,"children":20288},{"style":551},[20289],{"type":420,"value":664},{"type":415,"tag":532,"props":20291,"children":20292},{"style":551},[20293],{"type":420,"value":8738},{"type":415,"tag":532,"props":20295,"children":20296},{"style":804},[20297],{"type":420,"value":20298},"plan-",{"type":415,"tag":532,"props":20300,"children":20301},{"style":551},[20302],{"type":420,"value":8748},{"type":415,"tag":532,"props":20304,"children":20305},{"style":545},[20306],{"type":420,"value":20190},{"type":415,"tag":532,"props":20308,"children":20309},{"style":551},[20310],{"type":420,"value":432},{"type":415,"tag":532,"props":20312,"children":20313},{"style":545},[20314],{"type":420,"value":20199},{"type":415,"tag":532,"props":20316,"children":20317},{"style":551},[20318],{"type":420,"value":432},{"type":415,"tag":532,"props":20320,"children":20321},{"style":545},[20322],{"type":420,"value":20208},{"type":415,"tag":532,"props":20324,"children":20325},{"style":551},[20326],{"type":420,"value":4864},{"type":415,"tag":532,"props":20328,"children":20329},{"style":804},[20330],{"type":420,"value":4216},{"type":415,"tag":532,"props":20332,"children":20333},{"style":551},[20334],{"type":420,"value":8748},{"type":415,"tag":532,"props":20336,"children":20337},{"style":545},[20338],{"type":420,"value":20190},{"type":415,"tag":532,"props":20340,"children":20341},{"style":551},[20342],{"type":420,"value":432},{"type":415,"tag":532,"props":20344,"children":20345},{"style":545},[20346],{"type":420,"value":20199},{"type":415,"tag":532,"props":20348,"children":20349},{"style":551},[20350],{"type":420,"value":432},{"type":415,"tag":532,"props":20352,"children":20353},{"style":545},[20354],{"type":420,"value":20241},{"type":415,"tag":532,"props":20356,"children":20357},{"style":551},[20358],{"type":420,"value":4502},{"type":415,"tag":532,"props":20360,"children":20361},{"style":551},[20362],{"type":420,"value":1099},{"type":415,"tag":532,"props":20364,"children":20365},{"style":551},[20366],{"type":420,"value":3276},{"type":415,"tag":532,"props":20368,"children":20369},{"style":631},[20370],{"type":420,"value":20371}," AppServicePlanArgs",{"type":415,"tag":532,"props":20373,"children":20374},{"style":545},[20375],{"type":420,"value":18873},{"type":415,"tag":532,"props":20377,"children":20378},{"class":534,"line":617},[20379,20383],{"type":415,"tag":532,"props":20380,"children":20381},{"style":551},[20382],{"type":420,"value":8748},{"type":415,"tag":532,"props":20384,"children":20385},{"style":545},[20386],{"type":420,"value":18873},{"type":415,"tag":532,"props":20388,"children":20389},{"class":534,"line":627},[20390,20395,20399,20403,20407,20411,20415],{"type":415,"tag":532,"props":20391,"children":20392},{"style":545},[20393],{"type":420,"value":20394},"    ResourceGroupName ",{"type":415,"tag":532,"props":20396,"children":20397},{"style":551},[20398],{"type":420,"value":1134},{"type":415,"tag":532,"props":20400,"children":20401},{"style":545},[20402],{"type":420,"value":20155},{"type":415,"tag":532,"props":20404,"children":20405},{"style":551},[20406],{"type":420,"value":432},{"type":415,"tag":532,"props":20408,"children":20409},{"style":545},[20410],{"type":420,"value":1344},{"type":415,"tag":532,"props":20412,"children":20413},{"style":551},[20414],{"type":420,"value":1099},{"type":415,"tag":532,"props":20416,"children":20417},{"style":545},[20418],{"type":420,"value":18873},{"type":415,"tag":532,"props":20420,"children":20421},{"class":534,"line":677},[20422,20427,20431,20435,20440,20444,20448],{"type":415,"tag":532,"props":20423,"children":20424},{"style":545},[20425],{"type":420,"value":20426},"    Kind ",{"type":415,"tag":532,"props":20428,"children":20429},{"style":551},[20430],{"type":420,"value":1134},{"type":415,"tag":532,"props":20432,"children":20433},{"style":551},[20434],{"type":420,"value":4041},{"type":415,"tag":532,"props":20436,"children":20437},{"style":804},[20438],{"type":420,"value":20439},"App",{"type":415,"tag":532,"props":20441,"children":20442},{"style":551},[20443],{"type":420,"value":801},{"type":415,"tag":532,"props":20445,"children":20446},{"style":551},[20447],{"type":420,"value":1099},{"type":415,"tag":532,"props":20449,"children":20450},{"style":545},[20451],{"type":420,"value":18873},{"type":415,"tag":532,"props":20453,"children":20454},{"class":534,"line":719},[20455,20460,20464,20468,20473],{"type":415,"tag":532,"props":20456,"children":20457},{"style":545},[20458],{"type":420,"value":20459},"    Sku ",{"type":415,"tag":532,"props":20461,"children":20462},{"style":551},[20463],{"type":420,"value":1134},{"type":415,"tag":532,"props":20465,"children":20466},{"style":551},[20467],{"type":420,"value":3276},{"type":415,"tag":532,"props":20469,"children":20470},{"style":631},[20471],{"type":420,"value":20472}," SkuDescriptionArgs",{"type":415,"tag":532,"props":20474,"children":20475},{"style":545},[20476],{"type":420,"value":18873},{"type":415,"tag":532,"props":20478,"children":20479},{"class":534,"line":758},[20480,20484],{"type":415,"tag":532,"props":20481,"children":20482},{"style":551},[20483],{"type":420,"value":18906},{"type":415,"tag":532,"props":20485,"children":20486},{"style":545},[20487],{"type":420,"value":18873},{"type":415,"tag":532,"props":20489,"children":20490},{"class":534,"line":767},[20491,20496,20500,20504,20509,20513,20517],{"type":415,"tag":532,"props":20492,"children":20493},{"style":545},[20494],{"type":420,"value":20495},"        Tier ",{"type":415,"tag":532,"props":20497,"children":20498},{"style":551},[20499],{"type":420,"value":1134},{"type":415,"tag":532,"props":20501,"children":20502},{"style":551},[20503],{"type":420,"value":4041},{"type":415,"tag":532,"props":20505,"children":20506},{"style":804},[20507],{"type":420,"value":20508},"Basic",{"type":415,"tag":532,"props":20510,"children":20511},{"style":551},[20512],{"type":420,"value":801},{"type":415,"tag":532,"props":20514,"children":20515},{"style":551},[20516],{"type":420,"value":1099},{"type":415,"tag":532,"props":20518,"children":20519},{"style":545},[20520],{"type":420,"value":18873},{"type":415,"tag":532,"props":20522,"children":20523},{"class":534,"line":819},[20524,20529,20533,20537,20542,20546,20550],{"type":415,"tag":532,"props":20525,"children":20526},{"style":545},[20527],{"type":420,"value":20528},"        Name ",{"type":415,"tag":532,"props":20530,"children":20531},{"style":551},[20532],{"type":420,"value":1134},{"type":415,"tag":532,"props":20534,"children":20535},{"style":551},[20536],{"type":420,"value":4041},{"type":415,"tag":532,"props":20538,"children":20539},{"style":804},[20540],{"type":420,"value":20541},"B1",{"type":415,"tag":532,"props":20543,"children":20544},{"style":551},[20545],{"type":420,"value":801},{"type":415,"tag":532,"props":20547,"children":20548},{"style":551},[20549],{"type":420,"value":1099},{"type":415,"tag":532,"props":20551,"children":20552},{"style":545},[20553],{"type":420,"value":18873},{"type":415,"tag":532,"props":20555,"children":20556},{"class":534,"line":850},[20557,20562],{"type":415,"tag":532,"props":20558,"children":20559},{"style":551},[20560],{"type":420,"value":20561},"    },",{"type":415,"tag":532,"props":20563,"children":20564},{"style":545},[20565],{"type":420,"value":18873},{"type":415,"tag":532,"props":20567,"children":20568},{"class":534,"line":859},[20569,20574],{"type":415,"tag":532,"props":20570,"children":20571},{"style":551},[20572],{"type":420,"value":20573},"});",{"type":415,"tag":532,"props":20575,"children":20576},{"style":545},[20577],{"type":420,"value":18873},{"type":415,"tag":532,"props":20579,"children":20580},{"class":534,"line":867},[20581],{"type":415,"tag":532,"props":20582,"children":20583},{"style":545},[20584],{"type":420,"value":18873},{"type":415,"tag":532,"props":20586,"children":20587},{"class":534,"line":902},[20588,20592,20597,20601,20605,20610,20614,20618,20623,20627,20631,20635,20639,20643,20647,20651,20655,20659,20663,20667,20671,20675,20679,20683,20687,20691,20696],{"type":415,"tag":532,"props":20589,"children":20590},{"style":631},[20591],{"type":420,"value":634},{"type":415,"tag":532,"props":20593,"children":20594},{"style":631},[20595],{"type":420,"value":20596}," appService",{"type":415,"tag":532,"props":20598,"children":20599},{"style":551},[20600],{"type":420,"value":644},{"type":415,"tag":532,"props":20602,"children":20603},{"style":551},[20604],{"type":420,"value":3276},{"type":415,"tag":532,"props":20606,"children":20607},{"style":631},[20608],{"type":420,"value":20609}," WebApp",{"type":415,"tag":532,"props":20611,"children":20612},{"style":551},[20613],{"type":420,"value":664},{"type":415,"tag":532,"props":20615,"children":20616},{"style":551},[20617],{"type":420,"value":8738},{"type":415,"tag":532,"props":20619,"children":20620},{"style":804},[20621],{"type":420,"value":20622},"app-",{"type":415,"tag":532,"props":20624,"children":20625},{"style":551},[20626],{"type":420,"value":8748},{"type":415,"tag":532,"props":20628,"children":20629},{"style":545},[20630],{"type":420,"value":20190},{"type":415,"tag":532,"props":20632,"children":20633},{"style":551},[20634],{"type":420,"value":432},{"type":415,"tag":532,"props":20636,"children":20637},{"style":545},[20638],{"type":420,"value":20199},{"type":415,"tag":532,"props":20640,"children":20641},{"style":551},[20642],{"type":420,"value":432},{"type":415,"tag":532,"props":20644,"children":20645},{"style":545},[20646],{"type":420,"value":20208},{"type":415,"tag":532,"props":20648,"children":20649},{"style":551},[20650],{"type":420,"value":4864},{"type":415,"tag":532,"props":20652,"children":20653},{"style":804},[20654],{"type":420,"value":4216},{"type":415,"tag":532,"props":20656,"children":20657},{"style":551},[20658],{"type":420,"value":8748},{"type":415,"tag":532,"props":20660,"children":20661},{"style":545},[20662],{"type":420,"value":20190},{"type":415,"tag":532,"props":20664,"children":20665},{"style":551},[20666],{"type":420,"value":432},{"type":415,"tag":532,"props":20668,"children":20669},{"style":545},[20670],{"type":420,"value":20199},{"type":415,"tag":532,"props":20672,"children":20673},{"style":551},[20674],{"type":420,"value":432},{"type":415,"tag":532,"props":20676,"children":20677},{"style":545},[20678],{"type":420,"value":20241},{"type":415,"tag":532,"props":20680,"children":20681},{"style":551},[20682],{"type":420,"value":4502},{"type":415,"tag":532,"props":20684,"children":20685},{"style":551},[20686],{"type":420,"value":1099},{"type":415,"tag":532,"props":20688,"children":20689},{"style":551},[20690],{"type":420,"value":3276},{"type":415,"tag":532,"props":20692,"children":20693},{"style":631},[20694],{"type":420,"value":20695}," WebAppArgs",{"type":415,"tag":532,"props":20697,"children":20698},{"style":545},[20699],{"type":420,"value":20700},"   \n",{"type":415,"tag":532,"props":20702,"children":20703},{"class":534,"line":1302},[20704,20708],{"type":415,"tag":532,"props":20705,"children":20706},{"style":551},[20707],{"type":420,"value":8748},{"type":415,"tag":532,"props":20709,"children":20710},{"style":545},[20711],{"type":420,"value":20700},{"type":415,"tag":532,"props":20713,"children":20714},{"class":534,"line":1311},[20715,20719,20723,20727,20731,20735,20739],{"type":415,"tag":532,"props":20716,"children":20717},{"style":545},[20718],{"type":420,"value":20394},{"type":415,"tag":532,"props":20720,"children":20721},{"style":551},[20722],{"type":420,"value":1134},{"type":415,"tag":532,"props":20724,"children":20725},{"style":545},[20726],{"type":420,"value":20155},{"type":415,"tag":532,"props":20728,"children":20729},{"style":551},[20730],{"type":420,"value":432},{"type":415,"tag":532,"props":20732,"children":20733},{"style":545},[20734],{"type":420,"value":1344},{"type":415,"tag":532,"props":20736,"children":20737},{"style":551},[20738],{"type":420,"value":1099},{"type":415,"tag":532,"props":20740,"children":20741},{"style":545},[20742],{"type":420,"value":18873},{"type":415,"tag":532,"props":20744,"children":20745},{"class":534,"line":1356},[20746,20751,20755,20759,20763],{"type":415,"tag":532,"props":20747,"children":20748},{"style":545},[20749],{"type":420,"value":20750},"    ServerFarmId ",{"type":415,"tag":532,"props":20752,"children":20753},{"style":551},[20754],{"type":420,"value":1134},{"type":415,"tag":532,"props":20756,"children":20757},{"style":545},[20758],{"type":420,"value":20272},{"type":415,"tag":532,"props":20760,"children":20761},{"style":551},[20762],{"type":420,"value":432},{"type":415,"tag":532,"props":20764,"children":20765},{"style":545},[20766],{"type":420,"value":20767},"Id  \n",{"type":415,"tag":532,"props":20769,"children":20770},{"class":534,"line":1365},[20771],{"type":415,"tag":532,"props":20772,"children":20773},{"style":551},[20774],{"type":420,"value":856},{"type":415,"tag":416,"props":20776,"children":20777},{},[20778],{"type":420,"value":20779},"The code is quite simple, and because we are writing C# in our IDE, we have autocompletion and everything we need to make writing the infrastructure code easier.",{"type":415,"tag":434,"props":20781,"children":20782},{"icon":436},[20783],{"type":415,"tag":416,"props":20784,"children":20785},{},[20786],{"type":420,"value":20787},"If you are used to Azure Bicep or ARM templates, the names of the classes or properties will look familiar to you. It's because we are using Azure Native, which is a Pulumi native provider that is generated from Azure APIs.",{"type":415,"tag":3914,"props":20789,"children":20791},{"id":20790},"stack-outputs",[20792],{"type":420,"value":20793},"Stack outputs",{"type":415,"tag":416,"props":20795,"children":20796},{},[20797],{"type":420,"value":20798},"Provisioning the cloud resources we need is great but we have to think about the next step which is to deploy our API on these resources. So what will we need for that?",{"type":415,"tag":416,"props":20800,"children":20801},{},[20802,20804,20810],{"type":420,"value":20803},"First, we will need to have the name of the provisioned App Service. That's easy it's the property Name of the ",{"type":415,"tag":468,"props":20805,"children":20807},{"className":20806},[],[20808],{"type":420,"value":20809},"appService",{"type":420,"value":20811}," variable.",{"type":415,"tag":416,"props":20813,"children":20814},{},[20815,20817,20824],{"type":420,"value":20816},"Second, because we are going to use the Kudu API to zip deploy our application to the App Service, we will need the ",{"type":415,"tag":423,"props":20818,"children":20821},{"href":20819,"rel":20820},"https://github.com/projectkudu/kudu/wiki/Deployment-credentials#site-credentials-aka-publish-profile-credentials",[427],[20822],{"type":420,"value":20823},"site credentials (aka the Publishing Profile Credentials)",{"type":420,"value":20825},". These can be retrieved in the Pulumi program using the following code:",{"type":415,"tag":523,"props":20827,"children":20829},{"className":525,"code":20828,"language":326,"meta":401,"style":401},"var publishingCredentials = ListWebAppPublishingCredentials.Invoke(new()  \n{  \n    ResourceGroupName = resourceGroup.Name,  \n    Name = appService.Name  \n});\n",[20830],{"type":415,"tag":468,"props":20831,"children":20832},{"__ignoreMap":401},[20833,20871,20882,20913,20937],{"type":415,"tag":532,"props":20834,"children":20835},{"class":534,"line":535},[20836,20840,20845,20849,20854,20858,20862,20867],{"type":415,"tag":532,"props":20837,"children":20838},{"style":631},[20839],{"type":420,"value":634},{"type":415,"tag":532,"props":20841,"children":20842},{"style":631},[20843],{"type":420,"value":20844}," publishingCredentials",{"type":415,"tag":532,"props":20846,"children":20847},{"style":551},[20848],{"type":420,"value":644},{"type":415,"tag":532,"props":20850,"children":20851},{"style":545},[20852],{"type":420,"value":20853}," ListWebAppPublishingCredentials",{"type":415,"tag":532,"props":20855,"children":20856},{"style":551},[20857],{"type":420,"value":432},{"type":415,"tag":532,"props":20859,"children":20860},{"style":656},[20861],{"type":420,"value":7713},{"type":415,"tag":532,"props":20863,"children":20864},{"style":551},[20865],{"type":420,"value":20866},"(new()",{"type":415,"tag":532,"props":20868,"children":20869},{"style":545},[20870],{"type":420,"value":18873},{"type":415,"tag":532,"props":20872,"children":20873},{"class":534,"line":566},[20874,20878],{"type":415,"tag":532,"props":20875,"children":20876},{"style":551},[20877],{"type":420,"value":8748},{"type":415,"tag":532,"props":20879,"children":20880},{"style":545},[20881],{"type":420,"value":18873},{"type":415,"tag":532,"props":20883,"children":20884},{"class":534,"line":583},[20885,20889,20893,20897,20901,20905,20909],{"type":415,"tag":532,"props":20886,"children":20887},{"style":545},[20888],{"type":420,"value":20394},{"type":415,"tag":532,"props":20890,"children":20891},{"style":551},[20892],{"type":420,"value":1134},{"type":415,"tag":532,"props":20894,"children":20895},{"style":545},[20896],{"type":420,"value":20155},{"type":415,"tag":532,"props":20898,"children":20899},{"style":551},[20900],{"type":420,"value":432},{"type":415,"tag":532,"props":20902,"children":20903},{"style":545},[20904],{"type":420,"value":1344},{"type":415,"tag":532,"props":20906,"children":20907},{"style":551},[20908],{"type":420,"value":1099},{"type":415,"tag":532,"props":20910,"children":20911},{"style":545},[20912],{"type":420,"value":18873},{"type":415,"tag":532,"props":20914,"children":20915},{"class":534,"line":617},[20916,20920,20924,20928,20932],{"type":415,"tag":532,"props":20917,"children":20918},{"style":545},[20919],{"type":420,"value":7762},{"type":415,"tag":532,"props":20921,"children":20922},{"style":551},[20923],{"type":420,"value":1134},{"type":415,"tag":532,"props":20925,"children":20926},{"style":545},[20927],{"type":420,"value":20596},{"type":415,"tag":532,"props":20929,"children":20930},{"style":551},[20931],{"type":420,"value":432},{"type":415,"tag":532,"props":20933,"children":20934},{"style":545},[20935],{"type":420,"value":20936},"Name  \n",{"type":415,"tag":532,"props":20938,"children":20939},{"class":534,"line":627},[20940],{"type":415,"tag":532,"props":20941,"children":20942},{"style":551},[20943],{"type":420,"value":856},{"type":415,"tag":434,"props":20945,"children":20946},{"icon":1382},[20947],{"type":415,"tag":416,"props":20948,"children":20949},{},[20950,20952,20959],{"type":420,"value":20951},"Using the Kudu API is just one of the ",{"type":415,"tag":423,"props":20953,"children":20956},{"href":20954,"rel":20955},"https://learn.microsoft.com/en-us/azure/app-service/deploy-zip?tabs=cli#deploy-a-zip-package",[427],[20957],{"type":420,"value":20958},"many ways",{"type":420,"value":20960}," to deploy a zip package to an App Service. I could have chosen another way like using the Azure CLI, in that case retrieving the site credentials would not have been needed.",{"type":415,"tag":416,"props":20962,"children":20963},{},[20964,20966,20972],{"type":420,"value":20965},"Pulumi, like Terraform, has this concept of stack ",{"type":415,"tag":423,"props":20967,"children":20970},{"href":20968,"rel":20969},"https://www.pulumi.com/docs/intro/concepts/stack/#outputs",[427],[20971],{"type":420,"value":11926},{"type":420,"value":20973},"  where outputs are information about your stack/infrastructure that you want to expose. That is exactly what we need to export our App Service name and our site credentials so that they can be retrieved later by the Nuke code that will take care of the application deployment. To export these values we can return them in a Dictionary like that:",{"type":415,"tag":523,"props":20975,"children":20977},{"className":525,"code":20976,"language":326,"meta":401,"style":401},"return new Dictionary\u003Cstring, object?>  \n{  \n    [\"publishingUsername\"] = Output.CreateSecret(publishingCredentials.Apply(c => c.PublishingUserName)),  \n    [\"publishingUserPassword\"] = Output.CreateSecret(publishingCredentials.Apply(c => c.PublishingPassword)),  \n    [\"appServiceName\"] = appService.Name  \n};\n",[20978],{"type":415,"tag":468,"props":20979,"children":20980},{"__ignoreMap":401},[20981,21017,21028,21120,21209,21249],{"type":415,"tag":532,"props":20982,"children":20983},{"class":534,"line":535},[20984,20988,20992,20996,21000,21004,21008,21013],{"type":415,"tag":532,"props":20985,"children":20986},{"style":1241},[20987],{"type":420,"value":10680},{"type":415,"tag":532,"props":20989,"children":20990},{"style":551},[20991],{"type":420,"value":3276},{"type":415,"tag":532,"props":20993,"children":20994},{"style":631},[20995],{"type":420,"value":10689},{"type":415,"tag":532,"props":20997,"children":20998},{"style":551},[20999],{"type":420,"value":706},{"type":415,"tag":532,"props":21001,"children":21002},{"style":551},[21003],{"type":420,"value":10698},{"type":415,"tag":532,"props":21005,"children":21006},{"style":551},[21007],{"type":420,"value":1099},{"type":415,"tag":532,"props":21009,"children":21010},{"style":551},[21011],{"type":420,"value":21012}," object?>",{"type":415,"tag":532,"props":21014,"children":21015},{"style":545},[21016],{"type":420,"value":18873},{"type":415,"tag":532,"props":21018,"children":21019},{"class":534,"line":566},[21020,21024],{"type":415,"tag":532,"props":21021,"children":21022},{"style":551},[21023],{"type":420,"value":8748},{"type":415,"tag":532,"props":21025,"children":21026},{"style":545},[21027],{"type":420,"value":18873},{"type":415,"tag":532,"props":21029,"children":21030},{"class":534,"line":583},[21031,21035,21039,21044,21048,21052,21056,21060,21064,21069,21073,21078,21082,21086,21090,21094,21098,21102,21106,21111,21116],{"type":415,"tag":532,"props":21032,"children":21033},{"style":551},[21034],{"type":420,"value":10722},{"type":415,"tag":532,"props":21036,"children":21037},{"style":551},[21038],{"type":420,"value":801},{"type":415,"tag":532,"props":21040,"children":21041},{"style":804},[21042],{"type":420,"value":21043},"publishingUsername",{"type":415,"tag":532,"props":21045,"children":21046},{"style":551},[21047],{"type":420,"value":801},{"type":415,"tag":532,"props":21049,"children":21050},{"style":551},[21051],{"type":420,"value":7449},{"type":415,"tag":532,"props":21053,"children":21054},{"style":551},[21055],{"type":420,"value":644},{"type":415,"tag":532,"props":21057,"children":21058},{"style":545},[21059],{"type":420,"value":9284},{"type":415,"tag":532,"props":21061,"children":21062},{"style":551},[21063],{"type":420,"value":432},{"type":415,"tag":532,"props":21065,"children":21066},{"style":656},[21067],{"type":420,"value":21068},"CreateSecret",{"type":415,"tag":532,"props":21070,"children":21071},{"style":551},[21072],{"type":420,"value":664},{"type":415,"tag":532,"props":21074,"children":21075},{"style":545},[21076],{"type":420,"value":21077},"publishingCredentials",{"type":415,"tag":532,"props":21079,"children":21080},{"style":551},[21081],{"type":420,"value":432},{"type":415,"tag":532,"props":21083,"children":21084},{"style":656},[21085],{"type":420,"value":8485},{"type":415,"tag":532,"props":21087,"children":21088},{"style":551},[21089],{"type":420,"value":664},{"type":415,"tag":532,"props":21091,"children":21092},{"style":631},[21093],{"type":420,"value":8494},{"type":415,"tag":532,"props":21095,"children":21096},{"style":551},[21097],{"type":420,"value":8499},{"type":415,"tag":532,"props":21099,"children":21100},{"style":545},[21101],{"type":420,"value":8504},{"type":415,"tag":532,"props":21103,"children":21104},{"style":551},[21105],{"type":420,"value":432},{"type":415,"tag":532,"props":21107,"children":21108},{"style":545},[21109],{"type":420,"value":21110},"PublishingUserName",{"type":415,"tag":532,"props":21112,"children":21113},{"style":551},[21114],{"type":420,"value":21115},")),",{"type":415,"tag":532,"props":21117,"children":21118},{"style":545},[21119],{"type":420,"value":18873},{"type":415,"tag":532,"props":21121,"children":21122},{"class":534,"line":617},[21123,21127,21131,21136,21140,21144,21148,21152,21156,21160,21164,21168,21172,21176,21180,21184,21188,21192,21196,21201,21205],{"type":415,"tag":532,"props":21124,"children":21125},{"style":551},[21126],{"type":420,"value":10722},{"type":415,"tag":532,"props":21128,"children":21129},{"style":551},[21130],{"type":420,"value":801},{"type":415,"tag":532,"props":21132,"children":21133},{"style":804},[21134],{"type":420,"value":21135},"publishingUserPassword",{"type":415,"tag":532,"props":21137,"children":21138},{"style":551},[21139],{"type":420,"value":801},{"type":415,"tag":532,"props":21141,"children":21142},{"style":551},[21143],{"type":420,"value":7449},{"type":415,"tag":532,"props":21145,"children":21146},{"style":551},[21147],{"type":420,"value":644},{"type":415,"tag":532,"props":21149,"children":21150},{"style":545},[21151],{"type":420,"value":9284},{"type":415,"tag":532,"props":21153,"children":21154},{"style":551},[21155],{"type":420,"value":432},{"type":415,"tag":532,"props":21157,"children":21158},{"style":656},[21159],{"type":420,"value":21068},{"type":415,"tag":532,"props":21161,"children":21162},{"style":551},[21163],{"type":420,"value":664},{"type":415,"tag":532,"props":21165,"children":21166},{"style":545},[21167],{"type":420,"value":21077},{"type":415,"tag":532,"props":21169,"children":21170},{"style":551},[21171],{"type":420,"value":432},{"type":415,"tag":532,"props":21173,"children":21174},{"style":656},[21175],{"type":420,"value":8485},{"type":415,"tag":532,"props":21177,"children":21178},{"style":551},[21179],{"type":420,"value":664},{"type":415,"tag":532,"props":21181,"children":21182},{"style":631},[21183],{"type":420,"value":8494},{"type":415,"tag":532,"props":21185,"children":21186},{"style":551},[21187],{"type":420,"value":8499},{"type":415,"tag":532,"props":21189,"children":21190},{"style":545},[21191],{"type":420,"value":8504},{"type":415,"tag":532,"props":21193,"children":21194},{"style":551},[21195],{"type":420,"value":432},{"type":415,"tag":532,"props":21197,"children":21198},{"style":545},[21199],{"type":420,"value":21200},"PublishingPassword",{"type":415,"tag":532,"props":21202,"children":21203},{"style":551},[21204],{"type":420,"value":21115},{"type":415,"tag":532,"props":21206,"children":21207},{"style":545},[21208],{"type":420,"value":18873},{"type":415,"tag":532,"props":21210,"children":21211},{"class":534,"line":627},[21212,21216,21220,21225,21229,21233,21237,21241,21245],{"type":415,"tag":532,"props":21213,"children":21214},{"style":551},[21215],{"type":420,"value":10722},{"type":415,"tag":532,"props":21217,"children":21218},{"style":551},[21219],{"type":420,"value":801},{"type":415,"tag":532,"props":21221,"children":21222},{"style":804},[21223],{"type":420,"value":21224},"appServiceName",{"type":415,"tag":532,"props":21226,"children":21227},{"style":551},[21228],{"type":420,"value":801},{"type":415,"tag":532,"props":21230,"children":21231},{"style":551},[21232],{"type":420,"value":7449},{"type":415,"tag":532,"props":21234,"children":21235},{"style":551},[21236],{"type":420,"value":644},{"type":415,"tag":532,"props":21238,"children":21239},{"style":545},[21240],{"type":420,"value":20596},{"type":415,"tag":532,"props":21242,"children":21243},{"style":551},[21244],{"type":420,"value":432},{"type":415,"tag":532,"props":21246,"children":21247},{"style":545},[21248],{"type":420,"value":20936},{"type":415,"tag":532,"props":21250,"children":21251},{"class":534,"line":677},[21252],{"type":415,"tag":532,"props":21253,"children":21254},{"style":551},[21255],{"type":420,"value":10828},{"type":415,"tag":416,"props":21257,"children":21258},{},[21259,21261,21267],{"type":420,"value":21260},"You might notice that we use the ",{"type":415,"tag":468,"props":21262,"children":21264},{"className":21263},[],[21265],{"type":420,"value":21266},"Output.CreateSecret",{"type":420,"value":21268}," method to create outputs for our publishing credentials. The aim is to tell Pulumi to treat these values as secrets, and that's what it will do by encrypting them in the state file for extra protection (that is not something Terraform does by the way).",{"type":415,"tag":3914,"props":21270,"children":21272},{"id":21271},"implementing-the-provision-infrastructure-step",[21273],{"type":420,"value":21274},"Implementing the Provision Infrastructure step",{"type":415,"tag":416,"props":21276,"children":21277},{},[21278,21280,21285],{"type":420,"value":21279},"To deploy the infrastructure, we can use the ",{"type":415,"tag":468,"props":21281,"children":21283},{"className":21282},[],[21284],{"type":420,"value":10839},{"type":420,"value":21286}," command. We will write the code in a fluent way as we did with the dotnet CLI:",{"type":415,"tag":523,"props":21288,"children":21290},{"className":525,"code":21289,"language":326,"meta":401,"style":401},"AbsolutePath InfrastructureDirectory => RootDirectory / \"infra\";\n\nTarget ProvisionInfra => _ => _  \n    .Description(\"Provision the infrastructure on Azure\")  \n    .Executes(() =>  \n    {  \n        PulumiTasks.PulumiUp(_ => _  \n            .SetCwd(InfrastructureDirectory)  \n            .SetStack(\"dev\")  \n            .EnableSkipPreview());  \n    });\n",[21291],{"type":415,"tag":468,"props":21292,"children":21293},{"__ignoreMap":401},[21294,21333,21340,21368,21405,21428,21439,21472,21500,21536,21556],{"type":415,"tag":532,"props":21295,"children":21296},{"class":534,"line":535},[21297,21301,21305,21309,21313,21317,21321,21325,21329],{"type":415,"tag":532,"props":21298,"children":21299},{"style":545},[21300],{"type":420,"value":19040},{"type":415,"tag":532,"props":21302,"children":21303},{"style":631},[21304],{"type":420,"value":19098},{"type":415,"tag":532,"props":21306,"children":21307},{"style":551},[21308],{"type":420,"value":8499},{"type":415,"tag":532,"props":21310,"children":21311},{"style":545},[21312],{"type":420,"value":19054},{"type":415,"tag":532,"props":21314,"children":21315},{"style":551},[21316],{"type":420,"value":4728},{"type":415,"tag":532,"props":21318,"children":21319},{"style":551},[21320],{"type":420,"value":4041},{"type":415,"tag":532,"props":21322,"children":21323},{"style":804},[21324],{"type":420,"value":19119},{"type":415,"tag":532,"props":21326,"children":21327},{"style":551},[21328],{"type":420,"value":801},{"type":415,"tag":532,"props":21330,"children":21331},{"style":551},[21332],{"type":420,"value":563},{"type":415,"tag":532,"props":21334,"children":21335},{"class":534,"line":566},[21336],{"type":415,"tag":532,"props":21337,"children":21338},{"emptyLinePlaceholder":621},[21339],{"type":420,"value":624},{"type":415,"tag":532,"props":21341,"children":21342},{"class":534,"line":583},[21343,21347,21352,21356,21360,21364],{"type":415,"tag":532,"props":21344,"children":21345},{"style":545},[21346],{"type":420,"value":18821},{"type":415,"tag":532,"props":21348,"children":21349},{"style":631},[21350],{"type":420,"value":21351},"ProvisionInfra",{"type":415,"tag":532,"props":21353,"children":21354},{"style":551},[21355],{"type":420,"value":8499},{"type":415,"tag":532,"props":21357,"children":21358},{"style":631},[21359],{"type":420,"value":3178},{"type":415,"tag":532,"props":21361,"children":21362},{"style":551},[21363],{"type":420,"value":8499},{"type":415,"tag":532,"props":21365,"children":21366},{"style":545},[21367],{"type":420,"value":18842},{"type":415,"tag":532,"props":21369,"children":21370},{"class":534,"line":617},[21371,21375,21380,21384,21388,21393,21397,21401],{"type":415,"tag":532,"props":21372,"children":21373},{"style":551},[21374],{"type":420,"value":18850},{"type":415,"tag":532,"props":21376,"children":21377},{"style":656},[21378],{"type":420,"value":21379},"Description",{"type":415,"tag":532,"props":21381,"children":21382},{"style":551},[21383],{"type":420,"value":664},{"type":415,"tag":532,"props":21385,"children":21386},{"style":551},[21387],{"type":420,"value":801},{"type":415,"tag":532,"props":21389,"children":21390},{"style":804},[21391],{"type":420,"value":21392},"Provision the infrastructure on Azure",{"type":415,"tag":532,"props":21394,"children":21395},{"style":551},[21396],{"type":420,"value":801},{"type":415,"tag":532,"props":21398,"children":21399},{"style":551},[21400],{"type":420,"value":1349},{"type":415,"tag":532,"props":21402,"children":21403},{"style":545},[21404],{"type":420,"value":18873},{"type":415,"tag":532,"props":21406,"children":21407},{"class":534,"line":627},[21408,21412,21416,21420,21424],{"type":415,"tag":532,"props":21409,"children":21410},{"style":551},[21411],{"type":420,"value":18850},{"type":415,"tag":532,"props":21413,"children":21414},{"style":656},[21415],{"type":420,"value":18885},{"type":415,"tag":532,"props":21417,"children":21418},{"style":551},[21419],{"type":420,"value":18890},{"type":415,"tag":532,"props":21421,"children":21422},{"style":551},[21423],{"type":420,"value":8499},{"type":415,"tag":532,"props":21425,"children":21426},{"style":545},[21427],{"type":420,"value":18873},{"type":415,"tag":532,"props":21429,"children":21430},{"class":534,"line":677},[21431,21435],{"type":415,"tag":532,"props":21432,"children":21433},{"style":551},[21434],{"type":420,"value":18906},{"type":415,"tag":532,"props":21436,"children":21437},{"style":545},[21438],{"type":420,"value":18873},{"type":415,"tag":532,"props":21440,"children":21441},{"class":534,"line":719},[21442,21447,21451,21456,21460,21464,21468],{"type":415,"tag":532,"props":21443,"children":21444},{"style":545},[21445],{"type":420,"value":21446},"        PulumiTasks",{"type":415,"tag":532,"props":21448,"children":21449},{"style":551},[21450],{"type":420,"value":432},{"type":415,"tag":532,"props":21452,"children":21453},{"style":656},[21454],{"type":420,"value":21455},"PulumiUp",{"type":415,"tag":532,"props":21457,"children":21458},{"style":551},[21459],{"type":420,"value":664},{"type":415,"tag":532,"props":21461,"children":21462},{"style":631},[21463],{"type":420,"value":3169},{"type":415,"tag":532,"props":21465,"children":21466},{"style":551},[21467],{"type":420,"value":8499},{"type":415,"tag":532,"props":21469,"children":21470},{"style":545},[21471],{"type":420,"value":18842},{"type":415,"tag":532,"props":21473,"children":21474},{"class":534,"line":758},[21475,21479,21484,21488,21492,21496],{"type":415,"tag":532,"props":21476,"children":21477},{"style":551},[21478],{"type":420,"value":3328},{"type":415,"tag":532,"props":21480,"children":21481},{"style":656},[21482],{"type":420,"value":21483},"SetCwd",{"type":415,"tag":532,"props":21485,"children":21486},{"style":551},[21487],{"type":420,"value":664},{"type":415,"tag":532,"props":21489,"children":21490},{"style":545},[21491],{"type":420,"value":19098},{"type":415,"tag":532,"props":21493,"children":21494},{"style":551},[21495],{"type":420,"value":1349},{"type":415,"tag":532,"props":21497,"children":21498},{"style":545},[21499],{"type":420,"value":18873},{"type":415,"tag":532,"props":21501,"children":21502},{"class":534,"line":767},[21503,21507,21512,21516,21520,21524,21528,21532],{"type":415,"tag":532,"props":21504,"children":21505},{"style":551},[21506],{"type":420,"value":3328},{"type":415,"tag":532,"props":21508,"children":21509},{"style":656},[21510],{"type":420,"value":21511},"SetStack",{"type":415,"tag":532,"props":21513,"children":21514},{"style":551},[21515],{"type":420,"value":664},{"type":415,"tag":532,"props":21517,"children":21518},{"style":551},[21519],{"type":420,"value":801},{"type":415,"tag":532,"props":21521,"children":21522},{"style":804},[21523],{"type":420,"value":7074},{"type":415,"tag":532,"props":21525,"children":21526},{"style":551},[21527],{"type":420,"value":801},{"type":415,"tag":532,"props":21529,"children":21530},{"style":551},[21531],{"type":420,"value":1349},{"type":415,"tag":532,"props":21533,"children":21534},{"style":545},[21535],{"type":420,"value":18873},{"type":415,"tag":532,"props":21537,"children":21538},{"class":534,"line":819},[21539,21543,21548,21552],{"type":415,"tag":532,"props":21540,"children":21541},{"style":551},[21542],{"type":420,"value":3328},{"type":415,"tag":532,"props":21544,"children":21545},{"style":656},[21546],{"type":420,"value":21547},"EnableSkipPreview",{"type":415,"tag":532,"props":21549,"children":21550},{"style":551},[21551],{"type":420,"value":19558},{"type":415,"tag":532,"props":21553,"children":21554},{"style":545},[21555],{"type":420,"value":18873},{"type":415,"tag":532,"props":21557,"children":21558},{"class":534,"line":850},[21559],{"type":415,"tag":532,"props":21560,"children":21561},{"style":551},[21562],{"type":420,"value":2468},{"type":415,"tag":482,"props":21564,"children":21566},{"id":21565},"deploying-the-aspnet-core-api-to-azure-app-service",[21567],{"type":420,"value":21568},"Deploying the ASP.NET Core API to Azure App Service",{"type":415,"tag":416,"props":21570,"children":21571},{},[21572,21574,21580],{"type":420,"value":21573},"I previously said we were going to use the Kudu API to deploy our application. You can check the ",{"type":415,"tag":423,"props":21575,"children":21578},{"href":21576,"rel":21577},"https://github.com/projectkudu/kudu/wiki/Deploying-from-a-zip-file-or-url",[427],[21579],{"type":420,"value":499},{"type":420,"value":21581}," about that but concretely we will do a POST request to the zipdeploy endpoint using Basic authentication.",{"type":415,"tag":416,"props":21583,"children":21584},{},[21585,21587,21593],{"type":420,"value":21586},"To retrieve a stack output, we can use the ",{"type":415,"tag":468,"props":21588,"children":21590},{"className":21589},[],[21591],{"type":420,"value":21592},"pulumi stack output",{"type":420,"value":21594}," command. To avoid duplicating the code I wrote a short method:",{"type":415,"tag":523,"props":21596,"children":21598},{"className":525,"code":21597,"language":326,"meta":401,"style":401},"string GetPulumiOutput(string outputName)  \n{  \n    return PulumiTasks.PulumiStackOutput(_ => _  \n            .SetCwd(InfrastructureDirectory)  \n            .SetPropertyName(outputName)  \n            .EnableShowSecrets()\n            .DisableProcessLogOutput())  \n        .StdToText();  \n}\n",[21599],{"type":415,"tag":468,"props":21600,"children":21601},{"__ignoreMap":401},[21602,21635,21646,21683,21710,21739,21755,21775,21796],{"type":415,"tag":532,"props":21603,"children":21604},{"class":534,"line":535},[21605,21609,21614,21618,21622,21627,21631],{"type":415,"tag":532,"props":21606,"children":21607},{"style":551},[21608],{"type":420,"value":10698},{"type":415,"tag":532,"props":21610,"children":21611},{"style":656},[21612],{"type":420,"value":21613}," GetPulumiOutput",{"type":415,"tag":532,"props":21615,"children":21616},{"style":551},[21617],{"type":420,"value":664},{"type":415,"tag":532,"props":21619,"children":21620},{"style":551},[21621],{"type":420,"value":10698},{"type":415,"tag":532,"props":21623,"children":21624},{"style":631},[21625],{"type":420,"value":21626}," outputName",{"type":415,"tag":532,"props":21628,"children":21629},{"style":551},[21630],{"type":420,"value":1349},{"type":415,"tag":532,"props":21632,"children":21633},{"style":545},[21634],{"type":420,"value":18873},{"type":415,"tag":532,"props":21636,"children":21637},{"class":534,"line":566},[21638,21642],{"type":415,"tag":532,"props":21639,"children":21640},{"style":551},[21641],{"type":420,"value":8748},{"type":415,"tag":532,"props":21643,"children":21644},{"style":545},[21645],{"type":420,"value":18873},{"type":415,"tag":532,"props":21647,"children":21648},{"class":534,"line":583},[21649,21653,21658,21662,21667,21671,21675,21679],{"type":415,"tag":532,"props":21650,"children":21651},{"style":1241},[21652],{"type":420,"value":8778},{"type":415,"tag":532,"props":21654,"children":21655},{"style":545},[21656],{"type":420,"value":21657}," PulumiTasks",{"type":415,"tag":532,"props":21659,"children":21660},{"style":551},[21661],{"type":420,"value":432},{"type":415,"tag":532,"props":21663,"children":21664},{"style":656},[21665],{"type":420,"value":21666},"PulumiStackOutput",{"type":415,"tag":532,"props":21668,"children":21669},{"style":551},[21670],{"type":420,"value":664},{"type":415,"tag":532,"props":21672,"children":21673},{"style":631},[21674],{"type":420,"value":3169},{"type":415,"tag":532,"props":21676,"children":21677},{"style":551},[21678],{"type":420,"value":8499},{"type":415,"tag":532,"props":21680,"children":21681},{"style":545},[21682],{"type":420,"value":18842},{"type":415,"tag":532,"props":21684,"children":21685},{"class":534,"line":617},[21686,21690,21694,21698,21702,21706],{"type":415,"tag":532,"props":21687,"children":21688},{"style":551},[21689],{"type":420,"value":3328},{"type":415,"tag":532,"props":21691,"children":21692},{"style":656},[21693],{"type":420,"value":21483},{"type":415,"tag":532,"props":21695,"children":21696},{"style":551},[21697],{"type":420,"value":664},{"type":415,"tag":532,"props":21699,"children":21700},{"style":545},[21701],{"type":420,"value":19098},{"type":415,"tag":532,"props":21703,"children":21704},{"style":551},[21705],{"type":420,"value":1349},{"type":415,"tag":532,"props":21707,"children":21708},{"style":545},[21709],{"type":420,"value":18873},{"type":415,"tag":532,"props":21711,"children":21712},{"class":534,"line":627},[21713,21717,21722,21726,21731,21735],{"type":415,"tag":532,"props":21714,"children":21715},{"style":551},[21716],{"type":420,"value":3328},{"type":415,"tag":532,"props":21718,"children":21719},{"style":656},[21720],{"type":420,"value":21721},"SetPropertyName",{"type":415,"tag":532,"props":21723,"children":21724},{"style":551},[21725],{"type":420,"value":664},{"type":415,"tag":532,"props":21727,"children":21728},{"style":545},[21729],{"type":420,"value":21730},"outputName",{"type":415,"tag":532,"props":21732,"children":21733},{"style":551},[21734],{"type":420,"value":1349},{"type":415,"tag":532,"props":21736,"children":21737},{"style":545},[21738],{"type":420,"value":18873},{"type":415,"tag":532,"props":21740,"children":21741},{"class":534,"line":677},[21742,21746,21751],{"type":415,"tag":532,"props":21743,"children":21744},{"style":551},[21745],{"type":420,"value":3328},{"type":415,"tag":532,"props":21747,"children":21748},{"style":656},[21749],{"type":420,"value":21750},"EnableShowSecrets",{"type":415,"tag":532,"props":21752,"children":21753},{"style":551},[21754],{"type":420,"value":7907},{"type":415,"tag":532,"props":21756,"children":21757},{"class":534,"line":719},[21758,21762,21767,21771],{"type":415,"tag":532,"props":21759,"children":21760},{"style":551},[21761],{"type":420,"value":3328},{"type":415,"tag":532,"props":21763,"children":21764},{"style":656},[21765],{"type":420,"value":21766},"DisableProcessLogOutput",{"type":415,"tag":532,"props":21768,"children":21769},{"style":551},[21770],{"type":420,"value":13082},{"type":415,"tag":532,"props":21772,"children":21773},{"style":545},[21774],{"type":420,"value":18873},{"type":415,"tag":532,"props":21776,"children":21777},{"class":534,"line":758},[21778,21782,21787,21792],{"type":415,"tag":532,"props":21779,"children":21780},{"style":551},[21781],{"type":420,"value":1532},{"type":415,"tag":532,"props":21783,"children":21784},{"style":656},[21785],{"type":420,"value":21786},"StdToText",{"type":415,"tag":532,"props":21788,"children":21789},{"style":551},[21790],{"type":420,"value":21791},"();",{"type":415,"tag":532,"props":21793,"children":21794},{"style":545},[21795],{"type":420,"value":18873},{"type":415,"tag":532,"props":21797,"children":21798},{"class":534,"line":767},[21799],{"type":415,"tag":532,"props":21800,"children":21801},{"style":551},[21802],{"type":420,"value":1379},{"type":415,"tag":416,"props":21804,"children":21805},{},[21806],{"type":420,"value":21807},"The step itself is not very complicated, just standard C# code using an HttpClient to send a POST request (with our application package as the content) to the Kudu API.",{"type":415,"tag":523,"props":21809,"children":21811},{"className":525,"code":21810,"language":326,"meta":401,"style":401},"Target Deploy => _ => _  \n    .DependsOn(Publish)  \n    .After(ProvisionInfra)  \n    .Executes(async () =>  \n    {  \n        var publishingUsername = GetPulumiOutput(\"publishingUsername\");  \n        var publishingUserPassword = GetPulumiOutput(\"publishingUserPassword\");  \n        var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($\"{publishingUsername}:{publishingUserPassword}\"));  \n  \n        await using var package = File.OpenRead(ArtifactsDirectory / \"api.zip\");  \n        using var httpClient = new HttpClient();  \n        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Basic\", base64Auth);  \n        await httpClient.PostAsync($\"https://{GetPulumiOutput(\"appServiceName\")}.scm.azurewebsites.net/api/zipdeploy\",  \n            new StreamContent(package));  \n    });\n",[21812],{"type":415,"tag":468,"props":21813,"children":21814},{"__ignoreMap":401},[21815,21843,21870,21898,21930,21941,21985,22029,22126,22133,22205,22243,22314,22387,22417],{"type":415,"tag":532,"props":21816,"children":21817},{"class":534,"line":535},[21818,21822,21827,21831,21835,21839],{"type":415,"tag":532,"props":21819,"children":21820},{"style":545},[21821],{"type":420,"value":18821},{"type":415,"tag":532,"props":21823,"children":21824},{"style":631},[21825],{"type":420,"value":21826},"Deploy",{"type":415,"tag":532,"props":21828,"children":21829},{"style":551},[21830],{"type":420,"value":8499},{"type":415,"tag":532,"props":21832,"children":21833},{"style":631},[21834],{"type":420,"value":3178},{"type":415,"tag":532,"props":21836,"children":21837},{"style":551},[21838],{"type":420,"value":8499},{"type":415,"tag":532,"props":21840,"children":21841},{"style":545},[21842],{"type":420,"value":18842},{"type":415,"tag":532,"props":21844,"children":21845},{"class":534,"line":566},[21846,21850,21854,21858,21862,21866],{"type":415,"tag":532,"props":21847,"children":21848},{"style":551},[21849],{"type":420,"value":18850},{"type":415,"tag":532,"props":21851,"children":21852},{"style":656},[21853],{"type":420,"value":19413},{"type":415,"tag":532,"props":21855,"children":21856},{"style":551},[21857],{"type":420,"value":664},{"type":415,"tag":532,"props":21859,"children":21860},{"style":545},[21861],{"type":420,"value":19614},{"type":415,"tag":532,"props":21863,"children":21864},{"style":551},[21865],{"type":420,"value":1349},{"type":415,"tag":532,"props":21867,"children":21868},{"style":545},[21869],{"type":420,"value":18873},{"type":415,"tag":532,"props":21871,"children":21872},{"class":534,"line":583},[21873,21877,21882,21886,21890,21894],{"type":415,"tag":532,"props":21874,"children":21875},{"style":551},[21876],{"type":420,"value":18850},{"type":415,"tag":532,"props":21878,"children":21879},{"style":656},[21880],{"type":420,"value":21881},"After",{"type":415,"tag":532,"props":21883,"children":21884},{"style":551},[21885],{"type":420,"value":664},{"type":415,"tag":532,"props":21887,"children":21888},{"style":545},[21889],{"type":420,"value":21351},{"type":415,"tag":532,"props":21891,"children":21892},{"style":551},[21893],{"type":420,"value":1349},{"type":415,"tag":532,"props":21895,"children":21896},{"style":545},[21897],{"type":420,"value":18873},{"type":415,"tag":532,"props":21899,"children":21900},{"class":534,"line":617},[21901,21905,21909,21913,21918,21922,21926],{"type":415,"tag":532,"props":21902,"children":21903},{"style":551},[21904],{"type":420,"value":18850},{"type":415,"tag":532,"props":21906,"children":21907},{"style":656},[21908],{"type":420,"value":18885},{"type":415,"tag":532,"props":21910,"children":21911},{"style":551},[21912],{"type":420,"value":664},{"type":415,"tag":532,"props":21914,"children":21915},{"style":954},[21916],{"type":420,"value":21917},"async",{"type":415,"tag":532,"props":21919,"children":21920},{"style":551},[21921],{"type":420,"value":3342},{"type":415,"tag":532,"props":21923,"children":21924},{"style":551},[21925],{"type":420,"value":8499},{"type":415,"tag":532,"props":21927,"children":21928},{"style":545},[21929],{"type":420,"value":18873},{"type":415,"tag":532,"props":21931,"children":21932},{"class":534,"line":627},[21933,21937],{"type":415,"tag":532,"props":21934,"children":21935},{"style":551},[21936],{"type":420,"value":18906},{"type":415,"tag":532,"props":21938,"children":21939},{"style":545},[21940],{"type":420,"value":18873},{"type":415,"tag":532,"props":21942,"children":21943},{"class":534,"line":677},[21944,21948,21953,21957,21961,21965,21969,21973,21977,21981],{"type":415,"tag":532,"props":21945,"children":21946},{"style":631},[21947],{"type":420,"value":3210},{"type":415,"tag":532,"props":21949,"children":21950},{"style":631},[21951],{"type":420,"value":21952}," publishingUsername",{"type":415,"tag":532,"props":21954,"children":21955},{"style":551},[21956],{"type":420,"value":644},{"type":415,"tag":532,"props":21958,"children":21959},{"style":656},[21960],{"type":420,"value":21613},{"type":415,"tag":532,"props":21962,"children":21963},{"style":551},[21964],{"type":420,"value":664},{"type":415,"tag":532,"props":21966,"children":21967},{"style":551},[21968],{"type":420,"value":801},{"type":415,"tag":532,"props":21970,"children":21971},{"style":804},[21972],{"type":420,"value":21043},{"type":415,"tag":532,"props":21974,"children":21975},{"style":551},[21976],{"type":420,"value":801},{"type":415,"tag":532,"props":21978,"children":21979},{"style":551},[21980],{"type":420,"value":18984},{"type":415,"tag":532,"props":21982,"children":21983},{"style":545},[21984],{"type":420,"value":18873},{"type":415,"tag":532,"props":21986,"children":21987},{"class":534,"line":719},[21988,21992,21997,22001,22005,22009,22013,22017,22021,22025],{"type":415,"tag":532,"props":21989,"children":21990},{"style":631},[21991],{"type":420,"value":3210},{"type":415,"tag":532,"props":21993,"children":21994},{"style":631},[21995],{"type":420,"value":21996}," publishingUserPassword",{"type":415,"tag":532,"props":21998,"children":21999},{"style":551},[22000],{"type":420,"value":644},{"type":415,"tag":532,"props":22002,"children":22003},{"style":656},[22004],{"type":420,"value":21613},{"type":415,"tag":532,"props":22006,"children":22007},{"style":551},[22008],{"type":420,"value":664},{"type":415,"tag":532,"props":22010,"children":22011},{"style":551},[22012],{"type":420,"value":801},{"type":415,"tag":532,"props":22014,"children":22015},{"style":804},[22016],{"type":420,"value":21135},{"type":415,"tag":532,"props":22018,"children":22019},{"style":551},[22020],{"type":420,"value":801},{"type":415,"tag":532,"props":22022,"children":22023},{"style":551},[22024],{"type":420,"value":18984},{"type":415,"tag":532,"props":22026,"children":22027},{"style":545},[22028],{"type":420,"value":18873},{"type":415,"tag":532,"props":22030,"children":22031},{"class":534,"line":758},[22032,22036,22041,22045,22050,22054,22059,22063,22068,22072,22077,22081,22086,22090,22094,22098,22102,22106,22110,22114,22118,22122],{"type":415,"tag":532,"props":22033,"children":22034},{"style":631},[22035],{"type":420,"value":3210},{"type":415,"tag":532,"props":22037,"children":22038},{"style":631},[22039],{"type":420,"value":22040}," base64Auth",{"type":415,"tag":532,"props":22042,"children":22043},{"style":551},[22044],{"type":420,"value":644},{"type":415,"tag":532,"props":22046,"children":22047},{"style":545},[22048],{"type":420,"value":22049}," Convert",{"type":415,"tag":532,"props":22051,"children":22052},{"style":551},[22053],{"type":420,"value":432},{"type":415,"tag":532,"props":22055,"children":22056},{"style":656},[22057],{"type":420,"value":22058},"ToBase64String",{"type":415,"tag":532,"props":22060,"children":22061},{"style":551},[22062],{"type":420,"value":664},{"type":415,"tag":532,"props":22064,"children":22065},{"style":545},[22066],{"type":420,"value":22067},"Encoding",{"type":415,"tag":532,"props":22069,"children":22070},{"style":551},[22071],{"type":420,"value":432},{"type":415,"tag":532,"props":22073,"children":22074},{"style":545},[22075],{"type":420,"value":22076},"Default",{"type":415,"tag":532,"props":22078,"children":22079},{"style":551},[22080],{"type":420,"value":432},{"type":415,"tag":532,"props":22082,"children":22083},{"style":656},[22084],{"type":420,"value":22085},"GetBytes",{"type":415,"tag":532,"props":22087,"children":22088},{"style":551},[22089],{"type":420,"value":664},{"type":415,"tag":532,"props":22091,"children":22092},{"style":551},[22093],{"type":420,"value":10764},{"type":415,"tag":532,"props":22095,"children":22096},{"style":545},[22097],{"type":420,"value":21043},{"type":415,"tag":532,"props":22099,"children":22100},{"style":551},[22101],{"type":420,"value":4864},{"type":415,"tag":532,"props":22103,"children":22104},{"style":804},[22105],{"type":420,"value":1290},{"type":415,"tag":532,"props":22107,"children":22108},{"style":551},[22109],{"type":420,"value":8748},{"type":415,"tag":532,"props":22111,"children":22112},{"style":545},[22113],{"type":420,"value":21135},{"type":415,"tag":532,"props":22115,"children":22116},{"style":551},[22117],{"type":420,"value":4502},{"type":415,"tag":532,"props":22119,"children":22120},{"style":551},[22121],{"type":420,"value":19320},{"type":415,"tag":532,"props":22123,"children":22124},{"style":545},[22125],{"type":420,"value":18873},{"type":415,"tag":532,"props":22127,"children":22128},{"class":534,"line":767},[22129],{"type":415,"tag":532,"props":22130,"children":22131},{"style":545},[22132],{"type":420,"value":18873},{"type":415,"tag":532,"props":22134,"children":22135},{"class":534,"line":819},[22136,22140,22145,22150,22155,22159,22163,22167,22172,22176,22181,22185,22189,22193,22197,22201],{"type":415,"tag":532,"props":22137,"children":22138},{"style":551},[22139],{"type":420,"value":1238},{"type":415,"tag":532,"props":22141,"children":22142},{"style":1241},[22143],{"type":420,"value":22144}," using",{"type":415,"tag":532,"props":22146,"children":22147},{"style":631},[22148],{"type":420,"value":22149}," var",{"type":415,"tag":532,"props":22151,"children":22152},{"style":631},[22153],{"type":420,"value":22154}," package",{"type":415,"tag":532,"props":22156,"children":22157},{"style":551},[22158],{"type":420,"value":644},{"type":415,"tag":532,"props":22160,"children":22161},{"style":545},[22162],{"type":420,"value":10133},{"type":415,"tag":532,"props":22164,"children":22165},{"style":551},[22166],{"type":420,"value":432},{"type":415,"tag":532,"props":22168,"children":22169},{"style":656},[22170],{"type":420,"value":22171},"OpenRead",{"type":415,"tag":532,"props":22173,"children":22174},{"style":551},[22175],{"type":420,"value":664},{"type":415,"tag":532,"props":22177,"children":22178},{"style":545},[22179],{"type":420,"value":22180},"ArtifactsDirectory ",{"type":415,"tag":532,"props":22182,"children":22183},{"style":551},[22184],{"type":420,"value":4728},{"type":415,"tag":532,"props":22186,"children":22187},{"style":551},[22188],{"type":420,"value":4041},{"type":415,"tag":532,"props":22190,"children":22191},{"style":804},[22192],{"type":420,"value":19593},{"type":415,"tag":532,"props":22194,"children":22195},{"style":551},[22196],{"type":420,"value":801},{"type":415,"tag":532,"props":22198,"children":22199},{"style":551},[22200],{"type":420,"value":18984},{"type":415,"tag":532,"props":22202,"children":22203},{"style":545},[22204],{"type":420,"value":18873},{"type":415,"tag":532,"props":22206,"children":22207},{"class":534,"line":850},[22208,22213,22217,22222,22226,22230,22235,22239],{"type":415,"tag":532,"props":22209,"children":22210},{"style":1241},[22211],{"type":420,"value":22212},"        using",{"type":415,"tag":532,"props":22214,"children":22215},{"style":631},[22216],{"type":420,"value":22149},{"type":415,"tag":532,"props":22218,"children":22219},{"style":631},[22220],{"type":420,"value":22221}," httpClient",{"type":415,"tag":532,"props":22223,"children":22224},{"style":551},[22225],{"type":420,"value":644},{"type":415,"tag":532,"props":22227,"children":22228},{"style":551},[22229],{"type":420,"value":3276},{"type":415,"tag":532,"props":22231,"children":22232},{"style":631},[22233],{"type":420,"value":22234}," HttpClient",{"type":415,"tag":532,"props":22236,"children":22237},{"style":551},[22238],{"type":420,"value":21791},{"type":415,"tag":532,"props":22240,"children":22241},{"style":545},[22242],{"type":420,"value":18873},{"type":415,"tag":532,"props":22244,"children":22245},{"class":534,"line":859},[22246,22251,22255,22260,22264,22269,22273,22277,22282,22286,22290,22294,22298,22302,22306,22310],{"type":415,"tag":532,"props":22247,"children":22248},{"style":545},[22249],{"type":420,"value":22250},"        httpClient",{"type":415,"tag":532,"props":22252,"children":22253},{"style":551},[22254],{"type":420,"value":432},{"type":415,"tag":532,"props":22256,"children":22257},{"style":545},[22258],{"type":420,"value":22259},"DefaultRequestHeaders",{"type":415,"tag":532,"props":22261,"children":22262},{"style":551},[22263],{"type":420,"value":432},{"type":415,"tag":532,"props":22265,"children":22266},{"style":545},[22267],{"type":420,"value":22268},"Authorization ",{"type":415,"tag":532,"props":22270,"children":22271},{"style":551},[22272],{"type":420,"value":1134},{"type":415,"tag":532,"props":22274,"children":22275},{"style":551},[22276],{"type":420,"value":3276},{"type":415,"tag":532,"props":22278,"children":22279},{"style":631},[22280],{"type":420,"value":22281}," AuthenticationHeaderValue",{"type":415,"tag":532,"props":22283,"children":22284},{"style":551},[22285],{"type":420,"value":664},{"type":415,"tag":532,"props":22287,"children":22288},{"style":551},[22289],{"type":420,"value":801},{"type":415,"tag":532,"props":22291,"children":22292},{"style":804},[22293],{"type":420,"value":20508},{"type":415,"tag":532,"props":22295,"children":22296},{"style":551},[22297],{"type":420,"value":801},{"type":415,"tag":532,"props":22299,"children":22300},{"style":551},[22301],{"type":420,"value":1099},{"type":415,"tag":532,"props":22303,"children":22304},{"style":545},[22305],{"type":420,"value":22040},{"type":415,"tag":532,"props":22307,"children":22308},{"style":551},[22309],{"type":420,"value":18984},{"type":415,"tag":532,"props":22311,"children":22312},{"style":545},[22313],{"type":420,"value":18873},{"type":415,"tag":532,"props":22315,"children":22316},{"class":534,"line":867},[22317,22321,22325,22329,22334,22338,22342,22347,22351,22356,22361,22365,22370,22375,22379,22383],{"type":415,"tag":532,"props":22318,"children":22319},{"style":551},[22320],{"type":420,"value":1238},{"type":415,"tag":532,"props":22322,"children":22323},{"style":545},[22324],{"type":420,"value":22221},{"type":415,"tag":532,"props":22326,"children":22327},{"style":551},[22328],{"type":420,"value":432},{"type":415,"tag":532,"props":22330,"children":22331},{"style":656},[22332],{"type":420,"value":22333},"PostAsync",{"type":415,"tag":532,"props":22335,"children":22336},{"style":551},[22337],{"type":420,"value":664},{"type":415,"tag":532,"props":22339,"children":22340},{"style":551},[22341],{"type":420,"value":8738},{"type":415,"tag":532,"props":22343,"children":22344},{"style":804},[22345],{"type":420,"value":22346},"https://",{"type":415,"tag":532,"props":22348,"children":22349},{"style":551},[22350],{"type":420,"value":8748},{"type":415,"tag":532,"props":22352,"children":22353},{"style":656},[22354],{"type":420,"value":22355},"GetPulumiOutput",{"type":415,"tag":532,"props":22357,"children":22358},{"style":551},[22359],{"type":420,"value":22360},"(\"",{"type":415,"tag":532,"props":22362,"children":22363},{"style":804},[22364],{"type":420,"value":21224},{"type":415,"tag":532,"props":22366,"children":22367},{"style":551},[22368],{"type":420,"value":22369},"\")}",{"type":415,"tag":532,"props":22371,"children":22372},{"style":804},[22373],{"type":420,"value":22374},".scm.azurewebsites.net/api/zipdeploy",{"type":415,"tag":532,"props":22376,"children":22377},{"style":551},[22378],{"type":420,"value":801},{"type":415,"tag":532,"props":22380,"children":22381},{"style":551},[22382],{"type":420,"value":1099},{"type":415,"tag":532,"props":22384,"children":22385},{"style":545},[22386],{"type":420,"value":18873},{"type":415,"tag":532,"props":22388,"children":22389},{"class":534,"line":902},[22390,22395,22400,22404,22409,22413],{"type":415,"tag":532,"props":22391,"children":22392},{"style":551},[22393],{"type":420,"value":22394},"            new",{"type":415,"tag":532,"props":22396,"children":22397},{"style":631},[22398],{"type":420,"value":22399}," StreamContent",{"type":415,"tag":532,"props":22401,"children":22402},{"style":551},[22403],{"type":420,"value":664},{"type":415,"tag":532,"props":22405,"children":22406},{"style":545},[22407],{"type":420,"value":22408},"package",{"type":415,"tag":532,"props":22410,"children":22411},{"style":551},[22412],{"type":420,"value":19320},{"type":415,"tag":532,"props":22414,"children":22415},{"style":545},[22416],{"type":420,"value":18873},{"type":415,"tag":532,"props":22418,"children":22419},{"class":534,"line":1302},[22420],{"type":415,"tag":532,"props":22421,"children":22422},{"style":551},[22423],{"type":420,"value":2468},{"type":415,"tag":434,"props":22425,"children":22426},{"icon":436},[22427],{"type":415,"tag":416,"props":22428,"children":22429},{},[22430,22432,22439],{"type":420,"value":22431},"George Dangl already wrote a nice ",{"type":415,"tag":423,"props":22433,"children":22436},{"href":22434,"rel":22435},"https://blog.dangl.me/archive/lets-use-nuke-to-quickly-deploy-an-app-to-azure-via-zip-deployment/",[427],[22437],{"type":420,"value":22438},"article",{"type":420,"value":22440}," about using Nuke to deploy an application to Azure App Service using the Kudu API, so you can have a look at it. The code in the article is similar to the one we have here except that the credentials don't come from Pulumi outputs but from an Azure Key Vault.",{"type":415,"tag":416,"props":22442,"children":22443},{},[22444],{"type":420,"value":22445},"What I like about this approach is that you know exactly what you are doing, and the deployment logic is not hidden from you in an obscure YAML task whose code you will never read (yes I am talking to you Azure Pipelines and GitHub Actions 😃).",{"type":415,"tag":416,"props":22447,"children":22448},{},[22449],{"type":420,"value":22450},"But the awesome part in Nuke is that you can put a breakpoint in the code and debug it locally. If you need to modify your pipeline, you don't need to write YAML code modifications without knowing if it would work or not 🤞, commit and push your modifications, wait for an agent to run the changed pipeline in the cloud, wait for it to fail, browse the logs to try to understand the problem, and try again until it works.",{"type":415,"tag":482,"props":22452,"children":22454},{"id":22453},"final-pipeline",[22455],{"type":420,"value":22456},"Final pipeline",{"type":415,"tag":416,"props":22458,"children":22459},{},[22460],{"type":420,"value":22461},"If I fold everything, the pipeline code we created looks like that:",{"type":415,"tag":416,"props":22463,"children":22464},{},[22465],{"type":415,"tag":3882,"props":22466,"children":22470},{"alt":22467,"className":22468,"src":22469},"Complete Nuke pipeline in the Build.cs file.",[3886,3887],"/posts/images/pulumi_met_nuke_11.png",[],{"type":415,"tag":416,"props":22472,"children":22473},{},[22474,22476,22482],{"type":420,"value":22475},"I think it is quite clear with the different steps/targets defined with their dependencies/order. Yet if this is not clear enough for you, you can use the ",{"type":415,"tag":468,"props":22477,"children":22479},{"className":22478},[],[22480],{"type":420,"value":22481},"nuke --plan",{"type":420,"value":22483}," command to display a visual representation of the pipeline (how cool is that !?)",{"type":415,"tag":416,"props":22485,"children":22486},{},[22487],{"type":415,"tag":3882,"props":22488,"children":22492},{"alt":22489,"className":22490,"src":22491},"Nuke execution plan displayed as a graph.",[3886,3887],"/posts/images/pulumi_met_nuke_12.png",[],{"type":415,"tag":434,"props":22494,"children":22495},{"icon":1382},[22496],{"type":415,"tag":416,"props":22497,"children":22498},{},[22499],{"type":420,"value":22500},"You can see that the execution plan is almost identical to the pipelines steps we talked about in the beginning of the article. The only difference is that we added to the Publish step a dependence on Clean.",{"type":415,"tag":416,"props":22502,"children":22503},{},[22504],{"type":420,"value":22505},"Let's execute the complete pipeline:",{"type":415,"tag":416,"props":22507,"children":22508},{},[22509],{"type":415,"tag":3882,"props":22510,"children":22514},{"alt":22511,"className":22512,"src":22513,"width":18428},"Pipeline output in terminal showing the different steps and their status.",[3886,3887],"/posts/images/pulumi_met_nuke_13.png",[],{"type":415,"tag":416,"props":22516,"children":22517},{},[22518],{"type":420,"value":22519},"If I go to my Azure portal I can see the new Azure resources, among them an App Service where my Weather API is deployed.",{"type":415,"tag":416,"props":22521,"children":22522},{},[22523],{"type":415,"tag":3882,"props":22524,"children":22528},{"alt":22525,"className":22526,"src":22527,"width":6932},"Weather API weather forecast endpoint response opened in a browser.",[3886,3887],"/posts/images/pulumi_met_nuke_14.png",[],{"type":415,"tag":482,"props":22530,"children":22532},{"id":22531},"conclusion",[22533],{"type":420,"value":22534},"Conclusion",{"type":415,"tag":3914,"props":22536,"children":22538},{"id":22537},"improvements-to-the-example-pipeline",[22539],{"type":420,"value":22540},"Improvements to the example pipeline",{"type":415,"tag":416,"props":22542,"children":22543},{},[22544],{"type":420,"value":22545},"The pipeline I have shown in this article is just a simple sample. They are lots of things that could be done to improve it. Beyond obvious ones like adding a Test target or using GitVersion to version the package, I want to talk about some choices I made in the pipeline implementation that may not be the best ones.",{"type":415,"tag":416,"props":22547,"children":22548},{},[22549,22551,22558,22560,22567,22569,22576],{"type":420,"value":22550},"As I said there are many ways to deploy a package to an App Service. While using the Kudu API is fine and allowed me to show you how we can use Pulumi stack outputs to retrieve publishing credentials, it might be a bit limited in some cases and involves a bit of manual code to make the HTTP request. A good alternative would be to use the Azure CLI that has ",{"type":415,"tag":423,"props":22552,"children":22555},{"href":22553,"rel":22554},"https://learn.microsoft.com/en-us/cli/azure/webapp/deployment/source?view=azure-cli-latest#az-webapp-deployment-source-config-zip",[427],[22556],{"type":420,"value":22557},"a command",{"type":420,"value":22559}," for that. But my preferred option would be to use the ",{"type":415,"tag":423,"props":22561,"children":22564},{"href":22562,"rel":22563},"https://learn.microsoft.com/en-us/dotnet/api/overview/azure/resource-manager?view=azure-dotnet",[427],[22565],{"type":420,"value":22566},"Azure Resource Manager libraries for .NET",{"type":420,"value":22568},". Unfortunately this SDK is quite new and miss ",{"type":415,"tag":423,"props":22570,"children":22573},{"href":22571,"rel":22572},"https://github.com/Azure/azure-sdk-for-net/issues/30577",[427],[22574],{"type":420,"value":22575},"samples",{"type":420,"value":22577}," on how to do that.",{"type":415,"tag":416,"props":22579,"children":22580},{},[22581,22583,22590],{"type":420,"value":22582},"Speaking of SDK, Pulumi has an API called the ",{"type":415,"tag":423,"props":22584,"children":22587},{"href":22585,"rel":22586},"https://www.pulumi.com/automation/",[427],[22588],{"type":420,"value":22589},"Automation API",{"type":420,"value":22591}," to use the Pulumi engine as an SDK. I think it would be a better option than using the Pulumi CLI. Generally speaking, I think using SDK instead of CLIs to write the targets of a pipeline brings more power, more flexibility, and a better developer experience.",{"type":415,"tag":3914,"props":22593,"children":22595},{"id":22594},"about-nuke-and-cicd",[22596],{"type":420,"value":22597},"About Nuke and CI/CD",{"type":415,"tag":416,"props":22599,"children":22600},{},[22601],{"type":420,"value":22602},"Nuke has many features I did not show in this small example. If we add some attributes to the pipeline code, Nuke can generate YAML workflow files to execute the Nuke pipeline. When executing the pipeline locally everything works fine because I am logged in to Pulumi CLI and Azure CLI in my terminal but I have to add secret parameters to my Nuke pipeline (a Pulumi token and an Azure Service Principal identifier/password) to make the authentication works when the pipeline is run from a CI/CD platform runner/agent.",{"type":415,"tag":416,"props":22604,"children":22605},{},[22606,22608,22614,22615,22622],{"type":420,"value":22607},"Moreover, there are many things I don't know yet about Nuke because I am just starting to use it. That is why I advise you to have a look at its ",{"type":415,"tag":423,"props":22609,"children":22612},{"href":22610,"rel":22611},"https://nuke.build/docs/introduction/",[427],[22613],{"type":420,"value":499},{"type":420,"value":8073},{"type":415,"tag":423,"props":22616,"children":22619},{"href":22617,"rel":22618},"https://nuke.build/resources/",[427],[22620],{"type":420,"value":22621},"at some resources",{"type":420,"value":22623}," and start playing with it by yourself.",{"type":415,"tag":416,"props":22625,"children":22626},{},[22627],{"type":420,"value":22628},"In the future, I see myself using Nuke for most of my CI pipelines, and not only for .NET projects (because I can run any CLI tools from Nuke, it also works for front projects where I would use the pnpm CLI for instance). I am not saying that because I am afraid of YAML or because I'm not familiar with ready-made tasks like Azure Pipelines tasks or GitHub Actions. I have been using Azure Pipelines for several years now and I have also played a bit with GitHub Actions. They are good platforms but lack local debugging and the great developer experience provided by a tool like Nuke. So I will continue using them but to run my Nuke pipelines 😉.",{"type":415,"tag":416,"props":22630,"children":22631},{},[22632],{"type":420,"value":22633},"Concerning the CD pipelines, I don't know yet if I can use Nuke for all my use cases. They are real benefits to using Nuke for deployments but I still have to investigate how some things can be done like deploying to multiple environments, and handling approvals between environments.",{"type":415,"tag":3914,"props":22635,"children":22637},{"id":22636},"pulumi-nuke-the-perfect-combo",[22638],{"type":420,"value":22639},"Pulumi & Nuke, the perfect combo?",{"type":415,"tag":416,"props":22641,"children":22642},{},[22643],{"type":420,"value":22644},"I don't know if it's the perfect combo but it's definitively one I love. Having .NET everywhere, from infrastructure code to pipeline code without forgetting the application code is awesome.",{"type":415,"tag":3470,"props":22646,"children":22647},{},[22648],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":22650},[22651,22652,22653,22658,22665,22671,22672,22673],{"id":18390,"depth":566,"text":18393},{"id":18411,"depth":566,"text":18414},{"id":18508,"depth":566,"text":18511,"children":22654},[22655,22656,22657],{"id":18514,"depth":583,"text":18517},{"id":18571,"depth":583,"text":18574},{"id":18691,"depth":583,"text":18694},{"id":18737,"depth":566,"text":18740,"children":22659},[22660,22661,22662,22663,22664],{"id":18743,"depth":583,"text":18746},{"id":18798,"depth":583,"text":18801},{"id":19180,"depth":583,"text":19183},{"id":19334,"depth":583,"text":19337},{"id":19572,"depth":583,"text":19575},{"id":20042,"depth":566,"text":20045,"children":22666},[22667,22668,22669,22670],{"id":20048,"depth":583,"text":20051},{"id":20103,"depth":583,"text":20106},{"id":20790,"depth":583,"text":20793},{"id":21271,"depth":583,"text":21274},{"id":21565,"depth":566,"text":21568},{"id":22453,"depth":566,"text":22456},{"id":22531,"depth":566,"text":22534,"children":22674},[22675,22676,22677],{"id":22537,"depth":583,"text":22540},{"id":22594,"depth":583,"text":22597},{"id":22636,"depth":583,"text":22639},"content:1.posts:45.when-pulumi-met-nuke.md","1.posts/45.when-pulumi-met-nuke.md",{"_path":112,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":111,"description":22681,"lead":22682,"date":22683,"image":22684,"badge":22686,"tags":22687,"body":22688,"_type":3483,"_id":25550,"_source":3485,"_file":25551,"_extension":3487},"In this article, we will talk about how to provision an Azure SQL Database with authentication restricted to Active Directory users/groups/applications. We will use Pulumi to do that.","Using Pulumi and its command provider to grant database permissions","2022-02-22T00:00:00.000Z",{"src":22685},"/images/lockers_1.jpg",{"label":266},[252,299,228,239,312,315],{"type":412,"children":22689,"toc":25532},[22690,22694,22700,22722,22735,22743,22748,22754,22759,23034,23064,23070,23075,23373,23385,23573,23579,23584,23596,23697,23717,23722,23727,23753,23758,23764,23778,23787,23819,23828,23844,23856,23862,23890,23895,23907,24023,24035,24067,24079,24118,24127,24154,24207,24213,24232,24238,24251,24326,24359,24364,24531,24537,24542,24719,24724,24742,24748,24767,24856,24867,25020,25040,25045,25427,25432,25464,25470,25488,25497,25501,25513,25518,25523,25528],{"type":415,"tag":416,"props":22691,"children":22692},{},[22693],{"type":420,"value":22681},{"type":415,"tag":482,"props":22695,"children":22697},{"id":22696},"why-this-article",[22698],{"type":420,"value":22699},"Why this article?",{"type":415,"tag":416,"props":22701,"children":22702},{},[22703,22705,22712,22714,22720],{"type":420,"value":22704},"In ",{"type":415,"tag":423,"props":22706,"children":22709},{"href":22707,"rel":22708},"https://www.techwatching.dev/posts/sqlclient-active-directory-authent",[427],[22710],{"type":420,"value":22711},"a previous article",{"type":420,"value":22713},", I already talked about connecting to an Azure SQL Database using Azure Active Directory authentication. However, my focus was on querying an Azure SQL Database from C# code (from an ASP.NET 6 Minimal API that was using ",{"type":415,"tag":468,"props":22715,"children":22717},{"className":22716},[],[22718],{"type":420,"value":22719},"Microsoft.Data.SqlClient",{"type":420,"value":22721}," 'Active Directory Default' authentication mode to be more precise), and not on the configuration of the Azure AD authentication itself.",{"type":415,"tag":416,"props":22723,"children":22724},{},[22725,22727,22733],{"type":420,"value":22726},"Still, in that article, I wrote an Azure CLI script that showed how to provision and configure the database with Azure AD authentication enabled. So why write another article about that? First because I did not show how to give an Azure AD entity (user, group, or managed identity) permission to access the database. (In my samples, to simplify things I was using the SQL server Azure AD administrator account to make my queries 🤫). Yet, it is something you will probably have to do if you want your App Service or Function App to query your database. Second because even if Azure CLI is great to handle Azure resources (if you are a reader of my blog, you probably know that I ",{"type":415,"tag":423,"props":22728,"children":22730},{"href":4423,"rel":22729},[427],[22731],{"type":420,"value":22732},"enjoy very much Azure CLI",{"type":420,"value":22734},"), in a real project I would probably use a more advanced Infrastructure as Code solution like Pulumi. And that is what we will show here.",{"type":415,"tag":434,"props":22736,"children":22737},{"icon":1382},[22738],{"type":415,"tag":416,"props":22739,"children":22740},{},[22741],{"type":420,"value":22742},"If you are not familiar with Pulumi, it is an IaC solution similar to Terraform but using programming languages like C#. Speaking of C#, that is what I will use to write my infrastructure code but you can easily do the same in another language supported by Pulumi (TypeScript, Go, Python,... choose the one you are used to), the concepts stay relevant and the code will be similar.",{"type":415,"tag":416,"props":22744,"children":22745},{},[22746],{"type":420,"value":22747},"Now, let's get to the heart of the matter.",{"type":415,"tag":482,"props":22749,"children":22751},{"id":22750},"an-azure-ad-user-as-our-sql-server-administrator",[22752],{"type":420,"value":22753},"An Azure AD user as our SQL Server administrator",{"type":415,"tag":416,"props":22755,"children":22756},{},[22757],{"type":420,"value":22758},"Usually, when you create an Azure SQL Server, you have to provide an administrator login and an administrator password. But I said I wanted to limit the authentication to Azure Active Directory authentication only. So we will only need an Azure AD account to set as the administrator of our SQL Server. We could use an existing Azure AD account, but let's create a new Azure AD user just for that:",{"type":415,"tag":523,"props":22760,"children":22762},{"className":525,"code":22761,"language":326,"meta":401,"style":401},"var config = new Config();\nvar sqlAdAdminLogin = config.Require(\"sqlAdAdmin\");\nvar sqlAdAdminPassword = config.RequireSecret(\"sqlAdPassword\");\n\nvar sqlAdAdmin = new User(\"sqlAdmin\", new UserArgs\n{\n    UserPrincipalName = sqlAdAdminLogin,\n    Password = sqlAdAdminPassword,\n    DisplayName = \"Global SQL Admin\"\n});\n",[22763],{"type":415,"tag":468,"props":22764,"children":22765},{"__ignoreMap":401},[22766,22794,22844,22894,22901,22956,22963,22983,23003,23027],{"type":415,"tag":532,"props":22767,"children":22768},{"class":534,"line":535},[22769,22773,22777,22781,22785,22790],{"type":415,"tag":532,"props":22770,"children":22771},{"style":631},[22772],{"type":420,"value":634},{"type":415,"tag":532,"props":22774,"children":22775},{"style":631},[22776],{"type":420,"value":7206},{"type":415,"tag":532,"props":22778,"children":22779},{"style":551},[22780],{"type":420,"value":644},{"type":415,"tag":532,"props":22782,"children":22783},{"style":551},[22784],{"type":420,"value":3276},{"type":415,"tag":532,"props":22786,"children":22787},{"style":631},[22788],{"type":420,"value":22789}," Config",{"type":415,"tag":532,"props":22791,"children":22792},{"style":551},[22793],{"type":420,"value":899},{"type":415,"tag":532,"props":22795,"children":22796},{"class":534,"line":566},[22797,22801,22806,22810,22814,22818,22823,22827,22831,22836,22840],{"type":415,"tag":532,"props":22798,"children":22799},{"style":631},[22800],{"type":420,"value":634},{"type":415,"tag":532,"props":22802,"children":22803},{"style":631},[22804],{"type":420,"value":22805}," sqlAdAdminLogin",{"type":415,"tag":532,"props":22807,"children":22808},{"style":551},[22809],{"type":420,"value":644},{"type":415,"tag":532,"props":22811,"children":22812},{"style":545},[22813],{"type":420,"value":7206},{"type":415,"tag":532,"props":22815,"children":22816},{"style":551},[22817],{"type":420,"value":432},{"type":415,"tag":532,"props":22819,"children":22820},{"style":656},[22821],{"type":420,"value":22822},"Require",{"type":415,"tag":532,"props":22824,"children":22825},{"style":551},[22826],{"type":420,"value":664},{"type":415,"tag":532,"props":22828,"children":22829},{"style":551},[22830],{"type":420,"value":801},{"type":415,"tag":532,"props":22832,"children":22833},{"style":804},[22834],{"type":420,"value":22835},"sqlAdAdmin",{"type":415,"tag":532,"props":22837,"children":22838},{"style":551},[22839],{"type":420,"value":801},{"type":415,"tag":532,"props":22841,"children":22842},{"style":551},[22843],{"type":420,"value":674},{"type":415,"tag":532,"props":22845,"children":22846},{"class":534,"line":583},[22847,22851,22856,22860,22864,22868,22873,22877,22881,22886,22890],{"type":415,"tag":532,"props":22848,"children":22849},{"style":631},[22850],{"type":420,"value":634},{"type":415,"tag":532,"props":22852,"children":22853},{"style":631},[22854],{"type":420,"value":22855}," sqlAdAdminPassword",{"type":415,"tag":532,"props":22857,"children":22858},{"style":551},[22859],{"type":420,"value":644},{"type":415,"tag":532,"props":22861,"children":22862},{"style":545},[22863],{"type":420,"value":7206},{"type":415,"tag":532,"props":22865,"children":22866},{"style":551},[22867],{"type":420,"value":432},{"type":415,"tag":532,"props":22869,"children":22870},{"style":656},[22871],{"type":420,"value":22872},"RequireSecret",{"type":415,"tag":532,"props":22874,"children":22875},{"style":551},[22876],{"type":420,"value":664},{"type":415,"tag":532,"props":22878,"children":22879},{"style":551},[22880],{"type":420,"value":801},{"type":415,"tag":532,"props":22882,"children":22883},{"style":804},[22884],{"type":420,"value":22885},"sqlAdPassword",{"type":415,"tag":532,"props":22887,"children":22888},{"style":551},[22889],{"type":420,"value":801},{"type":415,"tag":532,"props":22891,"children":22892},{"style":551},[22893],{"type":420,"value":674},{"type":415,"tag":532,"props":22895,"children":22896},{"class":534,"line":617},[22897],{"type":415,"tag":532,"props":22898,"children":22899},{"emptyLinePlaceholder":621},[22900],{"type":420,"value":624},{"type":415,"tag":532,"props":22902,"children":22903},{"class":534,"line":627},[22904,22908,22913,22917,22921,22926,22930,22934,22939,22943,22947,22951],{"type":415,"tag":532,"props":22905,"children":22906},{"style":631},[22907],{"type":420,"value":634},{"type":415,"tag":532,"props":22909,"children":22910},{"style":631},[22911],{"type":420,"value":22912}," sqlAdAdmin",{"type":415,"tag":532,"props":22914,"children":22915},{"style":551},[22916],{"type":420,"value":644},{"type":415,"tag":532,"props":22918,"children":22919},{"style":551},[22920],{"type":420,"value":3276},{"type":415,"tag":532,"props":22922,"children":22923},{"style":631},[22924],{"type":420,"value":22925}," User",{"type":415,"tag":532,"props":22927,"children":22928},{"style":551},[22929],{"type":420,"value":664},{"type":415,"tag":532,"props":22931,"children":22932},{"style":551},[22933],{"type":420,"value":801},{"type":415,"tag":532,"props":22935,"children":22936},{"style":804},[22937],{"type":420,"value":22938},"sqlAdmin",{"type":415,"tag":532,"props":22940,"children":22941},{"style":551},[22942],{"type":420,"value":801},{"type":415,"tag":532,"props":22944,"children":22945},{"style":551},[22946],{"type":420,"value":1099},{"type":415,"tag":532,"props":22948,"children":22949},{"style":551},[22950],{"type":420,"value":3276},{"type":415,"tag":532,"props":22952,"children":22953},{"style":631},[22954],{"type":420,"value":22955}," UserArgs\n",{"type":415,"tag":532,"props":22957,"children":22958},{"class":534,"line":677},[22959],{"type":415,"tag":532,"props":22960,"children":22961},{"style":551},[22962],{"type":420,"value":764},{"type":415,"tag":532,"props":22964,"children":22965},{"class":534,"line":719},[22966,22971,22975,22979],{"type":415,"tag":532,"props":22967,"children":22968},{"style":545},[22969],{"type":420,"value":22970},"    UserPrincipalName ",{"type":415,"tag":532,"props":22972,"children":22973},{"style":551},[22974],{"type":420,"value":1134},{"type":415,"tag":532,"props":22976,"children":22977},{"style":545},[22978],{"type":420,"value":22805},{"type":415,"tag":532,"props":22980,"children":22981},{"style":551},[22982],{"type":420,"value":7400},{"type":415,"tag":532,"props":22984,"children":22985},{"class":534,"line":758},[22986,22991,22995,22999],{"type":415,"tag":532,"props":22987,"children":22988},{"style":545},[22989],{"type":420,"value":22990},"    Password ",{"type":415,"tag":532,"props":22992,"children":22993},{"style":551},[22994],{"type":420,"value":1134},{"type":415,"tag":532,"props":22996,"children":22997},{"style":545},[22998],{"type":420,"value":22855},{"type":415,"tag":532,"props":23000,"children":23001},{"style":551},[23002],{"type":420,"value":7400},{"type":415,"tag":532,"props":23004,"children":23005},{"class":534,"line":767},[23006,23010,23014,23018,23023],{"type":415,"tag":532,"props":23007,"children":23008},{"style":545},[23009],{"type":420,"value":8956},{"type":415,"tag":532,"props":23011,"children":23012},{"style":551},[23013],{"type":420,"value":1134},{"type":415,"tag":532,"props":23015,"children":23016},{"style":551},[23017],{"type":420,"value":4041},{"type":415,"tag":532,"props":23019,"children":23020},{"style":804},[23021],{"type":420,"value":23022},"Global SQL Admin",{"type":415,"tag":532,"props":23024,"children":23025},{"style":551},[23026],{"type":420,"value":4051},{"type":415,"tag":532,"props":23028,"children":23029},{"class":534,"line":819},[23030],{"type":415,"tag":532,"props":23031,"children":23032},{"style":551},[23033],{"type":420,"value":856},{"type":415,"tag":416,"props":23035,"children":23036},{},[23037,23039,23045,23047,23053,23055,23062],{"type":420,"value":23038},"To create a new Azure AD user we need a login (it will be the email of the new user in our tenant) and a password. In this example, we retrieve these values from the ",{"type":415,"tag":423,"props":23040,"children":23043},{"href":23041,"rel":23042},"https://www.pulumi.com/docs/intro/concepts/config/",[427],[23044],{"type":420,"value":262},{"type":420,"value":23046}," which is stored in the YAML settings file. You can notice there that we retrieve a secret (the password) from the configuration thanks to the ",{"type":415,"tag":468,"props":23048,"children":23050},{"className":23049},[],[23051],{"type":420,"value":23052},"config.RequireSecret",{"type":420,"value":23054}," method. Indeed to avoid exposing a secret in the configuration file or the state file, Pulumi has ",{"type":415,"tag":423,"props":23056,"children":23059},{"href":23057,"rel":23058},"https://www.pulumi.com/docs/intro/concepts/secrets/",[427],[23060],{"type":420,"value":23061},"built-in support for secret encryption and decryption",{"type":420,"value":23063}," (not sure Terraform folks can say the same thing 😉).",{"type":415,"tag":482,"props":23065,"children":23067},{"id":23066},"create-the-azure-sql-server-and-its-database",[23068],{"type":420,"value":23069},"Create the Azure SQL Server and its database.",{"type":415,"tag":416,"props":23071,"children":23072},{},[23073],{"type":420,"value":23074},"Now that we have our administrator account, we can create the Azure SQL Server:",{"type":415,"tag":523,"props":23076,"children":23078},{"className":525,"code":23077,"language":326,"meta":401,"style":401},"var sqlServer = new Server($\"sql-sqlDbWithAzureAd-{Deployment.Instance.StackName}\", new ServerArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    Administrators = new ServerExternalAdministratorArgs\n    {\n        Login = sqlAdAdmin.UserPrincipalName,\n        Sid = sqlAdAdmin.Id,\n        AzureADOnlyAuthentication = true,\n        AdministratorType = AdministratorType.ActiveDirectory,\n        PrincipalType = PrincipalType.User,\n    },\n});\n",[23079],{"type":415,"tag":468,"props":23080,"children":23081},{"__ignoreMap":401},[23082,23161,23168,23195,23216,23223,23252,23280,23300,23330,23359,23366],{"type":415,"tag":532,"props":23083,"children":23084},{"class":534,"line":535},[23085,23089,23094,23098,23102,23107,23111,23115,23120,23124,23128,23132,23136,23140,23144,23148,23152,23156],{"type":415,"tag":532,"props":23086,"children":23087},{"style":631},[23088],{"type":420,"value":634},{"type":415,"tag":532,"props":23090,"children":23091},{"style":631},[23092],{"type":420,"value":23093}," sqlServer",{"type":415,"tag":532,"props":23095,"children":23096},{"style":551},[23097],{"type":420,"value":644},{"type":415,"tag":532,"props":23099,"children":23100},{"style":551},[23101],{"type":420,"value":3276},{"type":415,"tag":532,"props":23103,"children":23104},{"style":631},[23105],{"type":420,"value":23106}," Server",{"type":415,"tag":532,"props":23108,"children":23109},{"style":551},[23110],{"type":420,"value":664},{"type":415,"tag":532,"props":23112,"children":23113},{"style":551},[23114],{"type":420,"value":8738},{"type":415,"tag":532,"props":23116,"children":23117},{"style":804},[23118],{"type":420,"value":23119},"sql-sqlDbWithAzureAd-",{"type":415,"tag":532,"props":23121,"children":23122},{"style":551},[23123],{"type":420,"value":8748},{"type":415,"tag":532,"props":23125,"children":23126},{"style":545},[23127],{"type":420,"value":20190},{"type":415,"tag":532,"props":23129,"children":23130},{"style":551},[23131],{"type":420,"value":432},{"type":415,"tag":532,"props":23133,"children":23134},{"style":545},[23135],{"type":420,"value":20199},{"type":415,"tag":532,"props":23137,"children":23138},{"style":551},[23139],{"type":420,"value":432},{"type":415,"tag":532,"props":23141,"children":23142},{"style":545},[23143],{"type":420,"value":20241},{"type":415,"tag":532,"props":23145,"children":23146},{"style":551},[23147],{"type":420,"value":4502},{"type":415,"tag":532,"props":23149,"children":23150},{"style":551},[23151],{"type":420,"value":1099},{"type":415,"tag":532,"props":23153,"children":23154},{"style":551},[23155],{"type":420,"value":3276},{"type":415,"tag":532,"props":23157,"children":23158},{"style":631},[23159],{"type":420,"value":23160}," ServerArgs\n",{"type":415,"tag":532,"props":23162,"children":23163},{"class":534,"line":566},[23164],{"type":415,"tag":532,"props":23165,"children":23166},{"style":551},[23167],{"type":420,"value":764},{"type":415,"tag":532,"props":23169,"children":23170},{"class":534,"line":583},[23171,23175,23179,23183,23187,23191],{"type":415,"tag":532,"props":23172,"children":23173},{"style":545},[23174],{"type":420,"value":20394},{"type":415,"tag":532,"props":23176,"children":23177},{"style":551},[23178],{"type":420,"value":1134},{"type":415,"tag":532,"props":23180,"children":23181},{"style":545},[23182],{"type":420,"value":20155},{"type":415,"tag":532,"props":23184,"children":23185},{"style":551},[23186],{"type":420,"value":432},{"type":415,"tag":532,"props":23188,"children":23189},{"style":545},[23190],{"type":420,"value":1344},{"type":415,"tag":532,"props":23192,"children":23193},{"style":551},[23194],{"type":420,"value":7400},{"type":415,"tag":532,"props":23196,"children":23197},{"class":534,"line":617},[23198,23203,23207,23211],{"type":415,"tag":532,"props":23199,"children":23200},{"style":545},[23201],{"type":420,"value":23202},"    Administrators ",{"type":415,"tag":532,"props":23204,"children":23205},{"style":551},[23206],{"type":420,"value":1134},{"type":415,"tag":532,"props":23208,"children":23209},{"style":551},[23210],{"type":420,"value":3276},{"type":415,"tag":532,"props":23212,"children":23213},{"style":631},[23214],{"type":420,"value":23215}," ServerExternalAdministratorArgs\n",{"type":415,"tag":532,"props":23217,"children":23218},{"class":534,"line":627},[23219],{"type":415,"tag":532,"props":23220,"children":23221},{"style":551},[23222],{"type":420,"value":1121},{"type":415,"tag":532,"props":23224,"children":23225},{"class":534,"line":677},[23226,23231,23235,23239,23243,23248],{"type":415,"tag":532,"props":23227,"children":23228},{"style":545},[23229],{"type":420,"value":23230},"        Login ",{"type":415,"tag":532,"props":23232,"children":23233},{"style":551},[23234],{"type":420,"value":1134},{"type":415,"tag":532,"props":23236,"children":23237},{"style":545},[23238],{"type":420,"value":22912},{"type":415,"tag":532,"props":23240,"children":23241},{"style":551},[23242],{"type":420,"value":432},{"type":415,"tag":532,"props":23244,"children":23245},{"style":545},[23246],{"type":420,"value":23247},"UserPrincipalName",{"type":415,"tag":532,"props":23249,"children":23250},{"style":551},[23251],{"type":420,"value":7400},{"type":415,"tag":532,"props":23253,"children":23254},{"class":534,"line":719},[23255,23260,23264,23268,23272,23276],{"type":415,"tag":532,"props":23256,"children":23257},{"style":545},[23258],{"type":420,"value":23259},"        Sid ",{"type":415,"tag":532,"props":23261,"children":23262},{"style":551},[23263],{"type":420,"value":1134},{"type":415,"tag":532,"props":23265,"children":23266},{"style":545},[23267],{"type":420,"value":22912},{"type":415,"tag":532,"props":23269,"children":23270},{"style":551},[23271],{"type":420,"value":432},{"type":415,"tag":532,"props":23273,"children":23274},{"style":545},[23275],{"type":420,"value":7750},{"type":415,"tag":532,"props":23277,"children":23278},{"style":551},[23279],{"type":420,"value":7400},{"type":415,"tag":532,"props":23281,"children":23282},{"class":534,"line":758},[23283,23288,23292,23296],{"type":415,"tag":532,"props":23284,"children":23285},{"style":545},[23286],{"type":420,"value":23287},"        AzureADOnlyAuthentication ",{"type":415,"tag":532,"props":23289,"children":23290},{"style":551},[23291],{"type":420,"value":1134},{"type":415,"tag":532,"props":23293,"children":23294},{"style":1938},[23295],{"type":420,"value":1941},{"type":415,"tag":532,"props":23297,"children":23298},{"style":551},[23299],{"type":420,"value":7400},{"type":415,"tag":532,"props":23301,"children":23302},{"class":534,"line":767},[23303,23308,23312,23317,23321,23326],{"type":415,"tag":532,"props":23304,"children":23305},{"style":545},[23306],{"type":420,"value":23307},"        AdministratorType ",{"type":415,"tag":532,"props":23309,"children":23310},{"style":551},[23311],{"type":420,"value":1134},{"type":415,"tag":532,"props":23313,"children":23314},{"style":545},[23315],{"type":420,"value":23316}," AdministratorType",{"type":415,"tag":532,"props":23318,"children":23319},{"style":551},[23320],{"type":420,"value":432},{"type":415,"tag":532,"props":23322,"children":23323},{"style":545},[23324],{"type":420,"value":23325},"ActiveDirectory",{"type":415,"tag":532,"props":23327,"children":23328},{"style":551},[23329],{"type":420,"value":7400},{"type":415,"tag":532,"props":23331,"children":23332},{"class":534,"line":819},[23333,23338,23342,23346,23350,23355],{"type":415,"tag":532,"props":23334,"children":23335},{"style":545},[23336],{"type":420,"value":23337},"        PrincipalType ",{"type":415,"tag":532,"props":23339,"children":23340},{"style":551},[23341],{"type":420,"value":1134},{"type":415,"tag":532,"props":23343,"children":23344},{"style":545},[23345],{"type":420,"value":9224},{"type":415,"tag":532,"props":23347,"children":23348},{"style":551},[23349],{"type":420,"value":432},{"type":415,"tag":532,"props":23351,"children":23352},{"style":545},[23353],{"type":420,"value":23354},"User",{"type":415,"tag":532,"props":23356,"children":23357},{"style":551},[23358],{"type":420,"value":7400},{"type":415,"tag":532,"props":23360,"children":23361},{"class":534,"line":850},[23362],{"type":415,"tag":532,"props":23363,"children":23364},{"style":551},[23365],{"type":420,"value":7650},{"type":415,"tag":532,"props":23367,"children":23368},{"class":534,"line":859},[23369],{"type":415,"tag":532,"props":23370,"children":23371},{"style":551},[23372],{"type":420,"value":856},{"type":415,"tag":416,"props":23374,"children":23375},{},[23376,23378,23383],{"type":420,"value":23377},"Nothing special here: we are using the variable ",{"type":415,"tag":468,"props":23379,"children":23381},{"className":23380},[],[23382],{"type":420,"value":22938},{"type":420,"value":23384}," that is our newly created user to set the administrator of the SQL Server and we set the authentication to Azure AD only. We can then create the database:",{"type":415,"tag":523,"props":23386,"children":23388},{"className":525,"code":23387,"language":326,"meta":401,"style":401},"var database = new Database(\"sqldb-sqlDbWithAzureAd-Main\", new DatabaseArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    ServerName = sqlServer.Name,\n    Sku = new SkuArgs\n    {\n        Name = \"Basic\"\n    }\n});\n",[23389],{"type":415,"tag":468,"props":23390,"children":23391},{"__ignoreMap":401},[23392,23447,23454,23481,23509,23529,23536,23559,23566],{"type":415,"tag":532,"props":23393,"children":23394},{"class":534,"line":535},[23395,23399,23404,23408,23412,23417,23421,23425,23430,23434,23438,23442],{"type":415,"tag":532,"props":23396,"children":23397},{"style":631},[23398],{"type":420,"value":634},{"type":415,"tag":532,"props":23400,"children":23401},{"style":631},[23402],{"type":420,"value":23403}," database",{"type":415,"tag":532,"props":23405,"children":23406},{"style":551},[23407],{"type":420,"value":644},{"type":415,"tag":532,"props":23409,"children":23410},{"style":551},[23411],{"type":420,"value":3276},{"type":415,"tag":532,"props":23413,"children":23414},{"style":631},[23415],{"type":420,"value":23416}," Database",{"type":415,"tag":532,"props":23418,"children":23419},{"style":551},[23420],{"type":420,"value":664},{"type":415,"tag":532,"props":23422,"children":23423},{"style":551},[23424],{"type":420,"value":801},{"type":415,"tag":532,"props":23426,"children":23427},{"style":804},[23428],{"type":420,"value":23429},"sqldb-sqlDbWithAzureAd-Main",{"type":415,"tag":532,"props":23431,"children":23432},{"style":551},[23433],{"type":420,"value":801},{"type":415,"tag":532,"props":23435,"children":23436},{"style":551},[23437],{"type":420,"value":1099},{"type":415,"tag":532,"props":23439,"children":23440},{"style":551},[23441],{"type":420,"value":3276},{"type":415,"tag":532,"props":23443,"children":23444},{"style":631},[23445],{"type":420,"value":23446}," DatabaseArgs\n",{"type":415,"tag":532,"props":23448,"children":23449},{"class":534,"line":566},[23450],{"type":415,"tag":532,"props":23451,"children":23452},{"style":551},[23453],{"type":420,"value":764},{"type":415,"tag":532,"props":23455,"children":23456},{"class":534,"line":583},[23457,23461,23465,23469,23473,23477],{"type":415,"tag":532,"props":23458,"children":23459},{"style":545},[23460],{"type":420,"value":20394},{"type":415,"tag":532,"props":23462,"children":23463},{"style":551},[23464],{"type":420,"value":1134},{"type":415,"tag":532,"props":23466,"children":23467},{"style":545},[23468],{"type":420,"value":20155},{"type":415,"tag":532,"props":23470,"children":23471},{"style":551},[23472],{"type":420,"value":432},{"type":415,"tag":532,"props":23474,"children":23475},{"style":545},[23476],{"type":420,"value":1344},{"type":415,"tag":532,"props":23478,"children":23479},{"style":551},[23480],{"type":420,"value":7400},{"type":415,"tag":532,"props":23482,"children":23483},{"class":534,"line":617},[23484,23489,23493,23497,23501,23505],{"type":415,"tag":532,"props":23485,"children":23486},{"style":545},[23487],{"type":420,"value":23488},"    ServerName ",{"type":415,"tag":532,"props":23490,"children":23491},{"style":551},[23492],{"type":420,"value":1134},{"type":415,"tag":532,"props":23494,"children":23495},{"style":545},[23496],{"type":420,"value":23093},{"type":415,"tag":532,"props":23498,"children":23499},{"style":551},[23500],{"type":420,"value":432},{"type":415,"tag":532,"props":23502,"children":23503},{"style":545},[23504],{"type":420,"value":1344},{"type":415,"tag":532,"props":23506,"children":23507},{"style":551},[23508],{"type":420,"value":7400},{"type":415,"tag":532,"props":23510,"children":23511},{"class":534,"line":627},[23512,23516,23520,23524],{"type":415,"tag":532,"props":23513,"children":23514},{"style":545},[23515],{"type":420,"value":20459},{"type":415,"tag":532,"props":23517,"children":23518},{"style":551},[23519],{"type":420,"value":1134},{"type":415,"tag":532,"props":23521,"children":23522},{"style":551},[23523],{"type":420,"value":3276},{"type":415,"tag":532,"props":23525,"children":23526},{"style":631},[23527],{"type":420,"value":23528}," SkuArgs\n",{"type":415,"tag":532,"props":23530,"children":23531},{"class":534,"line":677},[23532],{"type":415,"tag":532,"props":23533,"children":23534},{"style":551},[23535],{"type":420,"value":1121},{"type":415,"tag":532,"props":23537,"children":23538},{"class":534,"line":719},[23539,23543,23547,23551,23555],{"type":415,"tag":532,"props":23540,"children":23541},{"style":545},[23542],{"type":420,"value":20528},{"type":415,"tag":532,"props":23544,"children":23545},{"style":551},[23546],{"type":420,"value":1134},{"type":415,"tag":532,"props":23548,"children":23549},{"style":551},[23550],{"type":420,"value":4041},{"type":415,"tag":532,"props":23552,"children":23553},{"style":804},[23554],{"type":420,"value":20508},{"type":415,"tag":532,"props":23556,"children":23557},{"style":551},[23558],{"type":420,"value":4051},{"type":415,"tag":532,"props":23560,"children":23561},{"class":534,"line":758},[23562],{"type":415,"tag":532,"props":23563,"children":23564},{"style":551},[23565],{"type":420,"value":1170},{"type":415,"tag":532,"props":23567,"children":23568},{"class":534,"line":767},[23569],{"type":415,"tag":532,"props":23570,"children":23571},{"style":551},[23572],{"type":420,"value":856},{"type":415,"tag":482,"props":23574,"children":23576},{"id":23575},"grant-sql-database-access-permissions-to-azure-ad-entities",[23577],{"type":420,"value":23578},"Grant SQL Database access permissions to Azure AD entities",{"type":415,"tag":416,"props":23580,"children":23581},{},[23582],{"type":420,"value":23583},"Once we have provisioned the Azure SQL Server and its database, here comes the tough part: we need to configure who can access the database. In a project, you will probably have to give access to some users and to the Azure resources that need to query the database (you will have to assign these resources a managed identity before that). But to keep things simple, we will just consider we need to grant SQL Database access to an Azure AD group. That could be a good way to do things by the way: create an Azure AD group, grant permissions to this group and add users and managed identities that need access to the database.",{"type":415,"tag":416,"props":23585,"children":23586},{},[23587,23589,23595],{"type":420,"value":23588},"Why did I say that this part was tough? It's because to grant SQL database permissions, we need to execute an SQL command on the Server as you can read ",{"type":415,"tag":423,"props":23590,"children":23593},{"href":23591,"rel":23592},"https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cef%2Cdotnet#grant-permissions-to-managed-identity",[427],[23594],{"type":420,"value":4269},{"type":420,"value":432},{"type":415,"tag":523,"props":23597,"children":23601},{"className":23598,"code":23599,"language":23600,"meta":401,"style":401},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE USER [\u003Cidentity-name>] FROM EXTERNAL PROVIDER;\nALTER ROLE db_datareader ADD MEMBER [\u003Cidentity-name>];\nALTER ROLE db_datawriter ADD MEMBER [\u003Cidentity-name>];\nGO\n","sql",[23602],{"type":415,"tag":468,"props":23603,"children":23604},{"__ignoreMap":401},[23605,23637,23665,23689],{"type":415,"tag":532,"props":23606,"children":23607},{"class":534,"line":535},[23608,23613,23618,23623,23628,23633],{"type":415,"tag":532,"props":23609,"children":23610},{"style":539},[23611],{"type":420,"value":23612},"CREATE",{"type":415,"tag":532,"props":23614,"children":23615},{"style":545},[23616],{"type":420,"value":23617}," USER [\u003Cidentity-name>] ",{"type":415,"tag":532,"props":23619,"children":23620},{"style":539},[23621],{"type":420,"value":23622},"FROM",{"type":415,"tag":532,"props":23624,"children":23625},{"style":539},[23626],{"type":420,"value":23627}," EXTERNAL",{"type":415,"tag":532,"props":23629,"children":23630},{"style":539},[23631],{"type":420,"value":23632}," PROVIDER",{"type":415,"tag":532,"props":23634,"children":23635},{"style":545},[23636],{"type":420,"value":563},{"type":415,"tag":532,"props":23638,"children":23639},{"class":534,"line":566},[23640,23645,23650,23655,23660],{"type":415,"tag":532,"props":23641,"children":23642},{"style":539},[23643],{"type":420,"value":23644},"ALTER",{"type":415,"tag":532,"props":23646,"children":23647},{"style":539},[23648],{"type":420,"value":23649}," ROLE",{"type":415,"tag":532,"props":23651,"children":23652},{"style":545},[23653],{"type":420,"value":23654}," db_datareader ",{"type":415,"tag":532,"props":23656,"children":23657},{"style":539},[23658],{"type":420,"value":23659},"ADD",{"type":415,"tag":532,"props":23661,"children":23662},{"style":545},[23663],{"type":420,"value":23664}," MEMBER [\u003Cidentity-name>];\n",{"type":415,"tag":532,"props":23666,"children":23667},{"class":534,"line":583},[23668,23672,23676,23681,23685],{"type":415,"tag":532,"props":23669,"children":23670},{"style":539},[23671],{"type":420,"value":23644},{"type":415,"tag":532,"props":23673,"children":23674},{"style":539},[23675],{"type":420,"value":23649},{"type":415,"tag":532,"props":23677,"children":23678},{"style":545},[23679],{"type":420,"value":23680}," db_datawriter ",{"type":415,"tag":532,"props":23682,"children":23683},{"style":539},[23684],{"type":420,"value":23659},{"type":415,"tag":532,"props":23686,"children":23687},{"style":545},[23688],{"type":420,"value":23664},{"type":415,"tag":532,"props":23690,"children":23691},{"class":534,"line":617},[23692],{"type":415,"tag":532,"props":23693,"children":23694},{"style":539},[23695],{"type":420,"value":23696},"GO\n",{"type":415,"tag":416,"props":23698,"children":23699},{},[23700,23702,23708,23709,23715],{"type":420,"value":23701},"With this command, we are creating a user and giving ",{"type":415,"tag":468,"props":23703,"children":23705},{"className":23704},[],[23706],{"type":420,"value":23707},"db_datareader",{"type":420,"value":6722},{"type":415,"tag":468,"props":23710,"children":23712},{"className":23711},[],[23713],{"type":420,"value":23714},"db_datawriter",{"type":420,"value":23716}," roles. However it is not a classical user, it's a user that is \"external\" to the database: in our case, it corresponds to an Azure AD entity (a user, group, or application).",{"type":415,"tag":416,"props":23718,"children":23719},{},[23720],{"type":420,"value":23721},"So it's not just about setting a property to properly configure an Azure resource, it's a bit more complicated.",{"type":415,"tag":416,"props":23723,"children":23724},{},[23725],{"type":420,"value":23726},"I see multiple ways of doing that:",{"type":415,"tag":508,"props":23728,"children":23729},{},[23730,23735,23740],{"type":415,"tag":512,"props":23731,"children":23732},{},[23733],{"type":420,"value":23734},"Create a new Pulumi provider \"SQL Server provider\" that is to able manage users in an SQL Server database",{"type":415,"tag":512,"props":23736,"children":23737},{},[23738],{"type":420,"value":23739},"Write custom C# code that executes the SQL command once the database is created",{"type":415,"tag":512,"props":23741,"children":23742},{},[23743,23745,23751],{"type":420,"value":23744},"Use the Pulumi Command provider to execute the SQL command using the ",{"type":415,"tag":468,"props":23746,"children":23748},{"className":23747},[],[23749],{"type":420,"value":23750},"sqlcmd",{"type":420,"value":23752}," utility",{"type":415,"tag":416,"props":23754,"children":23755},{},[23756],{"type":420,"value":23757},"Let's review these solutions.",{"type":415,"tag":3914,"props":23759,"children":23761},{"id":23760},"new-sql-server-provider",[23762],{"type":420,"value":23763},"New \"SQL Server Provider\"",{"type":415,"tag":416,"props":23765,"children":23766},{},[23767,23769,23776],{"type":420,"value":23768},"To manage SQL Server resources like users and roles, we can create a complete provider. We could create it from scratch of course or use this ",{"type":415,"tag":423,"props":23770,"children":23773},{"href":23771,"rel":23772},"https://github.com/pulumi/pulumi-provider-boilerplate",[427],[23774],{"type":420,"value":23775},"Pulumi GitHub repository",{"type":420,"value":23777}," that provides some boilerplate code to create a Pulumi provider. Usually, Pulumi providers are written in Go (like the Terraform providers by the way) and generate SDKs for all programming languages supported by Pulumi.",{"type":415,"tag":416,"props":23779,"children":23780},{},[23781],{"type":415,"tag":3882,"props":23782,"children":23786},{"alt":23783,"className":23784,"src":23785},"xyz Pulumi Provider boilerplate code repository on GitHub.",[3886,3887],"/posts/images/sqldatabase_ad_provider_1.png",[],{"type":415,"tag":416,"props":23788,"children":23789},{},[23790,23792,23799,23801,23808,23810,23817],{"type":420,"value":23791},"Another way would be to adapt the existing ",{"type":415,"tag":423,"props":23793,"children":23796},{"href":23794,"rel":23795},"https://registry.terraform.io/providers/betr-io/mssql/latest/docs",[427],[23797],{"type":420,"value":23798},"Microsoft SQL Server Provider",{"type":420,"value":23800}," for Terraform. This Terraform provider made by the community enables you to create and manage logins and users on a SQL Server. I talked about \"adapting\" this provider because you can create a Pulumi provider out of a Terraform provider by using the ",{"type":415,"tag":423,"props":23802,"children":23805},{"href":23803,"rel":23804},"https://github.com/pulumi/pulumi-terraform-bridge",[427],[23806],{"type":420,"value":23807},"Pulumi Terraform Bridge",{"type":420,"value":23809},". That's great because instead of reinventing the wheel you can benefit from Terraform ecosystem by creating a Pulumi provider that wraps an existing Terraform provider. This ",{"type":415,"tag":423,"props":23811,"children":23814},{"href":23812,"rel":23813},"https://github.com/pulumi/pulumi-tf-provider-boilerplate",[427],[23815],{"type":420,"value":23816},"GitHub repository",{"type":420,"value":23818}," contains boilerplate code to do exactly that.",{"type":415,"tag":416,"props":23820,"children":23821},{},[23822],{"type":415,"tag":3882,"props":23823,"children":23827},{"alt":23824,"className":23825,"src":23826},"Pulumi Terraform Bridge repository on GitHub.",[3886,3887],"/posts/images/sqldatabase_ad_provider_2.png",[],{"type":415,"tag":434,"props":23829,"children":23830},{"icon":1382},[23831],{"type":415,"tag":416,"props":23832,"children":23833},{},[23834,23836,23842],{"type":420,"value":23835},"You might have noticed that I sometimes criticize Terraform in my articles. That's not because I think Terraform is a bad infrastructure as code solution, in fact, I think it is a great solution with a rich ecosystem. However, I am critical of Terraform because I believe Infrastructure as Code should be done with programming languages instead of Domain-Specific Languages. Moreover, there are some areas (API coverage of major cloud providers, security, IDE support, ...) where I found Terraform is not good enough, especially compared to other platforms like Pulumi. So I am always a bit disappointed when I see that many people choose by default Terraform as their infrastructure as code platform without considering alternatives (and I am not only talking about Pulumi, there are also Farmer and Bicep for instance), even when these alternatives would be better suited to their use cases. That being said, Terraform has also advantages like its great community that creates and contributes to many providers like the ",{"type":415,"tag":468,"props":23837,"children":23839},{"className":23838},[],[23840],{"type":420,"value":23841},"mssql",{"type":420,"value":23843}," one.",{"type":415,"tag":416,"props":23845,"children":23846},{},[23847,23849,23854],{"type":420,"value":23848},"This first solution of creating a new \"SQL Server Provider\" (whether it be from scratch, from boilerplate code, or from the ",{"type":415,"tag":468,"props":23850,"children":23852},{"className":23851},[],[23853],{"type":420,"value":23841},{"type":420,"value":23855}," Terraform provider) is interesting but could be time-consuming because there are some things to set up and some amount of code to write.",{"type":415,"tag":3914,"props":23857,"children":23859},{"id":23858},"custom-c-code",[23860],{"type":420,"value":23861},"Custom C# code",{"type":415,"tag":416,"props":23863,"children":23864},{},[23865,23867,23879,23881,23888],{"type":420,"value":23866},"When you need to do something specific and there is no existing provider that can help you with it, you can just write the code to do it yourself without creating a complete provider. It's one of the reasons why I like Pulumi, even if you are doing Infrastructure as Code, at the end of the day you are just developing software so you can code what you need in the language you are familiar with. For instance, as I am developing in .NET, I can use the ",{"type":415,"tag":423,"props":23868,"children":23871},{"href":23869,"rel":23870},"https://docs.microsoft.com/en-us/sql/connect/ado-net/overview-sqlclient-driver",[427],[23872,23877],{"type":415,"tag":468,"props":23873,"children":23875},{"className":23874},[],[23876],{"type":420,"value":22719},{"type":420,"value":23878}," library",{"type":420,"value":23880}," (which is a data provider for Azure SQL Database) to connect and send commands to the database. And if I want to use ",{"type":415,"tag":423,"props":23882,"children":23885},{"href":23883,"rel":23884},"https://github.com/DapperLib/Dapper",[427],[23886],{"type":420,"value":23887},"Dapper",{"type":420,"value":23889}," on top of it because that's the library I am used to for querying a database I can. Hence writing the code that executes on the database the SQL command we have previously seen should not be very difficult.",{"type":415,"tag":416,"props":23891,"children":23892},{},[23893],{"type":420,"value":23894},"Now, even if we are using imperative language in Pulumi to write the infrastructure code it's still declarative infrastructure as code with a state. Therefore, we have to be careful about how and when this custom code should be executed.",{"type":415,"tag":416,"props":23896,"children":23897},{},[23898,23900,23905],{"type":420,"value":23899},"The easiest way is to use an ",{"type":415,"tag":468,"props":23901,"children":23903},{"className":23902},[],[23904],{"type":420,"value":8485},{"type":420,"value":23906}," method on an output of the database like this:",{"type":415,"tag":523,"props":23908,"children":23910},{"className":525,"code":23909,"language":326,"meta":401,"style":401},"database.Name.Apply(name =>\n{\n    /*** \n     * Indempotent code using Microsoft.Data.SqlClient library\n     * to execute the SQL command that assigns the correct roles\n     * to the Azure AD group we want to have access to the database.\n    ***/ \n    return true;\n});\n",[23911],{"type":415,"tag":468,"props":23912,"children":23913},{"__ignoreMap":401},[23914,23950,23957,23965,23973,23981,23989,24001,24016],{"type":415,"tag":532,"props":23915,"children":23916},{"class":534,"line":535},[23917,23922,23926,23930,23934,23938,23942,23946],{"type":415,"tag":532,"props":23918,"children":23919},{"style":545},[23920],{"type":420,"value":23921},"database",{"type":415,"tag":532,"props":23923,"children":23924},{"style":551},[23925],{"type":420,"value":432},{"type":415,"tag":532,"props":23927,"children":23928},{"style":545},[23929],{"type":420,"value":1344},{"type":415,"tag":532,"props":23931,"children":23932},{"style":551},[23933],{"type":420,"value":432},{"type":415,"tag":532,"props":23935,"children":23936},{"style":656},[23937],{"type":420,"value":8485},{"type":415,"tag":532,"props":23939,"children":23940},{"style":551},[23941],{"type":420,"value":664},{"type":415,"tag":532,"props":23943,"children":23944},{"style":631},[23945],{"type":420,"value":3535},{"type":415,"tag":532,"props":23947,"children":23948},{"style":551},[23949],{"type":420,"value":755},{"type":415,"tag":532,"props":23951,"children":23952},{"class":534,"line":566},[23953],{"type":415,"tag":532,"props":23954,"children":23955},{"style":551},[23956],{"type":420,"value":764},{"type":415,"tag":532,"props":23958,"children":23959},{"class":534,"line":583},[23960],{"type":415,"tag":532,"props":23961,"children":23962},{"style":5425},[23963],{"type":420,"value":23964},"    /*** \n",{"type":415,"tag":532,"props":23966,"children":23967},{"class":534,"line":617},[23968],{"type":415,"tag":532,"props":23969,"children":23970},{"style":5425},[23971],{"type":420,"value":23972},"     * Indempotent code using Microsoft.Data.SqlClient library\n",{"type":415,"tag":532,"props":23974,"children":23975},{"class":534,"line":627},[23976],{"type":415,"tag":532,"props":23977,"children":23978},{"style":5425},[23979],{"type":420,"value":23980},"     * to execute the SQL command that assigns the correct roles\n",{"type":415,"tag":532,"props":23982,"children":23983},{"class":534,"line":677},[23984],{"type":415,"tag":532,"props":23985,"children":23986},{"style":5425},[23987],{"type":420,"value":23988},"     * to the Azure AD group we want to have access to the database.\n",{"type":415,"tag":532,"props":23990,"children":23991},{"class":534,"line":719},[23992,23997],{"type":415,"tag":532,"props":23993,"children":23994},{"style":5425},[23995],{"type":420,"value":23996},"    ***/",{"type":415,"tag":532,"props":23998,"children":23999},{"style":545},[24000],{"type":420,"value":5637},{"type":415,"tag":532,"props":24002,"children":24003},{"class":534,"line":758},[24004,24008,24012],{"type":415,"tag":532,"props":24005,"children":24006},{"style":1241},[24007],{"type":420,"value":8778},{"type":415,"tag":532,"props":24009,"children":24010},{"style":1938},[24011],{"type":420,"value":1941},{"type":415,"tag":532,"props":24013,"children":24014},{"style":551},[24015],{"type":420,"value":563},{"type":415,"tag":532,"props":24017,"children":24018},{"class":534,"line":767},[24019],{"type":415,"tag":532,"props":24020,"children":24021},{"style":551},[24022],{"type":420,"value":856},{"type":415,"tag":416,"props":24024,"children":24025},{},[24026,24028,24033],{"type":420,"value":24027},"The code in the ",{"type":415,"tag":468,"props":24029,"children":24031},{"className":24030},[],[24032],{"type":420,"value":8485},{"type":420,"value":24034}," will execute on every run after the resource is created, that is why it needs to be idempotent. Having to make the code idempotent is a constraint that I would prefer to avoid but at least it gives us a simple way to execute the code that grants access to the database.",{"type":415,"tag":416,"props":24036,"children":24037},{},[24038,24040,24047,24049,24056,24058,24065],{"type":420,"value":24039},"Another way would be to use ",{"type":415,"tag":423,"props":24041,"children":24044},{"href":24042,"rel":24043},"https://www.pulumi.com/docs/intro/concepts/resources/dynamic-providers/",[427],[24045],{"type":420,"value":24046},"Dynamic Providers",{"type":420,"value":24048}," whose purpose is exactly that: do an infrastructure task that no existing provider can help you deliver. You can see some use cases of dynamic providers in ",{"type":415,"tag":423,"props":24050,"children":24053},{"href":24051,"rel":24052},"https://www.pulumi.com/blog/dynamic-providers/#sample-use-cases",[427],[24054],{"type":420,"value":24055},"this Pulumi article",{"type":420,"value":24057},". In our use case, we could imagine writing a dynamic resource provider for an Azure AD entity user in an Azure SQL Database.  We would have to implement the different CRUD operations to handle the different use cases properly (a user is added, a user is removed, user roles are updated, ...). Unfortunately, as you can see in ",{"type":415,"tag":423,"props":24059,"children":24062},{"href":24060,"rel":24061},"https://github.com/pulumi/pulumi/issues/3638",[427],[24063],{"type":420,"value":24064},"this GitHub issue",{"type":420,"value":24066},", .NET Dynamic Providers are not yet supported (only TypesScript, JavaScript and Python are for the moment). It's a shame because Dynamic Providers provide an easy and efficient way of supporting custom resource types.",{"type":415,"tag":3914,"props":24068,"children":24070},{"id":24069},"command-provider-with-the-sqlcmd-utility",[24071,24073,24078],{"type":420,"value":24072},"Command provider with the ",{"type":415,"tag":468,"props":24074,"children":24076},{"className":24075},[],[24077],{"type":420,"value":23750},{"type":420,"value":23752},{"type":415,"tag":416,"props":24080,"children":24081},{},[24082,24088,24090,24101,24103,24108,24110,24117],{"type":415,"tag":423,"props":24083,"children":24085},{"href":23591,"rel":24084},[427],[24086],{"type":420,"value":24087},"The Microsoft tutorial",{"type":420,"value":24089},", that shows how to grant database permissions to an Azure AD entity, explains how the necessary SQL commands can be run using the ",{"type":415,"tag":423,"props":24091,"children":24094},{"href":24092,"rel":24093},"https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility",[427],[24095,24100],{"type":415,"tag":468,"props":24096,"children":24098},{"className":24097},[],[24099],{"type":420,"value":23750},{"type":420,"value":23752},{"type":420,"value":24102},". So instead of writing some C# code to do the same, an interesting idea would be to directly run the ",{"type":415,"tag":468,"props":24104,"children":24106},{"className":24105},[],[24107],{"type":420,"value":23750},{"type":420,"value":24109}," utility. And you know what? There is a Pulumi provider for executing commands and scripts: ",{"type":415,"tag":423,"props":24111,"children":24114},{"href":24112,"rel":24113},"https://www.pulumi.com/registry/packages/command/api-docs/",[427],[24115],{"type":420,"value":24116},"the Command Provider",{"type":420,"value":432},{"type":415,"tag":416,"props":24119,"children":24120},{},[24121],{"type":415,"tag":3882,"props":24122,"children":24126},{"alt":24123,"className":24124,"src":24125},"Pulumi Command Provider on GitHub.",[3886,3887],"/posts/images/sqldatabase_ad_pulumi_1.png",[],{"type":415,"tag":416,"props":24128,"children":24129},{},[24130,24132,24137,24139,24145,24147,24152],{"type":420,"value":24131},"Because it's a Pulumi provider, the ",{"type":415,"tag":468,"props":24133,"children":24135},{"className":24134},[],[24136],{"type":420,"value":23750},{"type":420,"value":24138}," command would be executed \"as part of the Pulumi resource model\" which means the scripts would be executed at the corresponding time of the resource life-cycle (the ",{"type":415,"tag":468,"props":24140,"children":24142},{"className":24141},[],[24143],{"type":420,"value":24144},"create",{"type":420,"value":24146}," script when the resource is created and so on). So it's very nice and not the same as executing the ",{"type":415,"tag":468,"props":24148,"children":24150},{"className":24149},[],[24151],{"type":420,"value":23750},{"type":420,"value":24153}," outside of a Pulumi program, without access to all the variables and where you would have to make your script idempotent. Moreover, the ability to execute commands remotely can bring interesting use cases, just not for our current concern here.",{"type":415,"tag":434,"props":24155,"children":24156},{"icon":436},[24157],{"type":415,"tag":416,"props":24158,"children":24159},{},[24160,24162,24167,24168,24174,24176,24182,24183,24189,24190,24196,24198,24205],{"type":420,"value":24161},"Pulumi Command Provider is currently in preview and only supports running scripts on ",{"type":415,"tag":468,"props":24163,"children":24165},{"className":24164},[],[24166],{"type":420,"value":24144},{"type":420,"value":6722},{"type":415,"tag":468,"props":24169,"children":24171},{"className":24170},[],[24172],{"type":420,"value":24173},"destroy",{"type":420,"value":24175}," operations (support for ",{"type":415,"tag":468,"props":24177,"children":24179},{"className":24178},[],[24180],{"type":420,"value":24181},"diff",{"type":420,"value":8073},{"type":415,"tag":468,"props":24184,"children":24186},{"className":24185},[],[24187],{"type":420,"value":24188},"update",{"type":420,"value":6722},{"type":415,"tag":468,"props":24191,"children":24193},{"className":24192},[],[24194],{"type":420,"value":24195},"read",{"type":420,"value":24197}," operations ",{"type":415,"tag":423,"props":24199,"children":24202},{"href":24200,"rel":24201},"https://github.com/pulumi/pulumi-command/issues/20",[427],[24203],{"type":420,"value":24204},"will probably be added later",{"type":420,"value":24206},"). It works fine but does not log details about the error when a script fails, which makes debugging difficult. That should not prevent you from using it but as with any components in preview, use it with caution knowing everything is not perfect yet.",{"type":415,"tag":482,"props":24208,"children":24210},{"id":24209},"implement-the-database-permissions-for-an-azure-ad-group",[24211],{"type":420,"value":24212},"Implement the database permissions for an Azure AD Group",{"type":415,"tag":416,"props":24214,"children":24215},{},[24216,24218,24223,24225,24230],{"type":420,"value":24217},"Of the 3 possible solutions let's take the 3rd one with the Command provider and the ",{"type":415,"tag":468,"props":24219,"children":24221},{"className":24220},[],[24222],{"type":420,"value":23750},{"type":420,"value":24224}," utility. It is probably not the \"best\" solution but I thought it would be simpler to use the ",{"type":415,"tag":468,"props":24226,"children":24228},{"className":24227},[],[24229],{"type":420,"value":23750},{"type":420,"value":24231}," utility than writing a complete provider or even custom C# code to do the same. Furthermore, it's the opportunity to test the Command provider which is fairly new.",{"type":415,"tag":3914,"props":24233,"children":24235},{"id":24234},"allow-the-machine-running-the-pulumi-program-to-connect-to-the-sql-server",[24236],{"type":420,"value":24237},"Allow the machine running the Pulumi program to connect to the SQL Server",{"type":415,"tag":416,"props":24239,"children":24240},{},[24241,24243,24249],{"type":420,"value":24242},"To run a SQL command in the database, the machine that executes the Pulumi program needs to have its public IP authorized. To programmatically retrieve the public IP address from where the Pulumi program is running we can use ",{"type":415,"tag":468,"props":24244,"children":24246},{"className":24245},[],[24247],{"type":420,"value":24248},"ipify API",{"type":420,"value":24250},". It's a simple open source HTTP API that returns the public IP address of the caller.",{"type":415,"tag":523,"props":24252,"children":24254},{"className":525,"code":24253,"language":326,"meta":401,"style":401},"var publicIp = Output.Create(new HttpClient().GetStringAsync(\"https://api.ipify.org\"));\n",[24255],{"type":415,"tag":468,"props":24256,"children":24257},{"__ignoreMap":401},[24258],{"type":415,"tag":532,"props":24259,"children":24260},{"class":534,"line":535},[24261,24265,24270,24274,24278,24282,24287,24291,24295,24300,24305,24309,24313,24318,24322],{"type":415,"tag":532,"props":24262,"children":24263},{"style":631},[24264],{"type":420,"value":634},{"type":415,"tag":532,"props":24266,"children":24267},{"style":631},[24268],{"type":420,"value":24269}," publicIp",{"type":415,"tag":532,"props":24271,"children":24272},{"style":551},[24273],{"type":420,"value":644},{"type":415,"tag":532,"props":24275,"children":24276},{"style":545},[24277],{"type":420,"value":9284},{"type":415,"tag":532,"props":24279,"children":24280},{"style":551},[24281],{"type":420,"value":432},{"type":415,"tag":532,"props":24283,"children":24284},{"style":656},[24285],{"type":420,"value":24286},"Create",{"type":415,"tag":532,"props":24288,"children":24289},{"style":551},[24290],{"type":420,"value":787},{"type":415,"tag":532,"props":24292,"children":24293},{"style":631},[24294],{"type":420,"value":22234},{"type":415,"tag":532,"props":24296,"children":24297},{"style":551},[24298],{"type":420,"value":24299},"().",{"type":415,"tag":532,"props":24301,"children":24302},{"style":656},[24303],{"type":420,"value":24304},"GetStringAsync",{"type":415,"tag":532,"props":24306,"children":24307},{"style":551},[24308],{"type":420,"value":664},{"type":415,"tag":532,"props":24310,"children":24311},{"style":551},[24312],{"type":420,"value":801},{"type":415,"tag":532,"props":24314,"children":24315},{"style":804},[24316],{"type":420,"value":24317},"https://api.ipify.org",{"type":415,"tag":532,"props":24319,"children":24320},{"style":551},[24321],{"type":420,"value":801},{"type":415,"tag":532,"props":24323,"children":24324},{"style":551},[24325],{"type":420,"value":816},{"type":415,"tag":434,"props":24327,"children":24328},{"icon":1382},[24329],{"type":415,"tag":416,"props":24330,"children":24331},{},[24332,24334,24340,24342,24348,24350,24357],{"type":420,"value":24333},"You can note here that we are just using standard C# code with an ",{"type":415,"tag":468,"props":24335,"children":24337},{"className":24336},[],[24338],{"type":420,"value":24339},"HttpClient",{"type":420,"value":24341}," that makes a ",{"type":415,"tag":468,"props":24343,"children":24345},{"className":24344},[],[24346],{"type":420,"value":24347},"GET",{"type":420,"value":24349}," to the API and returns asynchronously a string. I like the fact that with Pulumi we can reuse our existing C# skills, and the libraries we are used to. If we were to do that in Terraform we would have to look in the documentation how to do HTTP calls, discover that there is an ",{"type":415,"tag":423,"props":24351,"children":24354},{"href":24352,"rel":24353},"https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http",[427],[24355],{"type":420,"value":24356},"http data source",{"type":420,"value":24358}," that can be used, understand how it works (to be honest it seems quite simple but still that is not natural) and use it.",{"type":415,"tag":416,"props":24360,"children":24361},{},[24362],{"type":420,"value":24363},"Now we can enable this public IP by creating a firewall rule in the SQL Server.",{"type":415,"tag":523,"props":24365,"children":24367},{"className":525,"code":24366,"language":326,"meta":401,"style":401},"var enableLocalMachine = new FirewallRule(\"AllowLocalMachine\", new FirewallRuleArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    ServerName = sqlServer.Name,\n    StartIpAddress = publicIp,\n    EndIpAddress = publicIp\n});\n",[24368],{"type":415,"tag":468,"props":24369,"children":24370},{"__ignoreMap":401},[24371,24426,24433,24460,24487,24507,24524],{"type":415,"tag":532,"props":24372,"children":24373},{"class":534,"line":535},[24374,24378,24383,24387,24391,24396,24400,24404,24409,24413,24417,24421],{"type":415,"tag":532,"props":24375,"children":24376},{"style":631},[24377],{"type":420,"value":634},{"type":415,"tag":532,"props":24379,"children":24380},{"style":631},[24381],{"type":420,"value":24382}," enableLocalMachine",{"type":415,"tag":532,"props":24384,"children":24385},{"style":551},[24386],{"type":420,"value":644},{"type":415,"tag":532,"props":24388,"children":24389},{"style":551},[24390],{"type":420,"value":3276},{"type":415,"tag":532,"props":24392,"children":24393},{"style":631},[24394],{"type":420,"value":24395}," FirewallRule",{"type":415,"tag":532,"props":24397,"children":24398},{"style":551},[24399],{"type":420,"value":664},{"type":415,"tag":532,"props":24401,"children":24402},{"style":551},[24403],{"type":420,"value":801},{"type":415,"tag":532,"props":24405,"children":24406},{"style":804},[24407],{"type":420,"value":24408},"AllowLocalMachine",{"type":415,"tag":532,"props":24410,"children":24411},{"style":551},[24412],{"type":420,"value":801},{"type":415,"tag":532,"props":24414,"children":24415},{"style":551},[24416],{"type":420,"value":1099},{"type":415,"tag":532,"props":24418,"children":24419},{"style":551},[24420],{"type":420,"value":3276},{"type":415,"tag":532,"props":24422,"children":24423},{"style":631},[24424],{"type":420,"value":24425}," FirewallRuleArgs\n",{"type":415,"tag":532,"props":24427,"children":24428},{"class":534,"line":566},[24429],{"type":415,"tag":532,"props":24430,"children":24431},{"style":551},[24432],{"type":420,"value":764},{"type":415,"tag":532,"props":24434,"children":24435},{"class":534,"line":583},[24436,24440,24444,24448,24452,24456],{"type":415,"tag":532,"props":24437,"children":24438},{"style":545},[24439],{"type":420,"value":20394},{"type":415,"tag":532,"props":24441,"children":24442},{"style":551},[24443],{"type":420,"value":1134},{"type":415,"tag":532,"props":24445,"children":24446},{"style":545},[24447],{"type":420,"value":20155},{"type":415,"tag":532,"props":24449,"children":24450},{"style":551},[24451],{"type":420,"value":432},{"type":415,"tag":532,"props":24453,"children":24454},{"style":545},[24455],{"type":420,"value":1344},{"type":415,"tag":532,"props":24457,"children":24458},{"style":551},[24459],{"type":420,"value":7400},{"type":415,"tag":532,"props":24461,"children":24462},{"class":534,"line":617},[24463,24467,24471,24475,24479,24483],{"type":415,"tag":532,"props":24464,"children":24465},{"style":545},[24466],{"type":420,"value":23488},{"type":415,"tag":532,"props":24468,"children":24469},{"style":551},[24470],{"type":420,"value":1134},{"type":415,"tag":532,"props":24472,"children":24473},{"style":545},[24474],{"type":420,"value":23093},{"type":415,"tag":532,"props":24476,"children":24477},{"style":551},[24478],{"type":420,"value":432},{"type":415,"tag":532,"props":24480,"children":24481},{"style":545},[24482],{"type":420,"value":1344},{"type":415,"tag":532,"props":24484,"children":24485},{"style":551},[24486],{"type":420,"value":7400},{"type":415,"tag":532,"props":24488,"children":24489},{"class":534,"line":627},[24490,24495,24499,24503],{"type":415,"tag":532,"props":24491,"children":24492},{"style":545},[24493],{"type":420,"value":24494},"    StartIpAddress ",{"type":415,"tag":532,"props":24496,"children":24497},{"style":551},[24498],{"type":420,"value":1134},{"type":415,"tag":532,"props":24500,"children":24501},{"style":545},[24502],{"type":420,"value":24269},{"type":415,"tag":532,"props":24504,"children":24505},{"style":551},[24506],{"type":420,"value":7400},{"type":415,"tag":532,"props":24508,"children":24509},{"class":534,"line":677},[24510,24515,24519],{"type":415,"tag":532,"props":24511,"children":24512},{"style":545},[24513],{"type":420,"value":24514},"    EndIpAddress ",{"type":415,"tag":532,"props":24516,"children":24517},{"style":551},[24518],{"type":420,"value":1134},{"type":415,"tag":532,"props":24520,"children":24521},{"style":545},[24522],{"type":420,"value":24523}," publicIp\n",{"type":415,"tag":532,"props":24525,"children":24526},{"class":534,"line":719},[24527],{"type":415,"tag":532,"props":24528,"children":24529},{"style":551},[24530],{"type":420,"value":856},{"type":415,"tag":3914,"props":24532,"children":24534},{"id":24533},"create-the-azure-ad-group-that-will-be-given-access-to-the-database",[24535],{"type":420,"value":24536},"Create the Azure AD group that will be given access to the database",{"type":415,"tag":416,"props":24538,"children":24539},{},[24540],{"type":420,"value":24541},"We said we wanted to grant SQL Database access to an Azure AD group that will contain in the future users and application managed identities that need access to the database. So let's create that:",{"type":415,"tag":523,"props":24543,"children":24545},{"className":525,"code":24544,"language":326,"meta":401,"style":401},"var sqlDatabaseAuthorizedGroup = new Group(\"SqlDbUsersGroup\", new GroupArgs\n{\n    DisplayName = \"SqlDbUsersGroup\",\n    SecurityEnabled = true,\n    Owners = new InputList\u003Cstring> { sqlAdAdmin.Id }\n});\n",[24546],{"type":415,"tag":468,"props":24547,"children":24548},{"__ignoreMap":401},[24549,24604,24611,24638,24658,24712],{"type":415,"tag":532,"props":24550,"children":24551},{"class":534,"line":535},[24552,24556,24561,24565,24569,24574,24578,24582,24587,24591,24595,24599],{"type":415,"tag":532,"props":24553,"children":24554},{"style":631},[24555],{"type":420,"value":634},{"type":415,"tag":532,"props":24557,"children":24558},{"style":631},[24559],{"type":420,"value":24560}," sqlDatabaseAuthorizedGroup",{"type":415,"tag":532,"props":24562,"children":24563},{"style":551},[24564],{"type":420,"value":644},{"type":415,"tag":532,"props":24566,"children":24567},{"style":551},[24568],{"type":420,"value":3276},{"type":415,"tag":532,"props":24570,"children":24571},{"style":631},[24572],{"type":420,"value":24573}," Group",{"type":415,"tag":532,"props":24575,"children":24576},{"style":551},[24577],{"type":420,"value":664},{"type":415,"tag":532,"props":24579,"children":24580},{"style":551},[24581],{"type":420,"value":801},{"type":415,"tag":532,"props":24583,"children":24584},{"style":804},[24585],{"type":420,"value":24586},"SqlDbUsersGroup",{"type":415,"tag":532,"props":24588,"children":24589},{"style":551},[24590],{"type":420,"value":801},{"type":415,"tag":532,"props":24592,"children":24593},{"style":551},[24594],{"type":420,"value":1099},{"type":415,"tag":532,"props":24596,"children":24597},{"style":551},[24598],{"type":420,"value":3276},{"type":415,"tag":532,"props":24600,"children":24601},{"style":631},[24602],{"type":420,"value":24603}," GroupArgs\n",{"type":415,"tag":532,"props":24605,"children":24606},{"class":534,"line":566},[24607],{"type":415,"tag":532,"props":24608,"children":24609},{"style":551},[24610],{"type":420,"value":764},{"type":415,"tag":532,"props":24612,"children":24613},{"class":534,"line":583},[24614,24618,24622,24626,24630,24634],{"type":415,"tag":532,"props":24615,"children":24616},{"style":545},[24617],{"type":420,"value":8956},{"type":415,"tag":532,"props":24619,"children":24620},{"style":551},[24621],{"type":420,"value":1134},{"type":415,"tag":532,"props":24623,"children":24624},{"style":551},[24625],{"type":420,"value":4041},{"type":415,"tag":532,"props":24627,"children":24628},{"style":804},[24629],{"type":420,"value":24586},{"type":415,"tag":532,"props":24631,"children":24632},{"style":551},[24633],{"type":420,"value":801},{"type":415,"tag":532,"props":24635,"children":24636},{"style":551},[24637],{"type":420,"value":7400},{"type":415,"tag":532,"props":24639,"children":24640},{"class":534,"line":617},[24641,24646,24650,24654],{"type":415,"tag":532,"props":24642,"children":24643},{"style":545},[24644],{"type":420,"value":24645},"    SecurityEnabled ",{"type":415,"tag":532,"props":24647,"children":24648},{"style":551},[24649],{"type":420,"value":1134},{"type":415,"tag":532,"props":24651,"children":24652},{"style":1938},[24653],{"type":420,"value":1941},{"type":415,"tag":532,"props":24655,"children":24656},{"style":551},[24657],{"type":420,"value":7400},{"type":415,"tag":532,"props":24659,"children":24660},{"class":534,"line":627},[24661,24666,24670,24674,24679,24683,24687,24691,24695,24699,24703,24708],{"type":415,"tag":532,"props":24662,"children":24663},{"style":545},[24664],{"type":420,"value":24665},"    Owners ",{"type":415,"tag":532,"props":24667,"children":24668},{"style":551},[24669],{"type":420,"value":1134},{"type":415,"tag":532,"props":24671,"children":24672},{"style":551},[24673],{"type":420,"value":3276},{"type":415,"tag":532,"props":24675,"children":24676},{"style":631},[24677],{"type":420,"value":24678}," InputList",{"type":415,"tag":532,"props":24680,"children":24681},{"style":551},[24682],{"type":420,"value":706},{"type":415,"tag":532,"props":24684,"children":24685},{"style":551},[24686],{"type":420,"value":10698},{"type":415,"tag":532,"props":24688,"children":24689},{"style":551},[24690],{"type":420,"value":1015},{"type":415,"tag":532,"props":24692,"children":24693},{"style":551},[24694],{"type":420,"value":3347},{"type":415,"tag":532,"props":24696,"children":24697},{"style":545},[24698],{"type":420,"value":22912},{"type":415,"tag":532,"props":24700,"children":24701},{"style":551},[24702],{"type":420,"value":432},{"type":415,"tag":532,"props":24704,"children":24705},{"style":545},[24706],{"type":420,"value":24707},"Id ",{"type":415,"tag":532,"props":24709,"children":24710},{"style":551},[24711],{"type":420,"value":1379},{"type":415,"tag":532,"props":24713,"children":24714},{"class":534,"line":677},[24715],{"type":415,"tag":532,"props":24716,"children":24717},{"style":551},[24718],{"type":420,"value":856},{"type":415,"tag":416,"props":24720,"children":24721},{},[24722],{"type":420,"value":24723},"We set the Azure SQL Server admin as the owner of the group. This way, the admin of the database can add Azure AD users to the group and they directly have the permissions configured for this group. I like authorizing an Azure AD group instead of each Azure AD user because:",{"type":415,"tag":508,"props":24725,"children":24726},{},[24727,24732,24737],{"type":415,"tag":512,"props":24728,"children":24729},{},[24730],{"type":420,"value":24731},"it is easier to manage a group than individual users (adding a user to a group is less work than using SQL commands to assign the correct role for each user)",{"type":415,"tag":512,"props":24733,"children":24734},{},[24735],{"type":420,"value":24736},"you don't lose granularity of access control (you can always create several groups with different permissions if you need to)",{"type":415,"tag":512,"props":24738,"children":24739},{},[24740],{"type":420,"value":24741},"you can ensure that your application runs with the same permissions locally (the code you debug uses your user account identity) and on Azure (the code uses the managed identity of the App Service where it is hosted) by putting users and managed identities in the same group",{"type":415,"tag":3914,"props":24743,"children":24745},{"id":24744},"assign-the-roles-to-the-azure-ad-group-using-the-command-provider",[24746],{"type":420,"value":24747},"Assign the roles to the Azure AD group using the Command provider",{"type":415,"tag":416,"props":24749,"children":24750},{},[24751,24753,24758,24760,24765],{"type":420,"value":24752},"As we already talked about, we can specify a script to run on the ",{"type":415,"tag":468,"props":24754,"children":24756},{"className":24755},[],[24757],{"type":420,"value":24144},{"type":420,"value":24759}," operation and another on the ",{"type":415,"tag":468,"props":24761,"children":24763},{"className":24762},[],[24764],{"type":420,"value":24173},{"type":420,"value":24766}," operations. To keep things simple for this sample, we will only handle the creation scenario where we will add our Azure AD group as a user of the database and give it the expected roles. We already showed the SQL Command to execute, with our new group name it becomes:",{"type":415,"tag":523,"props":24768,"children":24770},{"className":23598,"code":24769,"language":23600,"meta":401,"style":401},"CREATE USER {sqlDatabaseAuthorizedGroup.DisplayName} FROM EXTERNAL PROVIDER;\nALTER ROLE db_datareader ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\nALTER ROLE db_datawriter ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\nGO\n",[24771],{"type":415,"tag":468,"props":24772,"children":24773},{"__ignoreMap":401},[24774,24802,24826,24849],{"type":415,"tag":532,"props":24775,"children":24776},{"class":534,"line":535},[24777,24781,24786,24790,24794,24798],{"type":415,"tag":532,"props":24778,"children":24779},{"style":539},[24780],{"type":420,"value":23612},{"type":415,"tag":532,"props":24782,"children":24783},{"style":545},[24784],{"type":420,"value":24785}," USER {sqlDatabaseAuthorizedGroup.DisplayName} ",{"type":415,"tag":532,"props":24787,"children":24788},{"style":539},[24789],{"type":420,"value":23622},{"type":415,"tag":532,"props":24791,"children":24792},{"style":539},[24793],{"type":420,"value":23627},{"type":415,"tag":532,"props":24795,"children":24796},{"style":539},[24797],{"type":420,"value":23632},{"type":415,"tag":532,"props":24799,"children":24800},{"style":545},[24801],{"type":420,"value":563},{"type":415,"tag":532,"props":24803,"children":24804},{"class":534,"line":566},[24805,24809,24813,24817,24821],{"type":415,"tag":532,"props":24806,"children":24807},{"style":539},[24808],{"type":420,"value":23644},{"type":415,"tag":532,"props":24810,"children":24811},{"style":539},[24812],{"type":420,"value":23649},{"type":415,"tag":532,"props":24814,"children":24815},{"style":545},[24816],{"type":420,"value":23654},{"type":415,"tag":532,"props":24818,"children":24819},{"style":539},[24820],{"type":420,"value":23659},{"type":415,"tag":532,"props":24822,"children":24823},{"style":545},[24824],{"type":420,"value":24825}," MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\n",{"type":415,"tag":532,"props":24827,"children":24828},{"class":534,"line":583},[24829,24833,24837,24841,24845],{"type":415,"tag":532,"props":24830,"children":24831},{"style":539},[24832],{"type":420,"value":23644},{"type":415,"tag":532,"props":24834,"children":24835},{"style":539},[24836],{"type":420,"value":23649},{"type":415,"tag":532,"props":24838,"children":24839},{"style":545},[24840],{"type":420,"value":23680},{"type":415,"tag":532,"props":24842,"children":24843},{"style":539},[24844],{"type":420,"value":23659},{"type":415,"tag":532,"props":24846,"children":24847},{"style":545},[24848],{"type":420,"value":24825},{"type":415,"tag":532,"props":24850,"children":24851},{"class":534,"line":617},[24852],{"type":415,"tag":532,"props":24853,"children":24854},{"style":539},[24855],{"type":420,"value":23696},{"type":415,"tag":416,"props":24857,"children":24858},{},[24859,24860,24865],{"type":420,"value":4968},{"type":415,"tag":468,"props":24861,"children":24863},{"className":24862},[],[24864],{"type":420,"value":23750},{"type":420,"value":24866}," utility can be used like this to send a command on the database:",{"type":415,"tag":523,"props":24868,"children":24870},{"className":4059,"code":24869,"language":248,"meta":401,"style":401},"sqlcmd -S {sqlServer.Name}.database.windows.net -d {database.Name} -U {sqlAdAdmin.UserPrincipalName} -P {sqlAdAdmin.Password} -G -l 30 -Q '___SQL Command___'\n",[24871],{"type":415,"tag":468,"props":24872,"children":24873},{"__ignoreMap":401},[24874],{"type":415,"tag":532,"props":24875,"children":24876},{"class":534,"line":535},[24877,24882,24886,24891,24895,24900,24904,24909,24913,24917,24921,24926,24930,24934,24939,24943,24948,24952,24956,24961,24965,24970,24974,24978,24983,24987,24992,24997,25001,25006,25011,25016],{"type":415,"tag":532,"props":24878,"children":24879},{"style":545},[24880],{"type":420,"value":24881},"sqlcmd ",{"type":415,"tag":532,"props":24883,"children":24884},{"style":551},[24885],{"type":420,"value":4216},{"type":415,"tag":532,"props":24887,"children":24888},{"style":545},[24889],{"type":420,"value":24890},"S ",{"type":415,"tag":532,"props":24892,"children":24893},{"style":551},[24894],{"type":420,"value":8748},{"type":415,"tag":532,"props":24896,"children":24897},{"style":545},[24898],{"type":420,"value":24899},"sqlServer.Name",{"type":415,"tag":532,"props":24901,"children":24902},{"style":551},[24903],{"type":420,"value":4864},{"type":415,"tag":532,"props":24905,"children":24906},{"style":545},[24907],{"type":420,"value":24908},".database.windows.net ",{"type":415,"tag":532,"props":24910,"children":24911},{"style":551},[24912],{"type":420,"value":4216},{"type":415,"tag":532,"props":24914,"children":24915},{"style":545},[24916],{"type":420,"value":11394},{"type":415,"tag":532,"props":24918,"children":24919},{"style":551},[24920],{"type":420,"value":8748},{"type":415,"tag":532,"props":24922,"children":24923},{"style":545},[24924],{"type":420,"value":24925},"database.Name",{"type":415,"tag":532,"props":24927,"children":24928},{"style":551},[24929],{"type":420,"value":4864},{"type":415,"tag":532,"props":24931,"children":24932},{"style":551},[24933],{"type":420,"value":4335},{"type":415,"tag":532,"props":24935,"children":24936},{"style":545},[24937],{"type":420,"value":24938},"U ",{"type":415,"tag":532,"props":24940,"children":24941},{"style":551},[24942],{"type":420,"value":8748},{"type":415,"tag":532,"props":24944,"children":24945},{"style":545},[24946],{"type":420,"value":24947},"sqlAdAdmin.UserPrincipalName",{"type":415,"tag":532,"props":24949,"children":24950},{"style":551},[24951],{"type":420,"value":4864},{"type":415,"tag":532,"props":24953,"children":24954},{"style":551},[24955],{"type":420,"value":4335},{"type":415,"tag":532,"props":24957,"children":24958},{"style":545},[24959],{"type":420,"value":24960},"P ",{"type":415,"tag":532,"props":24962,"children":24963},{"style":551},[24964],{"type":420,"value":8748},{"type":415,"tag":532,"props":24966,"children":24967},{"style":545},[24968],{"type":420,"value":24969},"sqlAdAdmin.Password",{"type":415,"tag":532,"props":24971,"children":24972},{"style":551},[24973],{"type":420,"value":4864},{"type":415,"tag":532,"props":24975,"children":24976},{"style":551},[24977],{"type":420,"value":4335},{"type":415,"tag":532,"props":24979,"children":24980},{"style":545},[24981],{"type":420,"value":24982},"G ",{"type":415,"tag":532,"props":24984,"children":24985},{"style":551},[24986],{"type":420,"value":4216},{"type":415,"tag":532,"props":24988,"children":24989},{"style":545},[24990],{"type":420,"value":24991},"l ",{"type":415,"tag":532,"props":24993,"children":24994},{"style":539},[24995],{"type":420,"value":24996},"30",{"type":415,"tag":532,"props":24998,"children":24999},{"style":551},[25000],{"type":420,"value":4335},{"type":415,"tag":532,"props":25002,"children":25003},{"style":545},[25004],{"type":420,"value":25005},"Q ",{"type":415,"tag":532,"props":25007,"children":25008},{"style":551},[25009],{"type":420,"value":25010},"'",{"type":415,"tag":532,"props":25012,"children":25013},{"style":804},[25014],{"type":420,"value":25015},"___SQL Command___",{"type":415,"tag":532,"props":25017,"children":25018},{"style":551},[25019],{"type":420,"value":3707},{"type":415,"tag":416,"props":25021,"children":25022},{},[25023,25025,25031,25033,25038],{"type":420,"value":25024},"You can check the ",{"type":415,"tag":423,"props":25026,"children":25029},{"href":25027,"rel":25028},"https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver15#sqlcmd-commands",[427],[25030],{"type":420,"value":499},{"type":420,"value":25032}," to learn more about how to use ",{"type":415,"tag":468,"props":25034,"children":25036},{"className":25035},[],[25037],{"type":420,"value":23750},{"type":420,"value":25039}," but that is quite simple: we are just specifying to send a command line query on our database using Azure Active Directory to authenticate.",{"type":415,"tag":416,"props":25041,"children":25042},{},[25043],{"type":420,"value":25044},"If we use all that with our Command provider, we get the following C# code.",{"type":415,"tag":523,"props":25046,"children":25048},{"className":525,"code":25047,"language":326,"meta":401,"style":401},"var authorizeAdGroup = new Command(\"AuthorizeAdGroup\", new CommandArgs\n{\n    Create = Output.Format($\"sqlcmd -S {sqlServer.Name}.database.windows.net -d {database.Name} -U {sqlAdAdmin.UserPrincipalName} -P {sqlAdAdmin.Password} -G -l 30 -Q 'CREATE USER {sqlDatabaseAuthorizedGroup.DisplayName} FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName}; ALTER ROLE db_datawriter ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};'\"),\n    Interpreter = new InputList\u003Cstring>\n    {\n        \"pwsh\",\n        \"-c\"\n    }\n});\n",[25049],{"type":415,"tag":468,"props":25050,"children":25051},{"__ignoreMap":401},[25052,25107,25114,25337,25370,25377,25397,25413,25420],{"type":415,"tag":532,"props":25053,"children":25054},{"class":534,"line":535},[25055,25059,25064,25068,25072,25077,25081,25085,25090,25094,25098,25102],{"type":415,"tag":532,"props":25056,"children":25057},{"style":631},[25058],{"type":420,"value":634},{"type":415,"tag":532,"props":25060,"children":25061},{"style":631},[25062],{"type":420,"value":25063}," authorizeAdGroup",{"type":415,"tag":532,"props":25065,"children":25066},{"style":551},[25067],{"type":420,"value":644},{"type":415,"tag":532,"props":25069,"children":25070},{"style":551},[25071],{"type":420,"value":3276},{"type":415,"tag":532,"props":25073,"children":25074},{"style":631},[25075],{"type":420,"value":25076}," Command",{"type":415,"tag":532,"props":25078,"children":25079},{"style":551},[25080],{"type":420,"value":664},{"type":415,"tag":532,"props":25082,"children":25083},{"style":551},[25084],{"type":420,"value":801},{"type":415,"tag":532,"props":25086,"children":25087},{"style":804},[25088],{"type":420,"value":25089},"AuthorizeAdGroup",{"type":415,"tag":532,"props":25091,"children":25092},{"style":551},[25093],{"type":420,"value":801},{"type":415,"tag":532,"props":25095,"children":25096},{"style":551},[25097],{"type":420,"value":1099},{"type":415,"tag":532,"props":25099,"children":25100},{"style":551},[25101],{"type":420,"value":3276},{"type":415,"tag":532,"props":25103,"children":25104},{"style":631},[25105],{"type":420,"value":25106}," CommandArgs\n",{"type":415,"tag":532,"props":25108,"children":25109},{"class":534,"line":566},[25110],{"type":415,"tag":532,"props":25111,"children":25112},{"style":551},[25113],{"type":420,"value":764},{"type":415,"tag":532,"props":25115,"children":25116},{"class":534,"line":583},[25117,25122,25126,25130,25134,25138,25142,25146,25151,25155,25160,25164,25168,25172,25177,25181,25185,25189,25193,25197,25202,25206,25210,25214,25218,25222,25227,25231,25235,25239,25244,25248,25253,25257,25262,25266,25270,25274,25279,25283,25287,25291,25295,25299,25304,25308,25312,25316,25320,25324,25329,25333],{"type":415,"tag":532,"props":25118,"children":25119},{"style":545},[25120],{"type":420,"value":25121},"    Create ",{"type":415,"tag":532,"props":25123,"children":25124},{"style":551},[25125],{"type":420,"value":1134},{"type":415,"tag":532,"props":25127,"children":25128},{"style":545},[25129],{"type":420,"value":9284},{"type":415,"tag":532,"props":25131,"children":25132},{"style":551},[25133],{"type":420,"value":432},{"type":415,"tag":532,"props":25135,"children":25136},{"style":656},[25137],{"type":420,"value":9293},{"type":415,"tag":532,"props":25139,"children":25140},{"style":551},[25141],{"type":420,"value":664},{"type":415,"tag":532,"props":25143,"children":25144},{"style":551},[25145],{"type":420,"value":8738},{"type":415,"tag":532,"props":25147,"children":25148},{"style":804},[25149],{"type":420,"value":25150},"sqlcmd -S ",{"type":415,"tag":532,"props":25152,"children":25153},{"style":551},[25154],{"type":420,"value":8748},{"type":415,"tag":532,"props":25156,"children":25157},{"style":545},[25158],{"type":420,"value":25159},"sqlServer",{"type":415,"tag":532,"props":25161,"children":25162},{"style":551},[25163],{"type":420,"value":432},{"type":415,"tag":532,"props":25165,"children":25166},{"style":545},[25167],{"type":420,"value":1344},{"type":415,"tag":532,"props":25169,"children":25170},{"style":551},[25171],{"type":420,"value":4864},{"type":415,"tag":532,"props":25173,"children":25174},{"style":804},[25175],{"type":420,"value":25176},".database.windows.net -d ",{"type":415,"tag":532,"props":25178,"children":25179},{"style":551},[25180],{"type":420,"value":8748},{"type":415,"tag":532,"props":25182,"children":25183},{"style":545},[25184],{"type":420,"value":23921},{"type":415,"tag":532,"props":25186,"children":25187},{"style":551},[25188],{"type":420,"value":432},{"type":415,"tag":532,"props":25190,"children":25191},{"style":545},[25192],{"type":420,"value":1344},{"type":415,"tag":532,"props":25194,"children":25195},{"style":551},[25196],{"type":420,"value":4864},{"type":415,"tag":532,"props":25198,"children":25199},{"style":804},[25200],{"type":420,"value":25201}," -U ",{"type":415,"tag":532,"props":25203,"children":25204},{"style":551},[25205],{"type":420,"value":8748},{"type":415,"tag":532,"props":25207,"children":25208},{"style":545},[25209],{"type":420,"value":22835},{"type":415,"tag":532,"props":25211,"children":25212},{"style":551},[25213],{"type":420,"value":432},{"type":415,"tag":532,"props":25215,"children":25216},{"style":545},[25217],{"type":420,"value":23247},{"type":415,"tag":532,"props":25219,"children":25220},{"style":551},[25221],{"type":420,"value":4864},{"type":415,"tag":532,"props":25223,"children":25224},{"style":804},[25225],{"type":420,"value":25226}," -P ",{"type":415,"tag":532,"props":25228,"children":25229},{"style":551},[25230],{"type":420,"value":8748},{"type":415,"tag":532,"props":25232,"children":25233},{"style":545},[25234],{"type":420,"value":22835},{"type":415,"tag":532,"props":25236,"children":25237},{"style":551},[25238],{"type":420,"value":432},{"type":415,"tag":532,"props":25240,"children":25241},{"style":545},[25242],{"type":420,"value":25243},"Password",{"type":415,"tag":532,"props":25245,"children":25246},{"style":551},[25247],{"type":420,"value":4864},{"type":415,"tag":532,"props":25249,"children":25250},{"style":804},[25251],{"type":420,"value":25252}," -G -l 30 -Q 'CREATE USER ",{"type":415,"tag":532,"props":25254,"children":25255},{"style":551},[25256],{"type":420,"value":8748},{"type":415,"tag":532,"props":25258,"children":25259},{"style":545},[25260],{"type":420,"value":25261},"sqlDatabaseAuthorizedGroup",{"type":415,"tag":532,"props":25263,"children":25264},{"style":551},[25265],{"type":420,"value":432},{"type":415,"tag":532,"props":25267,"children":25268},{"style":545},[25269],{"type":420,"value":8808},{"type":415,"tag":532,"props":25271,"children":25272},{"style":551},[25273],{"type":420,"value":4864},{"type":415,"tag":532,"props":25275,"children":25276},{"style":804},[25277],{"type":420,"value":25278}," FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER ",{"type":415,"tag":532,"props":25280,"children":25281},{"style":551},[25282],{"type":420,"value":8748},{"type":415,"tag":532,"props":25284,"children":25285},{"style":545},[25286],{"type":420,"value":25261},{"type":415,"tag":532,"props":25288,"children":25289},{"style":551},[25290],{"type":420,"value":432},{"type":415,"tag":532,"props":25292,"children":25293},{"style":545},[25294],{"type":420,"value":8808},{"type":415,"tag":532,"props":25296,"children":25297},{"style":551},[25298],{"type":420,"value":4864},{"type":415,"tag":532,"props":25300,"children":25301},{"style":804},[25302],{"type":420,"value":25303},"; ALTER ROLE db_datawriter ADD MEMBER ",{"type":415,"tag":532,"props":25305,"children":25306},{"style":551},[25307],{"type":420,"value":8748},{"type":415,"tag":532,"props":25309,"children":25310},{"style":545},[25311],{"type":420,"value":25261},{"type":415,"tag":532,"props":25313,"children":25314},{"style":551},[25315],{"type":420,"value":432},{"type":415,"tag":532,"props":25317,"children":25318},{"style":545},[25319],{"type":420,"value":8808},{"type":415,"tag":532,"props":25321,"children":25322},{"style":551},[25323],{"type":420,"value":4864},{"type":415,"tag":532,"props":25325,"children":25326},{"style":804},[25327],{"type":420,"value":25328},";'",{"type":415,"tag":532,"props":25330,"children":25331},{"style":551},[25332],{"type":420,"value":801},{"type":415,"tag":532,"props":25334,"children":25335},{"style":551},[25336],{"type":420,"value":10087},{"type":415,"tag":532,"props":25338,"children":25339},{"class":534,"line":617},[25340,25345,25349,25353,25357,25361,25365],{"type":415,"tag":532,"props":25341,"children":25342},{"style":545},[25343],{"type":420,"value":25344},"    Interpreter ",{"type":415,"tag":532,"props":25346,"children":25347},{"style":551},[25348],{"type":420,"value":1134},{"type":415,"tag":532,"props":25350,"children":25351},{"style":551},[25352],{"type":420,"value":3276},{"type":415,"tag":532,"props":25354,"children":25355},{"style":631},[25356],{"type":420,"value":24678},{"type":415,"tag":532,"props":25358,"children":25359},{"style":551},[25360],{"type":420,"value":706},{"type":415,"tag":532,"props":25362,"children":25363},{"style":551},[25364],{"type":420,"value":10698},{"type":415,"tag":532,"props":25366,"children":25367},{"style":551},[25368],{"type":420,"value":25369},">\n",{"type":415,"tag":532,"props":25371,"children":25372},{"class":534,"line":627},[25373],{"type":415,"tag":532,"props":25374,"children":25375},{"style":551},[25376],{"type":420,"value":1121},{"type":415,"tag":532,"props":25378,"children":25379},{"class":534,"line":677},[25380,25384,25389,25393],{"type":415,"tag":532,"props":25381,"children":25382},{"style":551},[25383],{"type":420,"value":4936},{"type":415,"tag":532,"props":25385,"children":25386},{"style":804},[25387],{"type":420,"value":25388},"pwsh",{"type":415,"tag":532,"props":25390,"children":25391},{"style":551},[25392],{"type":420,"value":801},{"type":415,"tag":532,"props":25394,"children":25395},{"style":551},[25396],{"type":420,"value":7400},{"type":415,"tag":532,"props":25398,"children":25399},{"class":534,"line":719},[25400,25404,25409],{"type":415,"tag":532,"props":25401,"children":25402},{"style":551},[25403],{"type":420,"value":4936},{"type":415,"tag":532,"props":25405,"children":25406},{"style":804},[25407],{"type":420,"value":25408},"-c",{"type":415,"tag":532,"props":25410,"children":25411},{"style":551},[25412],{"type":420,"value":4051},{"type":415,"tag":532,"props":25414,"children":25415},{"class":534,"line":758},[25416],{"type":415,"tag":532,"props":25417,"children":25418},{"style":551},[25419],{"type":420,"value":1170},{"type":415,"tag":532,"props":25421,"children":25422},{"class":534,"line":767},[25423],{"type":415,"tag":532,"props":25424,"children":25425},{"style":551},[25426],{"type":420,"value":856},{"type":415,"tag":416,"props":25428,"children":25429},{},[25430],{"type":420,"value":25431},"As you can see, we can specify a specific interpreter to use (PowerShell here).",{"type":415,"tag":434,"props":25433,"children":25434},{"icon":1382},[25435],{"type":415,"tag":416,"props":25436,"children":25437},{},[25438,25440,25447,25449,25455,25457,25462],{"type":420,"value":25439},"Don't do like me and forget that our variables are ",{"type":415,"tag":423,"props":25441,"children":25444},{"href":25442,"rel":25443},"https://www.pulumi.com/docs/intro/concepts/inputs-outputs/#inputs-and-outputs",[427],[25445],{"type":420,"value":25446},"outputs",{"type":420,"value":25448}," (only fully known when the infrastructure resource is completely provisioned). Because of that it is necessary to use the ",{"type":415,"tag":468,"props":25450,"children":25452},{"className":25451},[],[25453],{"type":420,"value":25454},"Output.Format",{"type":420,"value":25456}," method for string interpolation instead of using the C# operator ",{"type":415,"tag":468,"props":25458,"children":25460},{"className":25459},[],[25461],{"type":420,"value":4072},{"type":420,"value":25463},". Thanks to the community on Slack for helping me on that one because with the Command provider not logging the errors details I had a hard time on this.",{"type":415,"tag":3914,"props":25465,"children":25467},{"id":25466},"results",[25468],{"type":420,"value":25469},"Results",{"type":415,"tag":416,"props":25471,"children":25472},{},[25473,25475,25480,25481,25486],{"type":420,"value":25474},"And that's it! We now have created the Azure AD group as an external user in the database and assigned it the ",{"type":415,"tag":468,"props":25476,"children":25478},{"className":25477},[],[25479],{"type":420,"value":23707},{"type":420,"value":6722},{"type":415,"tag":468,"props":25482,"children":25484},{"className":25483},[],[25485],{"type":420,"value":23714},{"type":420,"value":25487}," roles.\nHere is what it looks like in Azure Data Studio:",{"type":415,"tag":416,"props":25489,"children":25490},{},[25491],{"type":415,"tag":3882,"props":25492,"children":25496},{"alt":25493,"className":25494,"src":25495},"SQL query listing database members and roles in Azure Data Studio.",[3886,3887],"/posts/images/sqldatabase_ad_azuredatastudio.png",[],{"type":415,"tag":482,"props":25498,"children":25499},{"id":22531},[25500],{"type":420,"value":22534},{"type":415,"tag":416,"props":25502,"children":25503},{},[25504,25506,25512],{"type":420,"value":25505},"This article is a bit long because I explain all the steps and possibilities but the complete code is not very big or complex. You can find it in this ",{"type":415,"tag":423,"props":25507,"children":25510},{"href":25508,"rel":25509},"https://github.com/TechWatching/SqlDatabaseWithAzureAd",[427],[25511],{"type":420,"value":23816},{"type":420,"value":432},{"type":415,"tag":416,"props":25514,"children":25515},{},[25516],{"type":420,"value":25517},"I did not see that many articles on the web that talk about using Azure Active Directory authentication for an Azure SQL Database, and even less that showed how to properly configure it using Infrastructure as Code. Yet, I think it's an important thing to do to properly secure your Azure SQL database. So I hope you enjoyed it and learn something. Whether you use Azure CLI, Bicep, ARM Templates, Terraform, or Pulumi, don't hesitate to use Azure AD authentication on your Azure SQL Database, for me that is the right and secure way to go.",{"type":415,"tag":416,"props":25519,"children":25520},{},[25521],{"type":420,"value":25522},"As you have seen in this article, even when there is no provider for your custom resource or task, there are always several solutions to do what you want with Pulumi. Some are more elegant, some are more complex than others but you will always find a way and you will not be limited by the platform.",{"type":415,"tag":416,"props":25524,"children":25525},{},[25526],{"type":420,"value":25527},"A big thank you to the Pulumi community that gave me some insights on how to configure Azure AD authentication on a database properly using Pulumi. Without the help of some people in the Pulumi Slack or the GitHub Issues/Discussions I would not have been able to write this article. Indeed some ideas and solutions are directly inspired by people's answers to my questions. This article is my way of contributing back and helping others that would have similar questions.",{"type":415,"tag":3470,"props":25529,"children":25530},{},[25531],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":25533},[25534,25535,25536,25537,25543,25549],{"id":22696,"depth":566,"text":22699},{"id":22750,"depth":566,"text":22753},{"id":23066,"depth":566,"text":23069},{"id":23575,"depth":566,"text":23578,"children":25538},[25539,25540,25541],{"id":23760,"depth":583,"text":23763},{"id":23858,"depth":583,"text":23861},{"id":24069,"depth":583,"text":25542},"Command provider with the sqlcmd utility",{"id":24209,"depth":566,"text":24212,"children":25544},[25545,25546,25547,25548],{"id":24234,"depth":583,"text":24237},{"id":24533,"depth":583,"text":24536},{"id":24744,"depth":583,"text":24747},{"id":25466,"depth":583,"text":25469},{"id":22531,"depth":566,"text":22534},"content:1.posts:35.sqldatabase-active-directory-authent.md","1.posts/35.sqldatabase-active-directory-authent.md",{"_path":97,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":96,"description":25553,"lead":25554,"date":25555,"badge":25556,"image":25557,"tags":25559,"body":25560,"_type":3483,"_id":28103,"_source":3485,"_file":28104,"_extension":3487},"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":25558},"/images/cloud-crave_1.jpg",[312,315,225,318,260,228],{"type":412,"children":25561,"toc":28085},[25562,25566,25572,25578,25583,25601,25609,25614,25619,25642,25651,25657,25662,25667,25690,25695,25701,25707,25719,25753,25758,25763,25769,25791,25800,25814,25819,25964,25969,26071,26076,26153,26158,26277,26282,26318,26324,26329,26354,26374,26461,26466,26486,26495,26501,26507,26512,26517,26523,26528,26533,26560,26565,26571,26576,26712,26725,26730,26805,26818,26888,26893,26943,26948,26983,26988,27083,27089,27094,27099,27113,27135,27144,27149,27153,27158,28063,28068,28081],{"type":415,"tag":416,"props":25563,"children":25564},{},[25565],{"type":420,"value":25553},{"type":415,"tag":482,"props":25567,"children":25569},{"id":25568},"a-quick-reminder-about-states-and-backends",[25570],{"type":420,"value":25571},"A quick reminder about states and backends",{"type":415,"tag":3914,"props":25573,"children":25575},{"id":25574},"what-is-this-state-we-need-to-store",[25576],{"type":420,"value":25577},"What is this state we need to store?",{"type":415,"tag":416,"props":25579,"children":25580},{},[25581],{"type":420,"value":25582},"Like other Infrastructure as Code platforms, Pulumi uses a declarative approach:",{"type":415,"tag":508,"props":25584,"children":25585},{},[25586,25591,25596],{"type":415,"tag":512,"props":25587,"children":25588},{},[25589],{"type":420,"value":25590},"we write code to describe the desired state of our infrastructure",{"type":415,"tag":512,"props":25592,"children":25593},{},[25594],{"type":420,"value":25595},"Pulumi engine compares this desired state with the current state of the infrastructure and determines what changes need to be made",{"type":415,"tag":512,"props":25597,"children":25598},{},[25599],{"type":420,"value":25600},"Pulumi deploys these changes and updates the current state of the provisioned infrastructure",{"type":415,"tag":434,"props":25602,"children":25603},{"icon":1382},[25604],{"type":415,"tag":416,"props":25605,"children":25606},{},[25607],{"type":420,"value":25608},"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":415,"tag":416,"props":25610,"children":25611},{},[25612],{"type":420,"value":25613},"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":415,"tag":416,"props":25615,"children":25616},{},[25617],{"type":420,"value":25618},"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":415,"tag":416,"props":25620,"children":25621},{},[25622,25624,25631,25633,25640],{"type":420,"value":25623},"If you want more information about states and backend, Pulumi has a ",{"type":415,"tag":423,"props":25625,"children":25628},{"href":25626,"rel":25627},"https://www.pulumi.com/docs/intro/concepts/state/",[427],[25629],{"type":420,"value":25630},"documentation page",{"type":420,"value":25632}," about that and there is also ",{"type":415,"tag":423,"props":25634,"children":25637},{"href":25635,"rel":25636},"https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/",[427],[25638],{"type":420,"value":25639},"a page",{"type":420,"value":25641}," about how Pulumi works.",{"type":415,"tag":416,"props":25643,"children":25644},{},[25645],{"type":415,"tag":3882,"props":25646,"children":25650},{"alt":25647,"className":25648,"src":25649},"Diagram of how Pulumi works.",[3886,3887],"/posts/images/pulumiazurebackend_schema_1.png",[],{"type":415,"tag":3914,"props":25652,"children":25654},{"id":25653},"what-backends-can-we-use-to-manage-the-infrastructure",[25655],{"type":420,"value":25656},"What \"backends\" can we use to manage the infrastructure?",{"type":415,"tag":416,"props":25658,"children":25659},{},[25660],{"type":420,"value":25661},"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":415,"tag":416,"props":25663,"children":25664},{},[25665],{"type":420,"value":25666},"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":415,"tag":508,"props":25668,"children":25669},{},[25670,25675,25680,25685],{"type":415,"tag":512,"props":25671,"children":25672},{},[25673],{"type":420,"value":25674},"Local Filesystem",{"type":415,"tag":512,"props":25676,"children":25677},{},[25678],{"type":420,"value":25679},"AWS S3 (or compatible server)",{"type":415,"tag":512,"props":25681,"children":25682},{},[25683],{"type":420,"value":25684},"Google Cloud Storage",{"type":415,"tag":512,"props":25686,"children":25687},{},[25688],{"type":420,"value":25689},"Azure Blob Storage",{"type":415,"tag":416,"props":25691,"children":25692},{},[25693],{"type":420,"value":25694},"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":415,"tag":482,"props":25696,"children":25698},{"id":25697},"using-pulumi-with-the-azure-blob-storage-backend",[25699],{"type":420,"value":25700},"Using Pulumi with the Azure Blob Storage backend",{"type":415,"tag":3914,"props":25702,"children":25704},{"id":25703},"what-do-we-need",[25705],{"type":420,"value":25706},"What do we need?",{"type":415,"tag":416,"props":25708,"children":25709},{},[25710,25717],{"type":415,"tag":423,"props":25711,"children":25714},{"href":25712,"rel":25713},"https://www.pulumi.com/docs/intro/concepts/state/#logging-into-the-azure-blob-storage-backend",[427],[25715],{"type":420,"value":25716},"Pulumi documentation",{"type":420,"value":25718}," on using Azure Blob Storage backend is short. It only says that we need to:",{"type":415,"tag":508,"props":25720,"children":25721},{},[25722,25727,25732],{"type":415,"tag":512,"props":25723,"children":25724},{},[25725],{"type":420,"value":25726},"set the AZURE_STORAGE_ACCOUNT environment variable to specify the Azure storage account to use",{"type":415,"tag":512,"props":25728,"children":25729},{},[25730],{"type":420,"value":25731},"set the AZURE_STORAGE_KEY or the AZURE_STORAGE_SAS_TOKEN environment variables to let Pulumi access the storage",{"type":415,"tag":512,"props":25733,"children":25734},{},[25735,25737,25743,25745,25751],{"type":420,"value":25736},"execute the following command ",{"type":415,"tag":468,"props":25738,"children":25740},{"className":25739},[],[25741],{"type":420,"value":25742},"pulumi login azblob://\u003Ccontainer-path>",{"type":420,"value":25744}," where ",{"type":415,"tag":468,"props":25746,"children":25748},{"className":25747},[],[25749],{"type":420,"value":25750},"container-path",{"type":420,"value":25752}," is the path to a blob container in the storage account",{"type":415,"tag":416,"props":25754,"children":25755},{},[25756],{"type":420,"value":25757},"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":415,"tag":416,"props":25759,"children":25760},{},[25761],{"type":420,"value":25762},"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":415,"tag":3914,"props":25764,"children":25766},{"id":25765},"how-to-create-and-configure-the-azure-blob-storage-backend",[25767],{"type":420,"value":25768},"How to create and configure the Azure Blob Storage backend?",{"type":415,"tag":416,"props":25770,"children":25771},{},[25772,25774,25781,25783,25789],{"type":420,"value":25773},"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":415,"tag":423,"props":25775,"children":25778},{"href":25776,"rel":25777},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.azurecli",[427],[25779],{"type":420,"value":25780},"Azure CLI Tools extension",{"type":420,"value":25782},": you can create ",{"type":415,"tag":468,"props":25784,"children":25786},{"className":25785},[],[25787],{"type":420,"value":25788},".azcli",{"type":420,"value":25790}," files with IntelliSense on them and run the commands you are writing in the integrated terminal (see screenshot below).",{"type":415,"tag":416,"props":25792,"children":25793},{},[25794],{"type":415,"tag":3882,"props":25795,"children":25799},{"alt":25796,"className":25797,"src":25798},"Azure CLI script in vscode.",[3886,3887],"/posts/images/pulumiazurebackend_vscode_1.png",[],{"type":415,"tag":434,"props":25801,"children":25802},{"icon":1382},[25803],{"type":415,"tag":416,"props":25804,"children":25805},{},[25806,25808,25813],{"type":420,"value":25807},"If you are not familiar with Azure CLI, you can check my article \"",{"type":415,"tag":423,"props":25809,"children":25811},{"href":4423,"rel":25810},[427],[25812],{"type":420,"value":15},{"type":420,"value":10986},{"type":415,"tag":416,"props":25815,"children":25816},{},[25817],{"type":420,"value":25818},"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":415,"tag":523,"props":25820,"children":25822},{"className":4059,"code":25821,"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",[25823],{"type":415,"tag":468,"props":25824,"children":25825},{"__ignoreMap":401},[25826,25861,25890,25927],{"type":415,"tag":532,"props":25827,"children":25828},{"class":534,"line":535},[25829,25833,25838,25842,25847,25851,25856],{"type":415,"tag":532,"props":25830,"children":25831},{"style":551},[25832],{"type":420,"value":4072},{"type":415,"tag":532,"props":25834,"children":25835},{"style":545},[25836],{"type":420,"value":25837},"random",{"type":415,"tag":532,"props":25839,"children":25840},{"style":551},[25841],{"type":420,"value":1134},{"type":415,"tag":532,"props":25843,"children":25844},{"style":656},[25845],{"type":420,"value":25846},"Get-Random",{"type":415,"tag":532,"props":25848,"children":25849},{"style":551},[25850],{"type":420,"value":4335},{"type":415,"tag":532,"props":25852,"children":25853},{"style":545},[25854],{"type":420,"value":25855},"Maximum ",{"type":415,"tag":532,"props":25857,"children":25858},{"style":539},[25859],{"type":420,"value":25860},"1000\n",{"type":415,"tag":532,"props":25862,"children":25863},{"class":534,"line":566},[25864,25868,25873,25877,25881,25886],{"type":415,"tag":532,"props":25865,"children":25866},{"style":551},[25867],{"type":420,"value":4072},{"type":415,"tag":532,"props":25869,"children":25870},{"style":545},[25871],{"type":420,"value":25872},"location",{"type":415,"tag":532,"props":25874,"children":25875},{"style":551},[25876],{"type":420,"value":1134},{"type":415,"tag":532,"props":25878,"children":25879},{"style":551},[25880],{"type":420,"value":801},{"type":415,"tag":532,"props":25882,"children":25883},{"style":804},[25884],{"type":420,"value":25885},"West Europe",{"type":415,"tag":532,"props":25887,"children":25888},{"style":551},[25889],{"type":420,"value":4051},{"type":415,"tag":532,"props":25891,"children":25892},{"class":534,"line":583},[25893,25897,25902,25906,25910,25915,25919,25923],{"type":415,"tag":532,"props":25894,"children":25895},{"style":551},[25896],{"type":420,"value":4072},{"type":415,"tag":532,"props":25898,"children":25899},{"style":545},[25900],{"type":420,"value":25901},"rgName",{"type":415,"tag":532,"props":25903,"children":25904},{"style":551},[25905],{"type":420,"value":1134},{"type":415,"tag":532,"props":25907,"children":25908},{"style":551},[25909],{"type":420,"value":801},{"type":415,"tag":532,"props":25911,"children":25912},{"style":804},[25913],{"type":420,"value":25914},"rg-iacstate-westeu-",{"type":415,"tag":532,"props":25916,"children":25917},{"style":551},[25918],{"type":420,"value":4072},{"type":415,"tag":532,"props":25920,"children":25921},{"style":545},[25922],{"type":420,"value":25837},{"type":415,"tag":532,"props":25924,"children":25925},{"style":551},[25926],{"type":420,"value":4051},{"type":415,"tag":532,"props":25928,"children":25929},{"class":534,"line":617},[25930,25934,25939,25943,25947,25952,25956,25960],{"type":415,"tag":532,"props":25931,"children":25932},{"style":551},[25933],{"type":420,"value":4072},{"type":415,"tag":532,"props":25935,"children":25936},{"style":545},[25937],{"type":420,"value":25938},"saName",{"type":415,"tag":532,"props":25940,"children":25941},{"style":551},[25942],{"type":420,"value":1134},{"type":415,"tag":532,"props":25944,"children":25945},{"style":551},[25946],{"type":420,"value":801},{"type":415,"tag":532,"props":25948,"children":25949},{"style":804},[25950],{"type":420,"value":25951},"stiacstate",{"type":415,"tag":532,"props":25953,"children":25954},{"style":551},[25955],{"type":420,"value":4072},{"type":415,"tag":532,"props":25957,"children":25958},{"style":545},[25959],{"type":420,"value":25837},{"type":415,"tag":532,"props":25961,"children":25962},{"style":551},[25963],{"type":420,"value":4051},{"type":415,"tag":416,"props":25965,"children":25966},{},[25967],{"type":420,"value":25968},"Then let's create our resource group and our storage account:",{"type":415,"tag":523,"props":25970,"children":25972},{"className":3984,"code":25971,"language":3986,"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",[25973],{"type":415,"tag":468,"props":25974,"children":25975},{"__ignoreMap":401},[25976,26013],{"type":415,"tag":532,"props":25977,"children":25978},{"class":534,"line":535},[25979,25984,25989,25994,25998,26003,26008],{"type":415,"tag":532,"props":25980,"children":25981},{"style":631},[25982],{"type":420,"value":25983},"az",{"type":415,"tag":532,"props":25985,"children":25986},{"style":804},[25987],{"type":420,"value":25988}," group",{"type":415,"tag":532,"props":25990,"children":25991},{"style":804},[25992],{"type":420,"value":25993}," create",{"type":415,"tag":532,"props":25995,"children":25996},{"style":804},[25997],{"type":420,"value":6978},{"type":415,"tag":532,"props":25999,"children":26000},{"style":545},[26001],{"type":420,"value":26002}," $rgName ",{"type":415,"tag":532,"props":26004,"children":26005},{"style":804},[26006],{"type":420,"value":26007},"-l",{"type":415,"tag":532,"props":26009,"children":26010},{"style":545},[26011],{"type":420,"value":26012}," $location\n",{"type":415,"tag":532,"props":26014,"children":26015},{"class":534,"line":566},[26016,26020,26025,26030,26034,26039,26043,26047,26052,26056,26061,26066],{"type":415,"tag":532,"props":26017,"children":26018},{"style":631},[26019],{"type":420,"value":25983},{"type":415,"tag":532,"props":26021,"children":26022},{"style":804},[26023],{"type":420,"value":26024}," storage",{"type":415,"tag":532,"props":26026,"children":26027},{"style":804},[26028],{"type":420,"value":26029}," account",{"type":415,"tag":532,"props":26031,"children":26032},{"style":804},[26033],{"type":420,"value":25993},{"type":415,"tag":532,"props":26035,"children":26036},{"style":804},[26037],{"type":420,"value":26038}," -g",{"type":415,"tag":532,"props":26040,"children":26041},{"style":545},[26042],{"type":420,"value":26002},{"type":415,"tag":532,"props":26044,"children":26045},{"style":804},[26046],{"type":420,"value":7045},{"type":415,"tag":532,"props":26048,"children":26049},{"style":545},[26050],{"type":420,"value":26051}," $saName ",{"type":415,"tag":532,"props":26053,"children":26054},{"style":804},[26055],{"type":420,"value":26007},{"type":415,"tag":532,"props":26057,"children":26058},{"style":545},[26059],{"type":420,"value":26060}," $location ",{"type":415,"tag":532,"props":26062,"children":26063},{"style":804},[26064],{"type":420,"value":26065},"--sku",{"type":415,"tag":532,"props":26067,"children":26068},{"style":804},[26069],{"type":420,"value":26070}," Standard_LRS\n",{"type":415,"tag":416,"props":26072,"children":26073},{},[26074],{"type":420,"value":26075},"The key to access the storage account can be retrieved with the following command:",{"type":415,"tag":523,"props":26077,"children":26079},{"className":3984,"code":26078,"language":3986,"meta":401,"style":401},"az storage account keys list --account-name $saName -g $rgName -o tsv --query '[0].value'\n",[26080],{"type":415,"tag":468,"props":26081,"children":26082},{"__ignoreMap":401},[26083],{"type":415,"tag":532,"props":26084,"children":26085},{"class":534,"line":535},[26086,26090,26094,26098,26103,26108,26113,26117,26121,26125,26130,26135,26140,26144,26149],{"type":415,"tag":532,"props":26087,"children":26088},{"style":631},[26089],{"type":420,"value":25983},{"type":415,"tag":532,"props":26091,"children":26092},{"style":804},[26093],{"type":420,"value":26024},{"type":415,"tag":532,"props":26095,"children":26096},{"style":804},[26097],{"type":420,"value":26029},{"type":415,"tag":532,"props":26099,"children":26100},{"style":804},[26101],{"type":420,"value":26102}," keys",{"type":415,"tag":532,"props":26104,"children":26105},{"style":804},[26106],{"type":420,"value":26107}," list",{"type":415,"tag":532,"props":26109,"children":26110},{"style":804},[26111],{"type":420,"value":26112}," --account-name",{"type":415,"tag":532,"props":26114,"children":26115},{"style":545},[26116],{"type":420,"value":26051},{"type":415,"tag":532,"props":26118,"children":26119},{"style":804},[26120],{"type":420,"value":11484},{"type":415,"tag":532,"props":26122,"children":26123},{"style":545},[26124],{"type":420,"value":26002},{"type":415,"tag":532,"props":26126,"children":26127},{"style":804},[26128],{"type":420,"value":26129},"-o",{"type":415,"tag":532,"props":26131,"children":26132},{"style":804},[26133],{"type":420,"value":26134}," tsv",{"type":415,"tag":532,"props":26136,"children":26137},{"style":804},[26138],{"type":420,"value":26139}," --query",{"type":415,"tag":532,"props":26141,"children":26142},{"style":551},[26143],{"type":420,"value":3697},{"type":415,"tag":532,"props":26145,"children":26146},{"style":804},[26147],{"type":420,"value":26148},"[0].value",{"type":415,"tag":532,"props":26150,"children":26151},{"style":551},[26152],{"type":420,"value":3707},{"type":415,"tag":416,"props":26154,"children":26155},{},[26156],{"type":420,"value":26157},"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":415,"tag":523,"props":26159,"children":26161},{"className":4059,"code":26160,"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",[26162],{"type":415,"tag":468,"props":26163,"children":26164},{"__ignoreMap":401},[26165,26255],{"type":415,"tag":532,"props":26166,"children":26167},{"class":534,"line":535},[26168,26172,26177,26181,26186,26190,26195,26199,26204,26208,26213,26217,26222,26226,26231,26235,26239,26243,26247,26251],{"type":415,"tag":532,"props":26169,"children":26170},{"style":551},[26171],{"type":420,"value":4072},{"type":415,"tag":532,"props":26173,"children":26174},{"style":545},[26175],{"type":420,"value":26176},"env:AZURE_STORAGE_KEY",{"type":415,"tag":532,"props":26178,"children":26179},{"style":551},[26180],{"type":420,"value":4197},{"type":415,"tag":532,"props":26182,"children":26183},{"style":545},[26184],{"type":420,"value":26185},"az storage account keys list ",{"type":415,"tag":532,"props":26187,"children":26188},{"style":551},[26189],{"type":420,"value":4216},{"type":415,"tag":532,"props":26191,"children":26192},{"style":545},[26193],{"type":420,"value":26194},"n ",{"type":415,"tag":532,"props":26196,"children":26197},{"style":551},[26198],{"type":420,"value":4072},{"type":415,"tag":532,"props":26200,"children":26201},{"style":545},[26202],{"type":420,"value":26203},"saName ",{"type":415,"tag":532,"props":26205,"children":26206},{"style":551},[26207],{"type":420,"value":4216},{"type":415,"tag":532,"props":26209,"children":26210},{"style":545},[26211],{"type":420,"value":26212},"g ",{"type":415,"tag":532,"props":26214,"children":26215},{"style":551},[26216],{"type":420,"value":4072},{"type":415,"tag":532,"props":26218,"children":26219},{"style":545},[26220],{"type":420,"value":26221},"rgName ",{"type":415,"tag":532,"props":26223,"children":26224},{"style":551},[26225],{"type":420,"value":4216},{"type":415,"tag":532,"props":26227,"children":26228},{"style":545},[26229],{"type":420,"value":26230},"o tsv ",{"type":415,"tag":532,"props":26232,"children":26233},{"style":551},[26234],{"type":420,"value":4115},{"type":415,"tag":532,"props":26236,"children":26237},{"style":545},[26238],{"type":420,"value":4317},{"type":415,"tag":532,"props":26240,"children":26241},{"style":551},[26242],{"type":420,"value":25010},{"type":415,"tag":532,"props":26244,"children":26245},{"style":804},[26246],{"type":420,"value":26148},{"type":415,"tag":532,"props":26248,"children":26249},{"style":551},[26250],{"type":420,"value":25010},{"type":415,"tag":532,"props":26252,"children":26253},{"style":551},[26254],{"type":420,"value":1113},{"type":415,"tag":532,"props":26256,"children":26257},{"class":534,"line":566},[26258,26262,26267,26272],{"type":415,"tag":532,"props":26259,"children":26260},{"style":551},[26261],{"type":420,"value":4072},{"type":415,"tag":532,"props":26263,"children":26264},{"style":545},[26265],{"type":420,"value":26266},"env:AZURE_STORAGE_ACCOUNT",{"type":415,"tag":532,"props":26268,"children":26269},{"style":551},[26270],{"type":420,"value":26271},"=$",{"type":415,"tag":532,"props":26273,"children":26274},{"style":545},[26275],{"type":420,"value":26276},"saName\n",{"type":415,"tag":416,"props":26278,"children":26279},{},[26280],{"type":420,"value":26281},"And finally, we can create the blob container that will contain the infrastructure state:",{"type":415,"tag":523,"props":26283,"children":26285},{"className":3984,"code":26284,"language":3986,"meta":401,"style":401},"az storage container create -n iacstate\n",[26286],{"type":415,"tag":468,"props":26287,"children":26288},{"__ignoreMap":401},[26289],{"type":415,"tag":532,"props":26290,"children":26291},{"class":534,"line":535},[26292,26296,26300,26305,26309,26313],{"type":415,"tag":532,"props":26293,"children":26294},{"style":631},[26295],{"type":420,"value":25983},{"type":415,"tag":532,"props":26297,"children":26298},{"style":804},[26299],{"type":420,"value":26024},{"type":415,"tag":532,"props":26301,"children":26302},{"style":804},[26303],{"type":420,"value":26304}," container",{"type":415,"tag":532,"props":26306,"children":26307},{"style":804},[26308],{"type":420,"value":25993},{"type":415,"tag":532,"props":26310,"children":26311},{"style":804},[26312],{"type":420,"value":6978},{"type":415,"tag":532,"props":26314,"children":26315},{"style":804},[26316],{"type":420,"value":26317}," iacstate\n",{"type":415,"tag":3914,"props":26319,"children":26321},{"id":26320},"how-to-provision-your-project-infrastructure-using-the-azure-blob-storage-backend",[26322],{"type":420,"value":26323},"How to provision your project infrastructure using the Azure Blob Storage backend?",{"type":415,"tag":416,"props":26325,"children":26326},{},[26327],{"type":420,"value":26328},"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":415,"tag":523,"props":26330,"children":26332},{"className":4059,"code":26331,"language":248,"meta":401,"style":401},"pulumi login azblob://iacstate\n",[26333],{"type":415,"tag":468,"props":26334,"children":26335},{"__ignoreMap":401},[26336],{"type":415,"tag":532,"props":26337,"children":26338},{"class":534,"line":535},[26339,26344,26349],{"type":415,"tag":532,"props":26340,"children":26341},{"style":545},[26342],{"type":420,"value":26343},"pulumi login azblob:",{"type":415,"tag":532,"props":26345,"children":26346},{"style":551},[26347],{"type":420,"value":26348},"//",{"type":415,"tag":532,"props":26350,"children":26351},{"style":545},[26352],{"type":420,"value":26353},"iacstate\n",{"type":415,"tag":416,"props":26355,"children":26356},{},[26357,26359,26365,26367,26372],{"type":420,"value":26358},"To verify Pulumi can correctly provision cloud resources using our Azure Blob Storage backend, we can create a new Pulumi project using the ",{"type":415,"tag":468,"props":26360,"children":26362},{"className":26361},[],[26363],{"type":420,"value":26364},"azure-csharp",{"type":420,"value":26366}," template and deploy the infrastructure with the ",{"type":415,"tag":468,"props":26368,"children":26370},{"className":26369},[],[26371],{"type":420,"value":10839},{"type":420,"value":26373}," command:",{"type":415,"tag":523,"props":26375,"children":26377},{"className":4059,"code":26376,"language":248,"meta":401,"style":401},"mkdir infra;cd infra;\npulumi new azure-csharp -n AzureStorageBackend -s dev -y\npulumi up -y\n",[26378],{"type":415,"tag":468,"props":26379,"children":26380},{"__ignoreMap":401},[26381,26402,26445],{"type":415,"tag":532,"props":26382,"children":26383},{"class":534,"line":535},[26384,26389,26393,26398],{"type":415,"tag":532,"props":26385,"children":26386},{"style":545},[26387],{"type":420,"value":26388},"mkdir infra",{"type":415,"tag":532,"props":26390,"children":26391},{"style":551},[26392],{"type":420,"value":15807},{"type":415,"tag":532,"props":26394,"children":26395},{"style":545},[26396],{"type":420,"value":26397},"cd infra",{"type":415,"tag":532,"props":26399,"children":26400},{"style":551},[26401],{"type":420,"value":563},{"type":415,"tag":532,"props":26403,"children":26404},{"class":534,"line":566},[26405,26410,26414,26419,26423,26428,26432,26436,26440],{"type":415,"tag":532,"props":26406,"children":26407},{"style":545},[26408],{"type":420,"value":26409},"pulumi new azure",{"type":415,"tag":532,"props":26411,"children":26412},{"style":551},[26413],{"type":420,"value":4216},{"type":415,"tag":532,"props":26415,"children":26416},{"style":545},[26417],{"type":420,"value":26418},"csharp ",{"type":415,"tag":532,"props":26420,"children":26421},{"style":551},[26422],{"type":420,"value":4216},{"type":415,"tag":532,"props":26424,"children":26425},{"style":545},[26426],{"type":420,"value":26427},"n AzureStorageBackend ",{"type":415,"tag":532,"props":26429,"children":26430},{"style":551},[26431],{"type":420,"value":4216},{"type":415,"tag":532,"props":26433,"children":26434},{"style":545},[26435],{"type":420,"value":11385},{"type":415,"tag":532,"props":26437,"children":26438},{"style":551},[26439],{"type":420,"value":4216},{"type":415,"tag":532,"props":26441,"children":26442},{"style":545},[26443],{"type":420,"value":26444},"y\n",{"type":415,"tag":532,"props":26446,"children":26447},{"class":534,"line":583},[26448,26453,26457],{"type":415,"tag":532,"props":26449,"children":26450},{"style":545},[26451],{"type":420,"value":26452},"pulumi up ",{"type":415,"tag":532,"props":26454,"children":26455},{"style":551},[26456],{"type":420,"value":4216},{"type":415,"tag":532,"props":26458,"children":26459},{"style":545},[26460],{"type":420,"value":26444},{"type":415,"tag":416,"props":26462,"children":26463},{},[26464],{"type":420,"value":26465},"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":415,"tag":416,"props":26467,"children":26468},{},[26469,26471,26476,26478,26484],{"type":420,"value":26470},"Once the ",{"type":415,"tag":468,"props":26472,"children":26474},{"className":26473},[],[26475],{"type":420,"value":10839},{"type":420,"value":26477}," command is finished, the infrastructure requested is provisioned, and we can see a new state file has been created in the ",{"type":415,"tag":468,"props":26479,"children":26481},{"className":26480},[],[26482],{"type":420,"value":26483},"iacstate",{"type":420,"value":26485}," blob container.",{"type":415,"tag":416,"props":26487,"children":26488},{},[26489],{"type":415,"tag":3882,"props":26490,"children":26494},{"alt":26491,"className":26492,"src":26493},"Azure Blob container explorer showing the Pulumi state file.",[3886,3887],"/posts/images/pulumiazurebackend_azure_1.png",[],{"type":415,"tag":482,"props":26496,"children":26498},{"id":26497},"managing-state-sensitive-data",[26499],{"type":420,"value":26500},"Managing state sensitive data",{"type":415,"tag":3914,"props":26502,"children":26504},{"id":26503},"why-is-it-needed-to-protect-sensitive-data-in-the-state",[26505],{"type":420,"value":26506},"Why is it needed to protect sensitive data in the state?",{"type":415,"tag":416,"props":26508,"children":26509},{},[26510],{"type":420,"value":26511},"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":415,"tag":416,"props":26513,"children":26514},{},[26515],{"type":420,"value":26516},"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":415,"tag":3914,"props":26518,"children":26520},{"id":26519},"what-are-the-available-encryption-providers",[26521],{"type":420,"value":26522},"What are the available encryption providers?",{"type":415,"tag":416,"props":26524,"children":26525},{},[26526],{"type":420,"value":26527},"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":415,"tag":416,"props":26529,"children":26530},{},[26531],{"type":420,"value":26532},"The passphrase is just one of the supported encryption/secrets providers but there are others:",{"type":415,"tag":508,"props":26534,"children":26535},{},[26536,26541,26545,26550,26555],{"type":415,"tag":512,"props":26537,"children":26538},{},[26539],{"type":420,"value":26540},"AWS Key Management Service",{"type":415,"tag":512,"props":26542,"children":26543},{},[26544],{"type":420,"value":260},{"type":415,"tag":512,"props":26546,"children":26547},{},[26548],{"type":420,"value":26549},"Google Cloud Key Management Service",{"type":415,"tag":512,"props":26551,"children":26552},{},[26553],{"type":420,"value":26554},"HashiCorp Vault Transit Secrets Engine",{"type":415,"tag":512,"props":26556,"children":26557},{},[26558],{"type":420,"value":26559},"Pulumi Service (used by default when using Pulumi Service as the backend)",{"type":415,"tag":416,"props":26561,"children":26562},{},[26563],{"type":420,"value":26564},"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":415,"tag":3914,"props":26566,"children":26568},{"id":26567},"how-to-use-azure-key-vault-as-the-encryption-provider",[26569],{"type":420,"value":26570},"How to use Azure Key Vault as the encryption provider?",{"type":415,"tag":416,"props":26572,"children":26573},{},[26574],{"type":420,"value":26575},"Let's first create a Key Vault:",{"type":415,"tag":523,"props":26577,"children":26579},{"className":4059,"code":26578,"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",[26580],{"type":415,"tag":468,"props":26581,"children":26582},{"__ignoreMap":401},[26583,26620],{"type":415,"tag":532,"props":26584,"children":26585},{"class":534,"line":535},[26586,26590,26595,26599,26603,26608,26612,26616],{"type":415,"tag":532,"props":26587,"children":26588},{"style":551},[26589],{"type":420,"value":4072},{"type":415,"tag":532,"props":26591,"children":26592},{"style":545},[26593],{"type":420,"value":26594},"kvName",{"type":415,"tag":532,"props":26596,"children":26597},{"style":551},[26598],{"type":420,"value":1134},{"type":415,"tag":532,"props":26600,"children":26601},{"style":551},[26602],{"type":420,"value":801},{"type":415,"tag":532,"props":26604,"children":26605},{"style":804},[26606],{"type":420,"value":26607},"kv-iacstate-westeu-",{"type":415,"tag":532,"props":26609,"children":26610},{"style":551},[26611],{"type":420,"value":4072},{"type":415,"tag":532,"props":26613,"children":26614},{"style":545},[26615],{"type":420,"value":25837},{"type":415,"tag":532,"props":26617,"children":26618},{"style":551},[26619],{"type":420,"value":4051},{"type":415,"tag":532,"props":26621,"children":26622},{"class":534,"line":566},[26623,26627,26632,26636,26641,26645,26649,26653,26657,26661,26665,26669,26674,26678,26683,26687,26692,26696,26700,26704,26708],{"type":415,"tag":532,"props":26624,"children":26625},{"style":551},[26626],{"type":420,"value":4072},{"type":415,"tag":532,"props":26628,"children":26629},{"style":545},[26630],{"type":420,"value":26631},"vaultId",{"type":415,"tag":532,"props":26633,"children":26634},{"style":551},[26635],{"type":420,"value":1134},{"type":415,"tag":532,"props":26637,"children":26638},{"style":545},[26639],{"type":420,"value":26640},"az keyvault create ",{"type":415,"tag":532,"props":26642,"children":26643},{"style":551},[26644],{"type":420,"value":4216},{"type":415,"tag":532,"props":26646,"children":26647},{"style":545},[26648],{"type":420,"value":26212},{"type":415,"tag":532,"props":26650,"children":26651},{"style":551},[26652],{"type":420,"value":4072},{"type":415,"tag":532,"props":26654,"children":26655},{"style":545},[26656],{"type":420,"value":26221},{"type":415,"tag":532,"props":26658,"children":26659},{"style":551},[26660],{"type":420,"value":4216},{"type":415,"tag":532,"props":26662,"children":26663},{"style":545},[26664],{"type":420,"value":26194},{"type":415,"tag":532,"props":26666,"children":26667},{"style":551},[26668],{"type":420,"value":4072},{"type":415,"tag":532,"props":26670,"children":26671},{"style":545},[26672],{"type":420,"value":26673},"kvName ",{"type":415,"tag":532,"props":26675,"children":26676},{"style":551},[26677],{"type":420,"value":4115},{"type":415,"tag":532,"props":26679,"children":26680},{"style":656},[26681],{"type":420,"value":26682},"enable-rbac",{"type":415,"tag":532,"props":26684,"children":26685},{"style":551},[26686],{"type":420,"value":4216},{"type":415,"tag":532,"props":26688,"children":26689},{"style":545},[26690],{"type":420,"value":26691},"authorization true ",{"type":415,"tag":532,"props":26693,"children":26694},{"style":551},[26695],{"type":420,"value":4115},{"type":415,"tag":532,"props":26697,"children":26698},{"style":545},[26699],{"type":420,"value":4317},{"type":415,"tag":532,"props":26701,"children":26702},{"style":551},[26703],{"type":420,"value":801},{"type":415,"tag":532,"props":26705,"children":26706},{"style":804},[26707],{"type":420,"value":4326},{"type":415,"tag":532,"props":26709,"children":26710},{"style":551},[26711],{"type":420,"value":4051},{"type":415,"tag":416,"props":26713,"children":26714},{},[26715,26717,26723],{"type":420,"value":26716},"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":415,"tag":468,"props":26718,"children":26720},{"className":26719},[],[26721],{"type":420,"value":26722},"--enable-rbac-authorization",{"type":420,"value":26724}," 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":415,"tag":416,"props":26726,"children":26727},{},[26728],{"type":420,"value":26729},"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":415,"tag":523,"props":26731,"children":26733},{"className":4059,"code":26732,"language":248,"meta":401,"style":401},"$myUserId=az ad signed-in-user show --query \"objectId\" -o tsv \n",[26734],{"type":415,"tag":468,"props":26735,"children":26736},{"__ignoreMap":401},[26737],{"type":415,"tag":532,"props":26738,"children":26739},{"class":534,"line":535},[26740,26744,26749,26753,26758,26762,26767,26771,26776,26780,26784,26788,26792,26796,26800],{"type":415,"tag":532,"props":26741,"children":26742},{"style":551},[26743],{"type":420,"value":4072},{"type":415,"tag":532,"props":26745,"children":26746},{"style":545},[26747],{"type":420,"value":26748},"myUserId",{"type":415,"tag":532,"props":26750,"children":26751},{"style":551},[26752],{"type":420,"value":1134},{"type":415,"tag":532,"props":26754,"children":26755},{"style":545},[26756],{"type":420,"value":26757},"az ad signed",{"type":415,"tag":532,"props":26759,"children":26760},{"style":551},[26761],{"type":420,"value":4216},{"type":415,"tag":532,"props":26763,"children":26764},{"style":545},[26765],{"type":420,"value":26766},"in",{"type":415,"tag":532,"props":26768,"children":26769},{"style":551},[26770],{"type":420,"value":4216},{"type":415,"tag":532,"props":26772,"children":26773},{"style":545},[26774],{"type":420,"value":26775},"user show ",{"type":415,"tag":532,"props":26777,"children":26778},{"style":551},[26779],{"type":420,"value":4115},{"type":415,"tag":532,"props":26781,"children":26782},{"style":545},[26783],{"type":420,"value":4317},{"type":415,"tag":532,"props":26785,"children":26786},{"style":551},[26787],{"type":420,"value":801},{"type":415,"tag":532,"props":26789,"children":26790},{"style":804},[26791],{"type":420,"value":12332},{"type":415,"tag":532,"props":26793,"children":26794},{"style":551},[26795],{"type":420,"value":801},{"type":415,"tag":532,"props":26797,"children":26798},{"style":551},[26799],{"type":420,"value":4335},{"type":415,"tag":532,"props":26801,"children":26802},{"style":545},[26803],{"type":420,"value":26804},"o tsv\n",{"type":415,"tag":416,"props":26806,"children":26807},{},[26808,26810,26816],{"type":420,"value":26809},"We can then assign to this user the ",{"type":415,"tag":468,"props":26811,"children":26813},{"className":26812},[],[26814],{"type":420,"value":26815},"Key Vault Crypto Officer",{"type":420,"value":26817}," role that will allow us to create a key and encrypt/decrypt data.",{"type":415,"tag":523,"props":26819,"children":26821},{"className":4059,"code":26820,"language":248,"meta":401,"style":401},"az role assignment create --scope $vaultId --role \"Key Vault Crypto Officer\" --assignee $myUserId \n",[26822],{"type":415,"tag":468,"props":26823,"children":26824},{"__ignoreMap":401},[26825],{"type":415,"tag":532,"props":26826,"children":26827},{"class":534,"line":535},[26828,26832,26836,26840,26844,26849,26853,26858,26862,26866,26870,26874,26879,26883],{"type":415,"tag":532,"props":26829,"children":26830},{"style":545},[26831],{"type":420,"value":4625},{"type":415,"tag":532,"props":26833,"children":26834},{"style":551},[26835],{"type":420,"value":4115},{"type":415,"tag":532,"props":26837,"children":26838},{"style":545},[26839],{"type":420,"value":4723},{"type":415,"tag":532,"props":26841,"children":26842},{"style":551},[26843],{"type":420,"value":4072},{"type":415,"tag":532,"props":26845,"children":26846},{"style":545},[26847],{"type":420,"value":26848},"vaultId ",{"type":415,"tag":532,"props":26850,"children":26851},{"style":551},[26852],{"type":420,"value":4115},{"type":415,"tag":532,"props":26854,"children":26855},{"style":545},[26856],{"type":420,"value":26857},"role ",{"type":415,"tag":532,"props":26859,"children":26860},{"style":551},[26861],{"type":420,"value":801},{"type":415,"tag":532,"props":26863,"children":26864},{"style":804},[26865],{"type":420,"value":26815},{"type":415,"tag":532,"props":26867,"children":26868},{"style":551},[26869],{"type":420,"value":801},{"type":415,"tag":532,"props":26871,"children":26872},{"style":551},[26873],{"type":420,"value":4139},{"type":415,"tag":532,"props":26875,"children":26876},{"style":545},[26877],{"type":420,"value":26878},"assignee ",{"type":415,"tag":532,"props":26880,"children":26881},{"style":551},[26882],{"type":420,"value":4072},{"type":415,"tag":532,"props":26884,"children":26885},{"style":545},[26886],{"type":420,"value":26887},"myUserId\n",{"type":415,"tag":416,"props":26889,"children":26890},{},[26891],{"type":420,"value":26892},"The key to encrypt/decrypt data can be created with the following command:",{"type":415,"tag":523,"props":26894,"children":26896},{"className":4059,"code":26895,"language":248,"meta":401,"style":401},"az keyvault key create -n encryptionState --vault-name $kvName\n",[26897],{"type":415,"tag":468,"props":26898,"children":26899},{"__ignoreMap":401},[26900],{"type":415,"tag":532,"props":26901,"children":26902},{"class":534,"line":535},[26903,26908,26912,26917,26921,26926,26930,26934,26938],{"type":415,"tag":532,"props":26904,"children":26905},{"style":545},[26906],{"type":420,"value":26907},"az keyvault key create ",{"type":415,"tag":532,"props":26909,"children":26910},{"style":551},[26911],{"type":420,"value":4216},{"type":415,"tag":532,"props":26913,"children":26914},{"style":545},[26915],{"type":420,"value":26916},"n encryptionState ",{"type":415,"tag":532,"props":26918,"children":26919},{"style":551},[26920],{"type":420,"value":4115},{"type":415,"tag":532,"props":26922,"children":26923},{"style":545},[26924],{"type":420,"value":26925},"vault",{"type":415,"tag":532,"props":26927,"children":26928},{"style":551},[26929],{"type":420,"value":4216},{"type":415,"tag":532,"props":26931,"children":26932},{"style":545},[26933],{"type":420,"value":4479},{"type":415,"tag":532,"props":26935,"children":26936},{"style":551},[26937],{"type":420,"value":4072},{"type":415,"tag":532,"props":26939,"children":26940},{"style":545},[26941],{"type":420,"value":26942},"kvName\n",{"type":415,"tag":416,"props":26944,"children":26945},{},[26946],{"type":420,"value":26947},"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":415,"tag":523,"props":26949,"children":26951},{"className":4059,"code":26950,"language":248,"meta":401,"style":401},"$env:AZURE_KEYVAULT_AUTH_VIA_CLI=\"true\"\n",[26952],{"type":415,"tag":468,"props":26953,"children":26954},{"__ignoreMap":401},[26955],{"type":415,"tag":532,"props":26956,"children":26957},{"class":534,"line":535},[26958,26962,26967,26971,26975,26979],{"type":415,"tag":532,"props":26959,"children":26960},{"style":551},[26961],{"type":420,"value":4072},{"type":415,"tag":532,"props":26963,"children":26964},{"style":545},[26965],{"type":420,"value":26966},"env:AZURE_KEYVAULT_AUTH_VIA_CLI",{"type":415,"tag":532,"props":26968,"children":26969},{"style":551},[26970],{"type":420,"value":1134},{"type":415,"tag":532,"props":26972,"children":26973},{"style":551},[26974],{"type":420,"value":801},{"type":415,"tag":532,"props":26976,"children":26977},{"style":804},[26978],{"type":420,"value":11958},{"type":415,"tag":532,"props":26980,"children":26981},{"style":551},[26982],{"type":420,"value":4051},{"type":415,"tag":416,"props":26984,"children":26985},{},[26986],{"type":420,"value":26987},"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":415,"tag":523,"props":26989,"children":26991},{"className":4059,"code":26990,"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",[26992],{"type":415,"tag":468,"props":26993,"children":26994},{"__ignoreMap":401},[26995],{"type":415,"tag":532,"props":26996,"children":26997},{"class":534,"line":535},[26998,27002,27006,27010,27014,27018,27022,27026,27030,27035,27039,27044,27048,27053,27057,27061,27066,27070,27074,27079],{"type":415,"tag":532,"props":26999,"children":27000},{"style":545},[27001],{"type":420,"value":26409},{"type":415,"tag":532,"props":27003,"children":27004},{"style":551},[27005],{"type":420,"value":4216},{"type":415,"tag":532,"props":27007,"children":27008},{"style":545},[27009],{"type":420,"value":26418},{"type":415,"tag":532,"props":27011,"children":27012},{"style":551},[27013],{"type":420,"value":4216},{"type":415,"tag":532,"props":27015,"children":27016},{"style":545},[27017],{"type":420,"value":26427},{"type":415,"tag":532,"props":27019,"children":27020},{"style":551},[27021],{"type":420,"value":4216},{"type":415,"tag":532,"props":27023,"children":27024},{"style":545},[27025],{"type":420,"value":11385},{"type":415,"tag":532,"props":27027,"children":27028},{"style":551},[27029],{"type":420,"value":4216},{"type":415,"tag":532,"props":27031,"children":27032},{"style":545},[27033],{"type":420,"value":27034},"y ",{"type":415,"tag":532,"props":27036,"children":27037},{"style":551},[27038],{"type":420,"value":4115},{"type":415,"tag":532,"props":27040,"children":27041},{"style":545},[27042],{"type":420,"value":27043},"secrets",{"type":415,"tag":532,"props":27045,"children":27046},{"style":551},[27047],{"type":420,"value":4216},{"type":415,"tag":532,"props":27049,"children":27050},{"style":545},[27051],{"type":420,"value":27052},"provider",{"type":415,"tag":532,"props":27054,"children":27055},{"style":551},[27056],{"type":420,"value":1134},{"type":415,"tag":532,"props":27058,"children":27059},{"style":551},[27060],{"type":420,"value":801},{"type":415,"tag":532,"props":27062,"children":27063},{"style":804},[27064],{"type":420,"value":27065},"azurekeyvault://",{"type":415,"tag":532,"props":27067,"children":27068},{"style":551},[27069],{"type":420,"value":4072},{"type":415,"tag":532,"props":27071,"children":27072},{"style":545},[27073],{"type":420,"value":26594},{"type":415,"tag":532,"props":27075,"children":27076},{"style":804},[27077],{"type":420,"value":27078},".vault.azure.net/keys/encryptionState",{"type":415,"tag":532,"props":27080,"children":27081},{"style":551},[27082],{"type":420,"value":4051},{"type":415,"tag":482,"props":27084,"children":27086},{"id":27085},"comparing-with-how-terraform-handle-state",[27087],{"type":420,"value":27088},"Comparing with how Terraform handle state",{"type":415,"tag":416,"props":27090,"children":27091},{},[27092],{"type":420,"value":27093},"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":415,"tag":416,"props":27095,"children":27096},{},[27097],{"type":420,"value":27098},"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":415,"tag":416,"props":27100,"children":27101},{},[27102,27104,27111],{"type":420,"value":27103},"On Microsoft documentation, there is a tutorial ",{"type":415,"tag":423,"props":27105,"children":27108},{"href":27106,"rel":27107},"https://docs.microsoft.com/en-us/azure/developer/terraform/store-state-in-azure-storage",[427],[27109],{"type":420,"value":27110},"\"Store Terraform state in Azure Storage\"",{"type":420,"value":27112}," 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":415,"tag":416,"props":27114,"children":27115},{},[27116,27118,27125,27127,27133],{"type":420,"value":27117},"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":415,"tag":423,"props":27119,"children":27122},{"href":27120,"rel":27121},"https://www.terraform.io/docs/language/state/sensitive-data.html",[427],[27123],{"type":420,"value":27124},"Terraform documentation",{"type":420,"value":27126}," just says to ",{"type":415,"tag":468,"props":27128,"children":27130},{"className":27129},[],[27131],{"type":420,"value":27132},"treat the state itself as sensitive data",{"type":420,"value":27134},". 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":415,"tag":416,"props":27136,"children":27137},{},[27138],{"type":415,"tag":3882,"props":27139,"children":27143},{"alt":27140,"className":27141,"src":27142},"Terraform state file containing clear text sensitive information in vscode.",[3886,3887],"/posts/images/pulumiazurebackend_tf_1.png",[],{"type":415,"tag":416,"props":27145,"children":27146},{},[27147],{"type":420,"value":27148},"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":415,"tag":482,"props":27150,"children":27151},{"id":10889},[27152],{"type":420,"value":10892},{"type":415,"tag":416,"props":27154,"children":27155},{},[27156],{"type":420,"value":27157},"You can find below the complete Azure CLI script used in this article:",{"type":415,"tag":523,"props":27159,"children":27161},{"className":4059,"code":27160,"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",[27162],{"type":415,"tag":468,"props":27163,"children":27164},{"__ignoreMap":401},[27165,27173,27204,27231,27266,27301,27336,27343,27384,27391,27399,27465,27473,27556,27575,27592,27599,27607,27694,27758,27818,27857,27865,27892,27899,27907,27922,27930,27949,27957,28040,28048],{"type":415,"tag":532,"props":27166,"children":27167},{"class":534,"line":535},[27168],{"type":415,"tag":532,"props":27169,"children":27170},{"style":5425},[27171],{"type":420,"value":27172},"# PowerShell variables used in the script \n",{"type":415,"tag":532,"props":27174,"children":27175},{"class":534,"line":566},[27176,27180,27184,27188,27192,27196,27200],{"type":415,"tag":532,"props":27177,"children":27178},{"style":551},[27179],{"type":420,"value":4072},{"type":415,"tag":532,"props":27181,"children":27182},{"style":545},[27183],{"type":420,"value":25837},{"type":415,"tag":532,"props":27185,"children":27186},{"style":551},[27187],{"type":420,"value":1134},{"type":415,"tag":532,"props":27189,"children":27190},{"style":656},[27191],{"type":420,"value":25846},{"type":415,"tag":532,"props":27193,"children":27194},{"style":551},[27195],{"type":420,"value":4335},{"type":415,"tag":532,"props":27197,"children":27198},{"style":545},[27199],{"type":420,"value":25855},{"type":415,"tag":532,"props":27201,"children":27202},{"style":539},[27203],{"type":420,"value":25860},{"type":415,"tag":532,"props":27205,"children":27206},{"class":534,"line":583},[27207,27211,27215,27219,27223,27227],{"type":415,"tag":532,"props":27208,"children":27209},{"style":551},[27210],{"type":420,"value":4072},{"type":415,"tag":532,"props":27212,"children":27213},{"style":545},[27214],{"type":420,"value":25872},{"type":415,"tag":532,"props":27216,"children":27217},{"style":551},[27218],{"type":420,"value":1134},{"type":415,"tag":532,"props":27220,"children":27221},{"style":551},[27222],{"type":420,"value":801},{"type":415,"tag":532,"props":27224,"children":27225},{"style":804},[27226],{"type":420,"value":25885},{"type":415,"tag":532,"props":27228,"children":27229},{"style":551},[27230],{"type":420,"value":4051},{"type":415,"tag":532,"props":27232,"children":27233},{"class":534,"line":617},[27234,27238,27242,27246,27250,27254,27258,27262],{"type":415,"tag":532,"props":27235,"children":27236},{"style":551},[27237],{"type":420,"value":4072},{"type":415,"tag":532,"props":27239,"children":27240},{"style":545},[27241],{"type":420,"value":25901},{"type":415,"tag":532,"props":27243,"children":27244},{"style":551},[27245],{"type":420,"value":1134},{"type":415,"tag":532,"props":27247,"children":27248},{"style":551},[27249],{"type":420,"value":801},{"type":415,"tag":532,"props":27251,"children":27252},{"style":804},[27253],{"type":420,"value":25914},{"type":415,"tag":532,"props":27255,"children":27256},{"style":551},[27257],{"type":420,"value":4072},{"type":415,"tag":532,"props":27259,"children":27260},{"style":545},[27261],{"type":420,"value":25837},{"type":415,"tag":532,"props":27263,"children":27264},{"style":551},[27265],{"type":420,"value":4051},{"type":415,"tag":532,"props":27267,"children":27268},{"class":534,"line":627},[27269,27273,27277,27281,27285,27289,27293,27297],{"type":415,"tag":532,"props":27270,"children":27271},{"style":551},[27272],{"type":420,"value":4072},{"type":415,"tag":532,"props":27274,"children":27275},{"style":545},[27276],{"type":420,"value":25938},{"type":415,"tag":532,"props":27278,"children":27279},{"style":551},[27280],{"type":420,"value":1134},{"type":415,"tag":532,"props":27282,"children":27283},{"style":551},[27284],{"type":420,"value":801},{"type":415,"tag":532,"props":27286,"children":27287},{"style":804},[27288],{"type":420,"value":25951},{"type":415,"tag":532,"props":27290,"children":27291},{"style":551},[27292],{"type":420,"value":4072},{"type":415,"tag":532,"props":27294,"children":27295},{"style":545},[27296],{"type":420,"value":25837},{"type":415,"tag":532,"props":27298,"children":27299},{"style":551},[27300],{"type":420,"value":4051},{"type":415,"tag":532,"props":27302,"children":27303},{"class":534,"line":677},[27304,27308,27312,27316,27320,27324,27328,27332],{"type":415,"tag":532,"props":27305,"children":27306},{"style":551},[27307],{"type":420,"value":4072},{"type":415,"tag":532,"props":27309,"children":27310},{"style":545},[27311],{"type":420,"value":26594},{"type":415,"tag":532,"props":27313,"children":27314},{"style":551},[27315],{"type":420,"value":1134},{"type":415,"tag":532,"props":27317,"children":27318},{"style":551},[27319],{"type":420,"value":801},{"type":415,"tag":532,"props":27321,"children":27322},{"style":804},[27323],{"type":420,"value":26607},{"type":415,"tag":532,"props":27325,"children":27326},{"style":551},[27327],{"type":420,"value":4072},{"type":415,"tag":532,"props":27329,"children":27330},{"style":545},[27331],{"type":420,"value":25837},{"type":415,"tag":532,"props":27333,"children":27334},{"style":551},[27335],{"type":420,"value":4051},{"type":415,"tag":532,"props":27337,"children":27338},{"class":534,"line":719},[27339],{"type":415,"tag":532,"props":27340,"children":27341},{"emptyLinePlaceholder":621},[27342],{"type":420,"value":624},{"type":415,"tag":532,"props":27344,"children":27345},{"class":534,"line":758},[27346,27351,27355,27359,27363,27367,27371,27375,27379],{"type":415,"tag":532,"props":27347,"children":27348},{"style":545},[27349],{"type":420,"value":27350},"az group create ",{"type":415,"tag":532,"props":27352,"children":27353},{"style":551},[27354],{"type":420,"value":4216},{"type":415,"tag":532,"props":27356,"children":27357},{"style":545},[27358],{"type":420,"value":26194},{"type":415,"tag":532,"props":27360,"children":27361},{"style":551},[27362],{"type":420,"value":4072},{"type":415,"tag":532,"props":27364,"children":27365},{"style":545},[27366],{"type":420,"value":26221},{"type":415,"tag":532,"props":27368,"children":27369},{"style":551},[27370],{"type":420,"value":4216},{"type":415,"tag":532,"props":27372,"children":27373},{"style":545},[27374],{"type":420,"value":24991},{"type":415,"tag":532,"props":27376,"children":27377},{"style":551},[27378],{"type":420,"value":4072},{"type":415,"tag":532,"props":27380,"children":27381},{"style":545},[27382],{"type":420,"value":27383},"location\n",{"type":415,"tag":532,"props":27385,"children":27386},{"class":534,"line":767},[27387],{"type":415,"tag":532,"props":27388,"children":27389},{"emptyLinePlaceholder":621},[27390],{"type":420,"value":624},{"type":415,"tag":532,"props":27392,"children":27393},{"class":534,"line":819},[27394],{"type":415,"tag":532,"props":27395,"children":27396},{"style":5425},[27397],{"type":420,"value":27398},"# Configure the Azure Blob Storage that will contain the state \n",{"type":415,"tag":532,"props":27400,"children":27401},{"class":534,"line":850},[27402,27407,27411,27415,27419,27423,27427,27431,27435,27439,27443,27447,27451,27456,27460],{"type":415,"tag":532,"props":27403,"children":27404},{"style":545},[27405],{"type":420,"value":27406},"az storage account create ",{"type":415,"tag":532,"props":27408,"children":27409},{"style":551},[27410],{"type":420,"value":4216},{"type":415,"tag":532,"props":27412,"children":27413},{"style":545},[27414],{"type":420,"value":26212},{"type":415,"tag":532,"props":27416,"children":27417},{"style":551},[27418],{"type":420,"value":4072},{"type":415,"tag":532,"props":27420,"children":27421},{"style":545},[27422],{"type":420,"value":26221},{"type":415,"tag":532,"props":27424,"children":27425},{"style":551},[27426],{"type":420,"value":4216},{"type":415,"tag":532,"props":27428,"children":27429},{"style":545},[27430],{"type":420,"value":26194},{"type":415,"tag":532,"props":27432,"children":27433},{"style":551},[27434],{"type":420,"value":4072},{"type":415,"tag":532,"props":27436,"children":27437},{"style":545},[27438],{"type":420,"value":26203},{"type":415,"tag":532,"props":27440,"children":27441},{"style":551},[27442],{"type":420,"value":4216},{"type":415,"tag":532,"props":27444,"children":27445},{"style":545},[27446],{"type":420,"value":24991},{"type":415,"tag":532,"props":27448,"children":27449},{"style":551},[27450],{"type":420,"value":4072},{"type":415,"tag":532,"props":27452,"children":27453},{"style":545},[27454],{"type":420,"value":27455},"location ",{"type":415,"tag":532,"props":27457,"children":27458},{"style":551},[27459],{"type":420,"value":4115},{"type":415,"tag":532,"props":27461,"children":27462},{"style":545},[27463],{"type":420,"value":27464},"sku Standard_LRS\n",{"type":415,"tag":532,"props":27466,"children":27467},{"class":534,"line":859},[27468],{"type":415,"tag":532,"props":27469,"children":27470},{"style":5425},[27471],{"type":420,"value":27472},"# Set environment variables needed to write on the storage account\n",{"type":415,"tag":532,"props":27474,"children":27475},{"class":534,"line":867},[27476,27480,27484,27488,27492,27496,27500,27504,27508,27512,27516,27520,27524,27528,27532,27536,27540,27544,27548,27552],{"type":415,"tag":532,"props":27477,"children":27478},{"style":551},[27479],{"type":420,"value":4072},{"type":415,"tag":532,"props":27481,"children":27482},{"style":545},[27483],{"type":420,"value":26176},{"type":415,"tag":532,"props":27485,"children":27486},{"style":551},[27487],{"type":420,"value":4197},{"type":415,"tag":532,"props":27489,"children":27490},{"style":545},[27491],{"type":420,"value":26185},{"type":415,"tag":532,"props":27493,"children":27494},{"style":551},[27495],{"type":420,"value":4216},{"type":415,"tag":532,"props":27497,"children":27498},{"style":545},[27499],{"type":420,"value":26194},{"type":415,"tag":532,"props":27501,"children":27502},{"style":551},[27503],{"type":420,"value":4072},{"type":415,"tag":532,"props":27505,"children":27506},{"style":545},[27507],{"type":420,"value":26203},{"type":415,"tag":532,"props":27509,"children":27510},{"style":551},[27511],{"type":420,"value":4216},{"type":415,"tag":532,"props":27513,"children":27514},{"style":545},[27515],{"type":420,"value":26212},{"type":415,"tag":532,"props":27517,"children":27518},{"style":551},[27519],{"type":420,"value":4072},{"type":415,"tag":532,"props":27521,"children":27522},{"style":545},[27523],{"type":420,"value":26221},{"type":415,"tag":532,"props":27525,"children":27526},{"style":551},[27527],{"type":420,"value":4216},{"type":415,"tag":532,"props":27529,"children":27530},{"style":545},[27531],{"type":420,"value":26230},{"type":415,"tag":532,"props":27533,"children":27534},{"style":551},[27535],{"type":420,"value":4115},{"type":415,"tag":532,"props":27537,"children":27538},{"style":545},[27539],{"type":420,"value":4317},{"type":415,"tag":532,"props":27541,"children":27542},{"style":551},[27543],{"type":420,"value":25010},{"type":415,"tag":532,"props":27545,"children":27546},{"style":804},[27547],{"type":420,"value":26148},{"type":415,"tag":532,"props":27549,"children":27550},{"style":551},[27551],{"type":420,"value":25010},{"type":415,"tag":532,"props":27553,"children":27554},{"style":551},[27555],{"type":420,"value":1113},{"type":415,"tag":532,"props":27557,"children":27558},{"class":534,"line":902},[27559,27563,27567,27571],{"type":415,"tag":532,"props":27560,"children":27561},{"style":551},[27562],{"type":420,"value":4072},{"type":415,"tag":532,"props":27564,"children":27565},{"style":545},[27566],{"type":420,"value":26266},{"type":415,"tag":532,"props":27568,"children":27569},{"style":551},[27570],{"type":420,"value":26271},{"type":415,"tag":532,"props":27572,"children":27573},{"style":545},[27574],{"type":420,"value":26276},{"type":415,"tag":532,"props":27576,"children":27577},{"class":534,"line":1302},[27578,27583,27587],{"type":415,"tag":532,"props":27579,"children":27580},{"style":545},[27581],{"type":420,"value":27582},"az storage container create ",{"type":415,"tag":532,"props":27584,"children":27585},{"style":551},[27586],{"type":420,"value":4216},{"type":415,"tag":532,"props":27588,"children":27589},{"style":545},[27590],{"type":420,"value":27591},"n iacstate\n",{"type":415,"tag":532,"props":27593,"children":27594},{"class":534,"line":1311},[27595],{"type":415,"tag":532,"props":27596,"children":27597},{"emptyLinePlaceholder":621},[27598],{"type":420,"value":624},{"type":415,"tag":532,"props":27600,"children":27601},{"class":534,"line":1356},[27602],{"type":415,"tag":532,"props":27603,"children":27604},{"style":5425},[27605],{"type":420,"value":27606},"# Configure the Key Vault that will be used to encrypt the sensitive data\n",{"type":415,"tag":532,"props":27608,"children":27609},{"class":534,"line":1365},[27610,27614,27618,27622,27626,27630,27634,27638,27642,27646,27650,27654,27658,27662,27666,27670,27674,27678,27682,27686,27690],{"type":415,"tag":532,"props":27611,"children":27612},{"style":551},[27613],{"type":420,"value":4072},{"type":415,"tag":532,"props":27615,"children":27616},{"style":545},[27617],{"type":420,"value":26631},{"type":415,"tag":532,"props":27619,"children":27620},{"style":551},[27621],{"type":420,"value":1134},{"type":415,"tag":532,"props":27623,"children":27624},{"style":545},[27625],{"type":420,"value":26640},{"type":415,"tag":532,"props":27627,"children":27628},{"style":551},[27629],{"type":420,"value":4216},{"type":415,"tag":532,"props":27631,"children":27632},{"style":545},[27633],{"type":420,"value":26212},{"type":415,"tag":532,"props":27635,"children":27636},{"style":551},[27637],{"type":420,"value":4072},{"type":415,"tag":532,"props":27639,"children":27640},{"style":545},[27641],{"type":420,"value":26221},{"type":415,"tag":532,"props":27643,"children":27644},{"style":551},[27645],{"type":420,"value":4216},{"type":415,"tag":532,"props":27647,"children":27648},{"style":545},[27649],{"type":420,"value":26194},{"type":415,"tag":532,"props":27651,"children":27652},{"style":551},[27653],{"type":420,"value":4072},{"type":415,"tag":532,"props":27655,"children":27656},{"style":545},[27657],{"type":420,"value":26673},{"type":415,"tag":532,"props":27659,"children":27660},{"style":551},[27661],{"type":420,"value":4115},{"type":415,"tag":532,"props":27663,"children":27664},{"style":656},[27665],{"type":420,"value":26682},{"type":415,"tag":532,"props":27667,"children":27668},{"style":551},[27669],{"type":420,"value":4216},{"type":415,"tag":532,"props":27671,"children":27672},{"style":545},[27673],{"type":420,"value":26691},{"type":415,"tag":532,"props":27675,"children":27676},{"style":551},[27677],{"type":420,"value":4115},{"type":415,"tag":532,"props":27679,"children":27680},{"style":545},[27681],{"type":420,"value":4317},{"type":415,"tag":532,"props":27683,"children":27684},{"style":551},[27685],{"type":420,"value":801},{"type":415,"tag":532,"props":27687,"children":27688},{"style":804},[27689],{"type":420,"value":4326},{"type":415,"tag":532,"props":27691,"children":27692},{"style":551},[27693],{"type":420,"value":4051},{"type":415,"tag":532,"props":27695,"children":27696},{"class":534,"line":1373},[27697,27701,27705,27709,27713,27717,27721,27725,27729,27733,27737,27741,27745,27749,27753],{"type":415,"tag":532,"props":27698,"children":27699},{"style":551},[27700],{"type":420,"value":4072},{"type":415,"tag":532,"props":27702,"children":27703},{"style":545},[27704],{"type":420,"value":26748},{"type":415,"tag":532,"props":27706,"children":27707},{"style":551},[27708],{"type":420,"value":1134},{"type":415,"tag":532,"props":27710,"children":27711},{"style":545},[27712],{"type":420,"value":26757},{"type":415,"tag":532,"props":27714,"children":27715},{"style":551},[27716],{"type":420,"value":4216},{"type":415,"tag":532,"props":27718,"children":27719},{"style":545},[27720],{"type":420,"value":26766},{"type":415,"tag":532,"props":27722,"children":27723},{"style":551},[27724],{"type":420,"value":4216},{"type":415,"tag":532,"props":27726,"children":27727},{"style":545},[27728],{"type":420,"value":26775},{"type":415,"tag":532,"props":27730,"children":27731},{"style":551},[27732],{"type":420,"value":4115},{"type":415,"tag":532,"props":27734,"children":27735},{"style":545},[27736],{"type":420,"value":4317},{"type":415,"tag":532,"props":27738,"children":27739},{"style":551},[27740],{"type":420,"value":801},{"type":415,"tag":532,"props":27742,"children":27743},{"style":804},[27744],{"type":420,"value":12332},{"type":415,"tag":532,"props":27746,"children":27747},{"style":551},[27748],{"type":420,"value":801},{"type":415,"tag":532,"props":27750,"children":27751},{"style":551},[27752],{"type":420,"value":4335},{"type":415,"tag":532,"props":27754,"children":27755},{"style":545},[27756],{"type":420,"value":27757},"o tsv \n",{"type":415,"tag":532,"props":27759,"children":27760},{"class":534,"line":3825},[27761,27765,27769,27773,27777,27781,27785,27789,27793,27797,27801,27805,27809,27813],{"type":415,"tag":532,"props":27762,"children":27763},{"style":545},[27764],{"type":420,"value":4625},{"type":415,"tag":532,"props":27766,"children":27767},{"style":551},[27768],{"type":420,"value":4115},{"type":415,"tag":532,"props":27770,"children":27771},{"style":545},[27772],{"type":420,"value":4723},{"type":415,"tag":532,"props":27774,"children":27775},{"style":551},[27776],{"type":420,"value":4072},{"type":415,"tag":532,"props":27778,"children":27779},{"style":545},[27780],{"type":420,"value":26848},{"type":415,"tag":532,"props":27782,"children":27783},{"style":551},[27784],{"type":420,"value":4115},{"type":415,"tag":532,"props":27786,"children":27787},{"style":545},[27788],{"type":420,"value":26857},{"type":415,"tag":532,"props":27790,"children":27791},{"style":551},[27792],{"type":420,"value":801},{"type":415,"tag":532,"props":27794,"children":27795},{"style":804},[27796],{"type":420,"value":26815},{"type":415,"tag":532,"props":27798,"children":27799},{"style":551},[27800],{"type":420,"value":801},{"type":415,"tag":532,"props":27802,"children":27803},{"style":551},[27804],{"type":420,"value":4139},{"type":415,"tag":532,"props":27806,"children":27807},{"style":545},[27808],{"type":420,"value":26878},{"type":415,"tag":532,"props":27810,"children":27811},{"style":551},[27812],{"type":420,"value":4072},{"type":415,"tag":532,"props":27814,"children":27815},{"style":545},[27816],{"type":420,"value":27817},"myUserId \n",{"type":415,"tag":532,"props":27819,"children":27820},{"class":534,"line":3843},[27821,27825,27829,27833,27837,27841,27845,27849,27853],{"type":415,"tag":532,"props":27822,"children":27823},{"style":545},[27824],{"type":420,"value":26907},{"type":415,"tag":532,"props":27826,"children":27827},{"style":551},[27828],{"type":420,"value":4216},{"type":415,"tag":532,"props":27830,"children":27831},{"style":545},[27832],{"type":420,"value":26916},{"type":415,"tag":532,"props":27834,"children":27835},{"style":551},[27836],{"type":420,"value":4115},{"type":415,"tag":532,"props":27838,"children":27839},{"style":545},[27840],{"type":420,"value":26925},{"type":415,"tag":532,"props":27842,"children":27843},{"style":551},[27844],{"type":420,"value":4216},{"type":415,"tag":532,"props":27846,"children":27847},{"style":545},[27848],{"type":420,"value":4479},{"type":415,"tag":532,"props":27850,"children":27851},{"style":551},[27852],{"type":420,"value":4072},{"type":415,"tag":532,"props":27854,"children":27855},{"style":545},[27856],{"type":420,"value":26942},{"type":415,"tag":532,"props":27858,"children":27859},{"class":534,"line":3852},[27860],{"type":415,"tag":532,"props":27861,"children":27862},{"style":5425},[27863],{"type":420,"value":27864},"# Use az cli to authenticate to key vault instead of using environment variables \n",{"type":415,"tag":532,"props":27866,"children":27867},{"class":534,"line":5941},[27868,27872,27876,27880,27884,27888],{"type":415,"tag":532,"props":27869,"children":27870},{"style":551},[27871],{"type":420,"value":4072},{"type":415,"tag":532,"props":27873,"children":27874},{"style":545},[27875],{"type":420,"value":26966},{"type":415,"tag":532,"props":27877,"children":27878},{"style":551},[27879],{"type":420,"value":1134},{"type":415,"tag":532,"props":27881,"children":27882},{"style":551},[27883],{"type":420,"value":801},{"type":415,"tag":532,"props":27885,"children":27886},{"style":804},[27887],{"type":420,"value":11958},{"type":415,"tag":532,"props":27889,"children":27890},{"style":551},[27891],{"type":420,"value":4051},{"type":415,"tag":532,"props":27893,"children":27894},{"class":534,"line":6053},[27895],{"type":415,"tag":532,"props":27896,"children":27897},{"emptyLinePlaceholder":621},[27898],{"type":420,"value":624},{"type":415,"tag":532,"props":27900,"children":27901},{"class":534,"line":6061},[27902],{"type":415,"tag":532,"props":27903,"children":27904},{"style":5425},[27905],{"type":420,"value":27906},"# Indicate pulumi to use the newly created azure blob storage as a backend\n",{"type":415,"tag":532,"props":27908,"children":27909},{"class":534,"line":6070},[27910,27914,27918],{"type":415,"tag":532,"props":27911,"children":27912},{"style":545},[27913],{"type":420,"value":26343},{"type":415,"tag":532,"props":27915,"children":27916},{"style":551},[27917],{"type":420,"value":26348},{"type":415,"tag":532,"props":27919,"children":27920},{"style":545},[27921],{"type":420,"value":26353},{"type":415,"tag":532,"props":27923,"children":27924},{"class":534,"line":6094},[27925],{"type":415,"tag":532,"props":27926,"children":27927},{"style":5425},[27928],{"type":420,"value":27929},"# Create and use a folder to store the infrastructure code\n",{"type":415,"tag":532,"props":27931,"children":27932},{"class":534,"line":6118},[27933,27937,27941,27945],{"type":415,"tag":532,"props":27934,"children":27935},{"style":545},[27936],{"type":420,"value":26388},{"type":415,"tag":532,"props":27938,"children":27939},{"style":551},[27940],{"type":420,"value":15807},{"type":415,"tag":532,"props":27942,"children":27943},{"style":545},[27944],{"type":420,"value":26397},{"type":415,"tag":532,"props":27946,"children":27947},{"style":551},[27948],{"type":420,"value":563},{"type":415,"tag":532,"props":27950,"children":27951},{"class":534,"line":6142},[27952],{"type":415,"tag":532,"props":27953,"children":27954},{"style":5425},[27955],{"type":420,"value":27956},"# Create a new Pulumi project using the azure blob storage as the backend and the keyvault as the encryption provider \n",{"type":415,"tag":532,"props":27958,"children":27959},{"class":534,"line":6182},[27960,27964,27968,27972,27976,27980,27984,27988,27992,27996,28000,28004,28008,28012,28016,28020,28024,28028,28032,28036],{"type":415,"tag":532,"props":27961,"children":27962},{"style":545},[27963],{"type":420,"value":26409},{"type":415,"tag":532,"props":27965,"children":27966},{"style":551},[27967],{"type":420,"value":4216},{"type":415,"tag":532,"props":27969,"children":27970},{"style":545},[27971],{"type":420,"value":26418},{"type":415,"tag":532,"props":27973,"children":27974},{"style":551},[27975],{"type":420,"value":4216},{"type":415,"tag":532,"props":27977,"children":27978},{"style":545},[27979],{"type":420,"value":26427},{"type":415,"tag":532,"props":27981,"children":27982},{"style":551},[27983],{"type":420,"value":4216},{"type":415,"tag":532,"props":27985,"children":27986},{"style":545},[27987],{"type":420,"value":11385},{"type":415,"tag":532,"props":27989,"children":27990},{"style":551},[27991],{"type":420,"value":4216},{"type":415,"tag":532,"props":27993,"children":27994},{"style":545},[27995],{"type":420,"value":27034},{"type":415,"tag":532,"props":27997,"children":27998},{"style":551},[27999],{"type":420,"value":4115},{"type":415,"tag":532,"props":28001,"children":28002},{"style":545},[28003],{"type":420,"value":27043},{"type":415,"tag":532,"props":28005,"children":28006},{"style":551},[28007],{"type":420,"value":4216},{"type":415,"tag":532,"props":28009,"children":28010},{"style":545},[28011],{"type":420,"value":27052},{"type":415,"tag":532,"props":28013,"children":28014},{"style":551},[28015],{"type":420,"value":1134},{"type":415,"tag":532,"props":28017,"children":28018},{"style":551},[28019],{"type":420,"value":801},{"type":415,"tag":532,"props":28021,"children":28022},{"style":804},[28023],{"type":420,"value":27065},{"type":415,"tag":532,"props":28025,"children":28026},{"style":551},[28027],{"type":420,"value":4072},{"type":415,"tag":532,"props":28029,"children":28030},{"style":545},[28031],{"type":420,"value":26594},{"type":415,"tag":532,"props":28033,"children":28034},{"style":804},[28035],{"type":420,"value":27078},{"type":415,"tag":532,"props":28037,"children":28038},{"style":551},[28039],{"type":420,"value":4051},{"type":415,"tag":532,"props":28041,"children":28042},{"class":534,"line":6214},[28043],{"type":415,"tag":532,"props":28044,"children":28045},{"style":5425},[28046],{"type":420,"value":28047},"# Deploy the infrastructure\n",{"type":415,"tag":532,"props":28049,"children":28050},{"class":534,"line":6234},[28051,28055,28059],{"type":415,"tag":532,"props":28052,"children":28053},{"style":545},[28054],{"type":420,"value":26452},{"type":415,"tag":532,"props":28056,"children":28057},{"style":551},[28058],{"type":420,"value":4216},{"type":415,"tag":532,"props":28060,"children":28061},{"style":545},[28062],{"type":420,"value":26444},{"type":415,"tag":416,"props":28064,"children":28065},{},[28066],{"type":420,"value":28067},"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":415,"tag":416,"props":28069,"children":28070},{},[28071,28073,28079],{"type":420,"value":28072},"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":415,"tag":423,"props":28074,"children":28077},{"href":28075,"rel":28076},"https://www.pulumi.com/pricing/",[427],[28078],{"type":420,"value":4427},{"type":420,"value":28080}," 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":415,"tag":3470,"props":28082,"children":28083},{},[28084],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":28086},[28087,28091,28096,28101,28102],{"id":25568,"depth":566,"text":25571,"children":28088},[28089,28090],{"id":25574,"depth":583,"text":25577},{"id":25653,"depth":583,"text":25656},{"id":25697,"depth":566,"text":25700,"children":28092},[28093,28094,28095],{"id":25703,"depth":583,"text":25706},{"id":25765,"depth":583,"text":25768},{"id":26320,"depth":583,"text":26323},{"id":26497,"depth":566,"text":26500,"children":28097},[28098,28099,28100],{"id":26503,"depth":583,"text":26506},{"id":26519,"depth":583,"text":26522},{"id":26567,"depth":583,"text":26570},{"id":27085,"depth":566,"text":27088},{"id":10889,"depth":566,"text":10892},"content:1.posts:30.pulumi-azure-backend.md","1.posts/30.pulumi-azure-backend.md",{"_path":82,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":81,"description":28106,"lead":28107,"date":28108,"image":28109,"badge":28111,"tags":28113,"body":28114,"_type":3483,"_id":28475,"_source":3485,"_file":28476,"_extension":3487},"This week is mainly about learning Azure tooling.","Azure emulators, Use my current account Edge extension, Azure icons in Visio, and Azure Charts.","2021-10-04T00:00:00.000Z",{"src":28110},"/images/surface_1.jpg",{"label":28112},"Tips",[272,228,318,321,324],{"type":412,"children":28115,"toc":28466},[28116,28120,28126,28132,28137,28146,28160,28225,28238,28244,28257,28270,28279,28284,28293,28307,28324,28330,28335,28344,28374,28380,28385,28407,28423,28429,28443,28452,28457,28462],{"type":415,"tag":416,"props":28117,"children":28118},{},[28119],{"type":420,"value":28106},{"type":415,"tag":482,"props":28121,"children":28123},{"id":28122},"playing-with-new-emulators",[28124],{"type":420,"value":28125},"Playing with \"new\" emulators",{"type":415,"tag":3914,"props":28127,"children":28129},{"id":28128},"azure-signalr-local-emulator",[28130],{"type":420,"value":28131},"Azure SignalR Local Emulator",{"type":415,"tag":416,"props":28133,"children":28134},{},[28135],{"type":420,"value":28136},"This week I was playing with SignalR Service (using the serverless service mode) and I needed to debug my Azure Functions locally. While I was implementing the infrastructure as code to deploy the Azure SignalR Service resource to Azure, I realized that I did not need to do that to test my code as there was a local emulator for SignalR Service. This emulator is currently in preview but looks promising.",{"type":415,"tag":416,"props":28138,"children":28139},{},[28140],{"type":415,"tag":3882,"props":28141,"children":28145},{"alt":28142,"className":28143,"src":28144},"Azure SignalR Service emulator website.",[3886,3887],"/posts/images/w392021tips_nuget_1.png",[],{"type":415,"tag":416,"props":28147,"children":28148},{},[28149,28151,28158],{"type":420,"value":28150},"It is available as a ",{"type":415,"tag":423,"props":28152,"children":28155},{"href":28153,"rel":28154},"https://www.nuget.org/packages/Microsoft.Azure.SignalR.Emulator",[427],[28156],{"type":420,"value":28157},"dotnet tool",{"type":420,"value":28159}," here so you can just install it by using the following command:",{"type":415,"tag":523,"props":28161,"children":28163},{"className":4059,"code":28162,"language":248,"meta":401,"style":401},"dotnet tool install -g Microsoft.Azure.SignalR.Emulator --version 1.0.0-preview1-10809\n",[28164],{"type":415,"tag":468,"props":28165,"children":28166},{"__ignoreMap":401},[28167],{"type":415,"tag":532,"props":28168,"children":28169},{"class":534,"line":535},[28170,28175,28179,28184,28188,28193,28198,28202,28207,28211,28216,28220],{"type":415,"tag":532,"props":28171,"children":28172},{"style":545},[28173],{"type":420,"value":28174},"dotnet tool install ",{"type":415,"tag":532,"props":28176,"children":28177},{"style":551},[28178],{"type":420,"value":4216},{"type":415,"tag":532,"props":28180,"children":28181},{"style":545},[28182],{"type":420,"value":28183},"g Microsoft.Azure.SignalR.Emulator ",{"type":415,"tag":532,"props":28185,"children":28186},{"style":551},[28187],{"type":420,"value":4115},{"type":415,"tag":532,"props":28189,"children":28190},{"style":545},[28191],{"type":420,"value":28192},"version ",{"type":415,"tag":532,"props":28194,"children":28195},{"style":539},[28196],{"type":420,"value":28197},"1.0",{"type":415,"tag":532,"props":28199,"children":28200},{"style":545},[28201],{"type":420,"value":432},{"type":415,"tag":532,"props":28203,"children":28204},{"style":539},[28205],{"type":420,"value":28206},"0",{"type":415,"tag":532,"props":28208,"children":28209},{"style":551},[28210],{"type":420,"value":4216},{"type":415,"tag":532,"props":28212,"children":28213},{"style":545},[28214],{"type":420,"value":28215},"preview1",{"type":415,"tag":532,"props":28217,"children":28218},{"style":551},[28219],{"type":420,"value":4216},{"type":415,"tag":532,"props":28221,"children":28222},{"style":539},[28223],{"type":420,"value":28224},"10809\n",{"type":415,"tag":416,"props":28226,"children":28227},{},[28228,28230,28236],{"type":420,"value":28229},"Have a look at the ",{"type":415,"tag":423,"props":28231,"children":28234},{"href":28232,"rel":28233},"https://github.com/Azure/azure-signalr/blob/dev/docs/emulator.md",[427],[28235],{"type":420,"value":499},{"type":420,"value":28237}," if you want to learn more about it.",{"type":415,"tag":3914,"props":28239,"children":28241},{"id":28240},"azurite",[28242],{"type":420,"value":28243},"Azurite",{"type":415,"tag":416,"props":28245,"children":28246},{},[28247,28249,28255],{"type":420,"value":28248},"You probably have already heard about ",{"type":415,"tag":423,"props":28250,"children":28253},{"href":28251,"rel":28252},"https://github.com/Azure/Azurite",[427],[28254],{"type":420,"value":28243},{"type":420,"value":28256}," the cross-platform emulator for local Azure Storage development. It is really useful when you are using queues, tables, or blobs from Azure Storage in your project and you want to debug your code with emulated versions of these services running locally. If you are developing Azure Functions you are certainly using an emulator for the storage but maybe not be aware of it.",{"type":415,"tag":416,"props":28258,"children":28259},{},[28260,28262,28268],{"type":420,"value":28261},"Azurite is the successor of Azure Storage Emulator but as the ",{"type":415,"tag":423,"props":28263,"children":28266},{"href":28264,"rel":28265},"https://docs.microsoft.com/en-us/azure/storage/common/storage-use-emulator",[427],[28267],{"type":420,"value":499},{"type":420,"value":28269}," says:",{"type":415,"tag":416,"props":28271,"children":28272},{},[28273],{"type":415,"tag":3882,"props":28274,"children":28278},{"alt":28275,"className":28276,"src":28277},"Documentation about Azure Storage emulator deprecation.",[3886,3887],"/posts/images/w392021tips_azurite_1.png",[],{"type":415,"tag":416,"props":28280,"children":28281},{},[28282],{"type":420,"value":28283},"It's funny because I try to keep myself up-to-date on this kind of news but I did not know at all Azure Storage Emulator had been already deprecated in favor of Azurite for quite some time. Yet, as you can see in the following screenshot when you create a Function App with the \"storage emulator\" option selected you can see the Azurite emulator in your connected services:",{"type":415,"tag":416,"props":28285,"children":28286},{},[28287],{"type":415,"tag":3882,"props":28288,"children":28292},{"alt":28289,"className":28290,"src":28291},"Service dependencies in Visual Studio.",[3886,3887],"/posts/images/w392021tips_vs_1.png",[],{"type":415,"tag":416,"props":28294,"children":28295},{},[28296,28298,28305],{"type":420,"value":28297},"You can check this ",{"type":415,"tag":423,"props":28299,"children":28302},{"href":28300,"rel":28301},"https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio",[427],[28303],{"type":420,"value":28304},"tutorial",{"type":420,"value":28306}," to see how to install and use Azurite.",{"type":415,"tag":434,"props":28308,"children":28309},{"icon":1382},[28310],{"type":415,"tag":416,"props":28311,"children":28312},{},[28313,28315,28322],{"type":420,"value":28314},"Be aware that Azurite is also available in a ",{"type":415,"tag":423,"props":28316,"children":28319},{"href":28317,"rel":28318},"https://marketplace.visualstudio.com/items?itemName=Azurite.azurite",[427],[28320],{"type":420,"value":28321},"vscode extension",{"type":420,"value":28323}," which allows you to start and stop storage services individually. If you don't want to bother with the command line, using Azurite from vscode is a good option.",{"type":415,"tag":482,"props":28325,"children":28327},{"id":28326},"using-your-edge-profile-and-skipping-the-account-prompt-screen-when-signing-into-microsoft-sites",[28328],{"type":420,"value":28329},"Using your Edge profile and skipping the account prompt screen when signing into Microsoft sites.",{"type":415,"tag":416,"props":28331,"children":28332},{},[28333],{"type":420,"value":28334},"As I have different Azure Active Directory accounts (for my company, for some of the clients I am working for, for testing purposes) it can be quite challenging to manage so I am using different Microsoft Edge profiles to keep things separated and to avoid signing out when switching from one account to another. However, even with different profiles, when you access a Microsoft site (Azure DevOps for instance) the browser prompts you to choose the account you want to use.",{"type":415,"tag":416,"props":28336,"children":28337},{},[28338],{"type":415,"tag":3882,"props":28339,"children":28343},{"alt":28340,"className":28341,"src":28342},"Use my current account extension page.",[3886,3887],"/posts/images/w392021tips_extension_1.png",[],{"type":415,"tag":416,"props":28345,"children":28346},{},[28347,28349,28355,28357,28363,28365,28372],{"type":420,"value":28348},"Claire Novotny (currently executive director at the .NET Foundation and working in the .NET team at Microsoft) developed a Microsoft Edge extension ",{"type":415,"tag":468,"props":28350,"children":28352},{"className":28351},[],[28353],{"type":420,"value":28354},"Use my current account",{"type":420,"value":28356}," that solves this problem. This plugin is available ",{"type":415,"tag":423,"props":28358,"children":28361},{"href":28359,"rel":28360},"https://microsoftedge.microsoft.com/addons/detail/use-my-current-account/hbfacnnpimgddoojjaonnnbeljegicfl",[427],[28362],{"type":420,"value":4427},{"type":420,"value":28364}," to download and you can check the source code on ",{"type":415,"tag":423,"props":28366,"children":28369},{"href":28367,"rel":28368},"https://github.com/novotnyllc/UseMyCurrentAccount",[427],[28370],{"type":420,"value":28371},"this GitHub repository",{"type":420,"value":28373},". It is a simple but very useful extension that I strongly encourage you to download if you use multiple Azure AD accounts.",{"type":415,"tag":482,"props":28375,"children":28377},{"id":28376},"using-up-to-date-azure-icons-in-visio",[28378],{"type":420,"value":28379},"Using up-to-date Azure icons in Visio.",{"type":415,"tag":416,"props":28381,"children":28382},{},[28383],{"type":420,"value":28384},"I use Visio from time to time to create nice-looking Azure architecture diagrams (at least I try 😀). To do that I use Visio packages about Azure some people provide on GitHub and that contain all the Azure resources icons I need.",{"type":415,"tag":416,"props":28386,"children":28387},{},[28388,28390,28397,28399,28405],{"type":420,"value":28389},"Azure icons often change, and there are always new resources added so always downloading the latest version of these Visio packages is a bit cumbersome. Fortunately, my friend Xavier Mignot shared on his ",{"type":415,"tag":423,"props":28391,"children":28394},{"href":28392,"rel":28393},"https://blog.xmi.fr/posts/visio-tips-git-clone/",[427],[28395],{"type":420,"value":28396},"blog",{"type":420,"value":28398}," a nice and simple solution for that problem: cloning the Visio packages git repositories under the ",{"type":415,"tag":468,"props":28400,"children":28402},{"className":28401},[],[28403],{"type":420,"value":28404},"My Shapes",{"type":420,"value":28406}," folder and regularly pulling new changes to have always up-to-date Azure icons.",{"type":415,"tag":434,"props":28408,"children":28409},{"icon":1382},[28410],{"type":415,"tag":416,"props":28411,"children":28412},{},[28413,28415,28421],{"type":420,"value":28414},"If you want more tips about Visio, check the other articles of Xavier on his ",{"type":415,"tag":423,"props":28416,"children":28419},{"href":28417,"rel":28418},"https://blog.xmi.fr/",[427],[28420],{"type":420,"value":28396},{"type":420,"value":28422},", there are also articles about Azure, IoT, .NET...",{"type":415,"tag":482,"props":28424,"children":28426},{"id":28425},"explore-azure-services-easily-with-azure-charts",[28427],{"type":420,"value":28428},"Explore Azure services easily with Azure Charts",{"type":415,"tag":416,"props":28430,"children":28431},{},[28432,28434,28441],{"type":420,"value":28433},"Microsoft's documentation is great but it is sometimes not easy to have a good overview of the services Azure provides. Finding basic things like the SLA of a service, the regions where it is available, and the learning resources to getting started on it can often take time. Unless you know about Alexey Polkovnikov's website ",{"type":415,"tag":423,"props":28435,"children":28438},{"href":28436,"rel":28437},"https://azurecharts.com/",[427],[28439],{"type":420,"value":28440},"Azure Charts",{"type":420,"value":28442}," which gives you all that and much more in a visual way.",{"type":415,"tag":416,"props":28444,"children":28445},{},[28446],{"type":415,"tag":3882,"props":28447,"children":28451},{"alt":28448,"className":28449,"src":28450},"Azure Charts website.",[3886,3887],"/posts/images/w392021tips_charts_1.png",[],{"type":415,"tag":416,"props":28453,"children":28454},{},[28455],{"type":420,"value":28456},"It's not a website I discovered this week but I showed it to a colleague this week and I thought (as each time I go on this website) that I should use it more often as it is a very useful tool.",{"type":415,"tag":416,"props":28458,"children":28459},{},[28460],{"type":420,"value":28461},"And that's it for this week, happy learning!",{"type":415,"tag":3470,"props":28463,"children":28464},{},[28465],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":28467},[28468,28472,28473,28474],{"id":28122,"depth":566,"text":28125,"children":28469},[28470,28471],{"id":28128,"depth":583,"text":28131},{"id":28240,"depth":583,"text":28243},{"id":28326,"depth":566,"text":28329},{"id":28376,"depth":566,"text":28379},{"id":28425,"depth":566,"text":28428},"content:1.posts:25.w39-2021-tips-learned-this-week.md","1.posts/25.w39-2021-tips-learned-this-week.md",{"_path":79,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":78,"description":28478,"lead":28479,"date":28480,"image":28481,"badge":28483,"tags":28484,"body":28485,"_type":3483,"_id":30473,"_source":3485,"_file":30474,"_extension":3487},"Have you ever felt a bit overwhelmed by the configuration in a project, not knowing where to look for the settings between the command line parameters, the environment variables, the configuration files in code, the configuration in Azure, ... ? When developing an ASP.NET Core application there are many places where you can put your configuration which makes it difficult to know where you should put it. Even if the official documentation about configuration in ASP.NET Core is very complete and well written, it only describes what you can use and how to use it, not what you should use and when. In this article,     I will try to answer these questions and give you my opinion about how we should use configuration providers in ASP.NET Core.","How should you use configuration providers in ASP.NET Core?","2021-09-27T00:00:00.000Z",{"src":28482},"/images/tokyo.jpg",{"label":408},[236,262,260,228],{"type":412,"children":28486,"toc":30460},[28487,28501,28507,28512,28517,28526,28532,28537,28546,28559,29223,29250,29259,29264,29273,29299,29305,29310,29322,29348,29372,29378,29383,29392,29397,29403,29408,29425,29468,29477,29483,29488,29525,29534,29539,29544,29844,29849,29855,29869,29878,29883,30255,30261,30271,30285,30333,30342,30373,30379,30384,30389,30451,30456],{"type":415,"tag":416,"props":28488,"children":28489},{},[28490,28492,28499],{"type":420,"value":28491},"Have you ever felt a bit overwhelmed by the configuration in a project, not knowing where to look for the settings between the command line parameters, the environment variables, the configuration files in code, the configuration in Azure, ... ? When developing an ASP.NET Core application there are many places where you can put your configuration which makes it difficult to know where you should put it. Even if the ",{"type":415,"tag":423,"props":28493,"children":28496},{"href":28494,"rel":28495},"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/",[427],[28497],{"type":420,"value":28498},"official documentation",{"type":420,"value":28500}," about configuration in ASP.NET Core is very complete and well written, it only describes what you can use and how to use it, not what you should use and when. In this article,     I will try to answer these questions and give you my opinion about how we should use configuration providers in ASP.NET Core.",{"type":415,"tag":482,"props":28502,"children":28504},{"id":28503},"a-quick-reminder-about-configuration",[28505],{"type":420,"value":28506},"A quick reminder about configuration",{"type":415,"tag":416,"props":28508,"children":28509},{},[28510],{"type":420,"value":28511},"Configuration is what allows you to quickly change how an application behaves by modifying a setting instead of rewriting the code. Configuration/settings are sometimes linked to the environment where your application runs but not always. Generally, when something is likely to change, a good practice is to define a setting for it in the configuration instead of hard coding it in the source code.",{"type":415,"tag":416,"props":28513,"children":28514},{},[28515],{"type":420,"value":28516},"Configuration can take many forms and ASP.NET Core has this powerful concept of configurations providers that read configuration data from different sources. But in the end, configuration is just a collection of key-value pairs.",{"type":415,"tag":416,"props":28518,"children":28519},{},[28520],{"type":415,"tag":3882,"props":28521,"children":28525},{"alt":28522,"className":28523,"src":28524},"Values in Startup.cs configuration in debug.",[3886,3887],"/posts/images/lostinconfiguration_providers_2.png",[],{"type":415,"tag":482,"props":28527,"children":28529},{"id":28528},"why-do-i-have-so-many-configuration-providers-by-default",[28530],{"type":420,"value":28531},"Why do I have so many configuration providers by default?",{"type":415,"tag":416,"props":28533,"children":28534},{},[28535],{"type":420,"value":28536},"When you create a new ASP.NET Core project from a template and run it, you have probably noticed that your configuration is not empty and that by default, multiple configuration providers are already registered.",{"type":415,"tag":416,"props":28538,"children":28539},{},[28540],{"type":415,"tag":3882,"props":28541,"children":28545},{"alt":28542,"className":28543,"src":28544},"Configuration providers in Startup.cs configuration in debug.",[3886,3887],"/posts/images/lostinconfiguration_providers_1.pngpng",[],{"type":415,"tag":416,"props":28547,"children":28548},{},[28549,28551,28557],{"type":420,"value":28550},"Do not worry there is no magic here, it just comes from the call ",{"type":415,"tag":468,"props":28552,"children":28554},{"className":28553},[],[28555],{"type":420,"value":28556},"Host.CreateDefaultBuilder(args)",{"type":420,"value":28558}," in your Program.cs.\nHere is an extract of what does this method:",{"type":415,"tag":523,"props":28560,"children":28562},{"className":525,"code":28561,"language":326,"meta":401,"style":401},"builder.ConfigureAppConfiguration((hostingContext, config) =>\n{\n    IHostEnvironment env = hostingContext.HostingEnvironment;\n    bool reloadOnChange = GetReloadConfigOnChangeValue(hostingContext);\n    config.AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: reloadOnChange)\n          .AddJsonFile($\"appsettings.{env.EnvironmentName}.json\", optional: true, reloadOnChange:reloadOnChange);\n    if (env.IsDevelopment() && env.ApplicationName is { Length: > 0 })\n    {\n        var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));\n        if (appAssembly is not null)\n        {\n            config.AddUserSecrets(appAssembly, optional: true, reloadOnChange: reloadOnChange);\n        }\n    }\n    config.AddEnvironmentVariables();\n    if (args is { Length: > 0 })\n    {\n        config.AddCommandLine(args);\n    }\n})\n",[28563],{"type":415,"tag":468,"props":28564,"children":28565},{"__ignoreMap":401},[28566,28608,28615,28650,28684,28755,28848,28928,28935,28995,29026,29033,29095,29102,29109,29129,29173,29180,29209,29216],{"type":415,"tag":532,"props":28567,"children":28568},{"class":534,"line":535},[28569,28573,28577,28582,28587,28592,28596,28600,28604],{"type":415,"tag":532,"props":28570,"children":28571},{"style":545},[28572],{"type":420,"value":683},{"type":415,"tag":532,"props":28574,"children":28575},{"style":551},[28576],{"type":420,"value":432},{"type":415,"tag":532,"props":28578,"children":28579},{"style":656},[28580],{"type":420,"value":28581},"ConfigureAppConfiguration",{"type":415,"tag":532,"props":28583,"children":28584},{"style":551},[28585],{"type":420,"value":28586},"((",{"type":415,"tag":532,"props":28588,"children":28589},{"style":631},[28590],{"type":420,"value":28591},"hostingContext",{"type":415,"tag":532,"props":28593,"children":28594},{"style":551},[28595],{"type":420,"value":1099},{"type":415,"tag":532,"props":28597,"children":28598},{"style":631},[28599],{"type":420,"value":7206},{"type":415,"tag":532,"props":28601,"children":28602},{"style":551},[28603],{"type":420,"value":1349},{"type":415,"tag":532,"props":28605,"children":28606},{"style":551},[28607],{"type":420,"value":755},{"type":415,"tag":532,"props":28609,"children":28610},{"class":534,"line":566},[28611],{"type":415,"tag":532,"props":28612,"children":28613},{"style":551},[28614],{"type":420,"value":764},{"type":415,"tag":532,"props":28616,"children":28617},{"class":534,"line":583},[28618,28623,28628,28632,28637,28641,28646],{"type":415,"tag":532,"props":28619,"children":28620},{"style":631},[28621],{"type":420,"value":28622},"    IHostEnvironment",{"type":415,"tag":532,"props":28624,"children":28625},{"style":631},[28626],{"type":420,"value":28627}," env",{"type":415,"tag":532,"props":28629,"children":28630},{"style":551},[28631],{"type":420,"value":644},{"type":415,"tag":532,"props":28633,"children":28634},{"style":545},[28635],{"type":420,"value":28636}," hostingContext",{"type":415,"tag":532,"props":28638,"children":28639},{"style":551},[28640],{"type":420,"value":432},{"type":415,"tag":532,"props":28642,"children":28643},{"style":545},[28644],{"type":420,"value":28645},"HostingEnvironment",{"type":415,"tag":532,"props":28647,"children":28648},{"style":551},[28649],{"type":420,"value":563},{"type":415,"tag":532,"props":28651,"children":28652},{"class":534,"line":617},[28653,28658,28663,28667,28672,28676,28680],{"type":415,"tag":532,"props":28654,"children":28655},{"style":551},[28656],{"type":420,"value":28657},"    bool",{"type":415,"tag":532,"props":28659,"children":28660},{"style":631},[28661],{"type":420,"value":28662}," reloadOnChange",{"type":415,"tag":532,"props":28664,"children":28665},{"style":551},[28666],{"type":420,"value":644},{"type":415,"tag":532,"props":28668,"children":28669},{"style":656},[28670],{"type":420,"value":28671}," GetReloadConfigOnChangeValue",{"type":415,"tag":532,"props":28673,"children":28674},{"style":551},[28675],{"type":420,"value":664},{"type":415,"tag":532,"props":28677,"children":28678},{"style":545},[28679],{"type":420,"value":28591},{"type":415,"tag":532,"props":28681,"children":28682},{"style":551},[28683],{"type":420,"value":674},{"type":415,"tag":532,"props":28685,"children":28686},{"class":534,"line":627},[28687,28692,28696,28701,28705,28709,28714,28718,28722,28727,28731,28735,28739,28743,28747,28751],{"type":415,"tag":532,"props":28688,"children":28689},{"style":545},[28690],{"type":420,"value":28691},"    config",{"type":415,"tag":532,"props":28693,"children":28694},{"style":551},[28695],{"type":420,"value":432},{"type":415,"tag":532,"props":28697,"children":28698},{"style":656},[28699],{"type":420,"value":28700},"AddJsonFile",{"type":415,"tag":532,"props":28702,"children":28703},{"style":551},[28704],{"type":420,"value":664},{"type":415,"tag":532,"props":28706,"children":28707},{"style":551},[28708],{"type":420,"value":801},{"type":415,"tag":532,"props":28710,"children":28711},{"style":804},[28712],{"type":420,"value":28713},"appsettings.json",{"type":415,"tag":532,"props":28715,"children":28716},{"style":551},[28717],{"type":420,"value":801},{"type":415,"tag":532,"props":28719,"children":28720},{"style":551},[28721],{"type":420,"value":1099},{"type":415,"tag":532,"props":28723,"children":28724},{"style":631},[28725],{"type":420,"value":28726}," optional",{"type":415,"tag":532,"props":28728,"children":28729},{"style":551},[28730],{"type":420,"value":1290},{"type":415,"tag":532,"props":28732,"children":28733},{"style":1938},[28734],{"type":420,"value":1941},{"type":415,"tag":532,"props":28736,"children":28737},{"style":551},[28738],{"type":420,"value":1099},{"type":415,"tag":532,"props":28740,"children":28741},{"style":631},[28742],{"type":420,"value":28662},{"type":415,"tag":532,"props":28744,"children":28745},{"style":551},[28746],{"type":420,"value":1290},{"type":415,"tag":532,"props":28748,"children":28749},{"style":545},[28750],{"type":420,"value":28662},{"type":415,"tag":532,"props":28752,"children":28753},{"style":551},[28754],{"type":420,"value":1113},{"type":415,"tag":532,"props":28756,"children":28757},{"class":534,"line":677},[28758,28763,28767,28771,28775,28780,28784,28789,28793,28798,28802,28807,28811,28815,28819,28823,28827,28831,28835,28839,28844],{"type":415,"tag":532,"props":28759,"children":28760},{"style":551},[28761],{"type":420,"value":28762},"          .",{"type":415,"tag":532,"props":28764,"children":28765},{"style":656},[28766],{"type":420,"value":28700},{"type":415,"tag":532,"props":28768,"children":28769},{"style":551},[28770],{"type":420,"value":664},{"type":415,"tag":532,"props":28772,"children":28773},{"style":551},[28774],{"type":420,"value":8738},{"type":415,"tag":532,"props":28776,"children":28777},{"style":804},[28778],{"type":420,"value":28779},"appsettings.",{"type":415,"tag":532,"props":28781,"children":28782},{"style":551},[28783],{"type":420,"value":8748},{"type":415,"tag":532,"props":28785,"children":28786},{"style":545},[28787],{"type":420,"value":28788},"env",{"type":415,"tag":532,"props":28790,"children":28791},{"style":551},[28792],{"type":420,"value":432},{"type":415,"tag":532,"props":28794,"children":28795},{"style":545},[28796],{"type":420,"value":28797},"EnvironmentName",{"type":415,"tag":532,"props":28799,"children":28800},{"style":551},[28801],{"type":420,"value":4864},{"type":415,"tag":532,"props":28803,"children":28804},{"style":804},[28805],{"type":420,"value":28806},".json",{"type":415,"tag":532,"props":28808,"children":28809},{"style":551},[28810],{"type":420,"value":801},{"type":415,"tag":532,"props":28812,"children":28813},{"style":551},[28814],{"type":420,"value":1099},{"type":415,"tag":532,"props":28816,"children":28817},{"style":631},[28818],{"type":420,"value":28726},{"type":415,"tag":532,"props":28820,"children":28821},{"style":551},[28822],{"type":420,"value":1290},{"type":415,"tag":532,"props":28824,"children":28825},{"style":1938},[28826],{"type":420,"value":1941},{"type":415,"tag":532,"props":28828,"children":28829},{"style":551},[28830],{"type":420,"value":1099},{"type":415,"tag":532,"props":28832,"children":28833},{"style":631},[28834],{"type":420,"value":28662},{"type":415,"tag":532,"props":28836,"children":28837},{"style":551},[28838],{"type":420,"value":1290},{"type":415,"tag":532,"props":28840,"children":28841},{"style":545},[28842],{"type":420,"value":28843},"reloadOnChange",{"type":415,"tag":532,"props":28845,"children":28846},{"style":551},[28847],{"type":420,"value":674},{"type":415,"tag":532,"props":28849,"children":28850},{"class":534,"line":719},[28851,28856,28860,28864,28868,28873,28877,28882,28886,28890,28895,28900,28904,28909,28913,28918,28923],{"type":415,"tag":532,"props":28852,"children":28853},{"style":1241},[28854],{"type":420,"value":28855},"    if",{"type":415,"tag":532,"props":28857,"children":28858},{"style":551},[28859],{"type":420,"value":1249},{"type":415,"tag":532,"props":28861,"children":28862},{"style":545},[28863],{"type":420,"value":28788},{"type":415,"tag":532,"props":28865,"children":28866},{"style":551},[28867],{"type":420,"value":432},{"type":415,"tag":532,"props":28869,"children":28870},{"style":656},[28871],{"type":420,"value":28872},"IsDevelopment",{"type":415,"tag":532,"props":28874,"children":28875},{"style":551},[28876],{"type":420,"value":12966},{"type":415,"tag":532,"props":28878,"children":28879},{"style":551},[28880],{"type":420,"value":28881}," &&",{"type":415,"tag":532,"props":28883,"children":28884},{"style":545},[28885],{"type":420,"value":28627},{"type":415,"tag":532,"props":28887,"children":28888},{"style":551},[28889],{"type":420,"value":432},{"type":415,"tag":532,"props":28891,"children":28892},{"style":545},[28893],{"type":420,"value":28894},"ApplicationName ",{"type":415,"tag":532,"props":28896,"children":28897},{"style":551},[28898],{"type":420,"value":28899},"is",{"type":415,"tag":532,"props":28901,"children":28902},{"style":551},[28903],{"type":420,"value":3347},{"type":415,"tag":532,"props":28905,"children":28906},{"style":545},[28907],{"type":420,"value":28908}," Length",{"type":415,"tag":532,"props":28910,"children":28911},{"style":551},[28912],{"type":420,"value":1290},{"type":415,"tag":532,"props":28914,"children":28915},{"style":551},[28916],{"type":420,"value":28917}," >",{"type":415,"tag":532,"props":28919,"children":28920},{"style":539},[28921],{"type":420,"value":28922}," 0",{"type":415,"tag":532,"props":28924,"children":28925},{"style":551},[28926],{"type":420,"value":28927}," })\n",{"type":415,"tag":532,"props":28929,"children":28930},{"class":534,"line":758},[28931],{"type":415,"tag":532,"props":28932,"children":28933},{"style":551},[28934],{"type":420,"value":1121},{"type":415,"tag":532,"props":28936,"children":28937},{"class":534,"line":767},[28938,28942,28947,28951,28956,28960,28965,28969,28974,28978,28982,28986,28991],{"type":415,"tag":532,"props":28939,"children":28940},{"style":631},[28941],{"type":420,"value":3210},{"type":415,"tag":532,"props":28943,"children":28944},{"style":631},[28945],{"type":420,"value":28946}," appAssembly",{"type":415,"tag":532,"props":28948,"children":28949},{"style":551},[28950],{"type":420,"value":644},{"type":415,"tag":532,"props":28952,"children":28953},{"style":545},[28954],{"type":420,"value":28955}," Assembly",{"type":415,"tag":532,"props":28957,"children":28958},{"style":551},[28959],{"type":420,"value":432},{"type":415,"tag":532,"props":28961,"children":28962},{"style":656},[28963],{"type":420,"value":28964},"Load",{"type":415,"tag":532,"props":28966,"children":28967},{"style":551},[28968],{"type":420,"value":787},{"type":415,"tag":532,"props":28970,"children":28971},{"style":631},[28972],{"type":420,"value":28973}," AssemblyName",{"type":415,"tag":532,"props":28975,"children":28976},{"style":551},[28977],{"type":420,"value":664},{"type":415,"tag":532,"props":28979,"children":28980},{"style":545},[28981],{"type":420,"value":28788},{"type":415,"tag":532,"props":28983,"children":28984},{"style":551},[28985],{"type":420,"value":432},{"type":415,"tag":532,"props":28987,"children":28988},{"style":545},[28989],{"type":420,"value":28990},"ApplicationName",{"type":415,"tag":532,"props":28992,"children":28993},{"style":551},[28994],{"type":420,"value":816},{"type":415,"tag":532,"props":28996,"children":28997},{"class":534,"line":819},[28998,29003,29007,29012,29016,29021],{"type":415,"tag":532,"props":28999,"children":29000},{"style":1241},[29001],{"type":420,"value":29002},"        if",{"type":415,"tag":532,"props":29004,"children":29005},{"style":551},[29006],{"type":420,"value":1249},{"type":415,"tag":532,"props":29008,"children":29009},{"style":545},[29010],{"type":420,"value":29011},"appAssembly ",{"type":415,"tag":532,"props":29013,"children":29014},{"style":551},[29015],{"type":420,"value":28899},{"type":415,"tag":532,"props":29017,"children":29018},{"style":551},[29019],{"type":420,"value":29020}," not",{"type":415,"tag":532,"props":29022,"children":29023},{"style":551},[29024],{"type":420,"value":29025}," null)\n",{"type":415,"tag":532,"props":29027,"children":29028},{"class":534,"line":850},[29029],{"type":415,"tag":532,"props":29030,"children":29031},{"style":551},[29032],{"type":420,"value":1308},{"type":415,"tag":532,"props":29034,"children":29035},{"class":534,"line":859},[29036,29041,29045,29050,29054,29059,29063,29067,29071,29075,29079,29083,29087,29091],{"type":415,"tag":532,"props":29037,"children":29038},{"style":545},[29039],{"type":420,"value":29040},"            config",{"type":415,"tag":532,"props":29042,"children":29043},{"style":551},[29044],{"type":420,"value":432},{"type":415,"tag":532,"props":29046,"children":29047},{"style":656},[29048],{"type":420,"value":29049},"AddUserSecrets",{"type":415,"tag":532,"props":29051,"children":29052},{"style":551},[29053],{"type":420,"value":664},{"type":415,"tag":532,"props":29055,"children":29056},{"style":545},[29057],{"type":420,"value":29058},"appAssembly",{"type":415,"tag":532,"props":29060,"children":29061},{"style":551},[29062],{"type":420,"value":1099},{"type":415,"tag":532,"props":29064,"children":29065},{"style":631},[29066],{"type":420,"value":28726},{"type":415,"tag":532,"props":29068,"children":29069},{"style":551},[29070],{"type":420,"value":1290},{"type":415,"tag":532,"props":29072,"children":29073},{"style":1938},[29074],{"type":420,"value":1941},{"type":415,"tag":532,"props":29076,"children":29077},{"style":551},[29078],{"type":420,"value":1099},{"type":415,"tag":532,"props":29080,"children":29081},{"style":631},[29082],{"type":420,"value":28662},{"type":415,"tag":532,"props":29084,"children":29085},{"style":551},[29086],{"type":420,"value":1290},{"type":415,"tag":532,"props":29088,"children":29089},{"style":545},[29090],{"type":420,"value":28662},{"type":415,"tag":532,"props":29092,"children":29093},{"style":551},[29094],{"type":420,"value":674},{"type":415,"tag":532,"props":29096,"children":29097},{"class":534,"line":867},[29098],{"type":415,"tag":532,"props":29099,"children":29100},{"style":551},[29101],{"type":420,"value":1362},{"type":415,"tag":532,"props":29103,"children":29104},{"class":534,"line":902},[29105],{"type":415,"tag":532,"props":29106,"children":29107},{"style":551},[29108],{"type":420,"value":1170},{"type":415,"tag":532,"props":29110,"children":29111},{"class":534,"line":1302},[29112,29116,29120,29125],{"type":415,"tag":532,"props":29113,"children":29114},{"style":545},[29115],{"type":420,"value":28691},{"type":415,"tag":532,"props":29117,"children":29118},{"style":551},[29119],{"type":420,"value":432},{"type":415,"tag":532,"props":29121,"children":29122},{"style":656},[29123],{"type":420,"value":29124},"AddEnvironmentVariables",{"type":415,"tag":532,"props":29126,"children":29127},{"style":551},[29128],{"type":420,"value":899},{"type":415,"tag":532,"props":29130,"children":29131},{"class":534,"line":1311},[29132,29136,29140,29145,29149,29153,29157,29161,29165,29169],{"type":415,"tag":532,"props":29133,"children":29134},{"style":1241},[29135],{"type":420,"value":28855},{"type":415,"tag":532,"props":29137,"children":29138},{"style":551},[29139],{"type":420,"value":1249},{"type":415,"tag":532,"props":29141,"children":29142},{"style":545},[29143],{"type":420,"value":29144},"args ",{"type":415,"tag":532,"props":29146,"children":29147},{"style":551},[29148],{"type":420,"value":28899},{"type":415,"tag":532,"props":29150,"children":29151},{"style":551},[29152],{"type":420,"value":3347},{"type":415,"tag":532,"props":29154,"children":29155},{"style":545},[29156],{"type":420,"value":28908},{"type":415,"tag":532,"props":29158,"children":29159},{"style":551},[29160],{"type":420,"value":1290},{"type":415,"tag":532,"props":29162,"children":29163},{"style":551},[29164],{"type":420,"value":28917},{"type":415,"tag":532,"props":29166,"children":29167},{"style":539},[29168],{"type":420,"value":28922},{"type":415,"tag":532,"props":29170,"children":29171},{"style":551},[29172],{"type":420,"value":28927},{"type":415,"tag":532,"props":29174,"children":29175},{"class":534,"line":1356},[29176],{"type":415,"tag":532,"props":29177,"children":29178},{"style":551},[29179],{"type":420,"value":1121},{"type":415,"tag":532,"props":29181,"children":29182},{"class":534,"line":1365},[29183,29188,29192,29197,29201,29205],{"type":415,"tag":532,"props":29184,"children":29185},{"style":545},[29186],{"type":420,"value":29187},"        config",{"type":415,"tag":532,"props":29189,"children":29190},{"style":551},[29191],{"type":420,"value":432},{"type":415,"tag":532,"props":29193,"children":29194},{"style":656},[29195],{"type":420,"value":29196},"AddCommandLine",{"type":415,"tag":532,"props":29198,"children":29199},{"style":551},[29200],{"type":420,"value":664},{"type":415,"tag":532,"props":29202,"children":29203},{"style":545},[29204],{"type":420,"value":669},{"type":415,"tag":532,"props":29206,"children":29207},{"style":551},[29208],{"type":420,"value":674},{"type":415,"tag":532,"props":29210,"children":29211},{"class":534,"line":1373},[29212],{"type":415,"tag":532,"props":29213,"children":29214},{"style":551},[29215],{"type":420,"value":1170},{"type":415,"tag":532,"props":29217,"children":29218},{"class":534,"line":3825},[29219],{"type":415,"tag":532,"props":29220,"children":29221},{"style":551},[29222],{"type":420,"value":3375},{"type":415,"tag":416,"props":29224,"children":29225},{},[29226,29228,29234,29236,29241,29243,29248],{"type":420,"value":29227},"As you can see, by default this ",{"type":415,"tag":468,"props":29229,"children":29231},{"className":29230},[],[29232],{"type":420,"value":29233},"CreateDefaultBuilder",{"type":420,"value":29235}," method loads configuration data using different configuration providers. You can load additional configuration by calling the ",{"type":415,"tag":468,"props":29237,"children":29239},{"className":29238},[],[29240],{"type":420,"value":28581},{"type":420,"value":29242}," in the ",{"type":415,"tag":468,"props":29244,"children":29246},{"className":29245},[],[29247],{"type":420,"value":20062},{"type":420,"value":29249}," like in the example which uses Azure Key Vault configuration provider.",{"type":415,"tag":416,"props":29251,"children":29252},{},[29253],{"type":415,"tag":3882,"props":29254,"children":29258},{"alt":29255,"className":29256,"src":29257},"Code for using ConfigureAppConfiguration in Program.cs.",[3886,3887],"/posts/images/lostinconfiguration_providers_4.png",[],{"type":415,"tag":416,"props":29260,"children":29261},{},[29262],{"type":420,"value":29263},"It is important to know that order in which the configuration provider is specified matters: in case multiple providers load different values for the same setting, the value of the last provider specifying this setting is the one that will be used in the configuration. You can see in which order the configuration is loaded from different sources in the method documentation.",{"type":415,"tag":416,"props":29265,"children":29266},{},[29267],{"type":415,"tag":3882,"props":29268,"children":29272},{"alt":29269,"className":29270,"src":29271},"CreateDefaultBuilder documentation in IDE.",[3886,3887],"/posts/images/lostinconfiguration_providers_3.png",[],{"type":415,"tag":416,"props":29274,"children":29275},{},[29276,29278,29284,29286,29291,29293,29298],{"type":420,"value":29277},"If the order in which configuration providers are registered by default does not suit you, then you can simply create the ",{"type":415,"tag":468,"props":29279,"children":29281},{"className":29280},[],[29282],{"type":420,"value":29283},"HostBuilder",{"type":420,"value":29285}," yourself in ",{"type":415,"tag":468,"props":29287,"children":29289},{"className":29288},[],[29290],{"type":420,"value":20062},{"type":420,"value":29292}," instead of using ",{"type":415,"tag":468,"props":29294,"children":29296},{"className":29295},[],[29297],{"type":420,"value":29233},{"type":420,"value":1766},{"type":415,"tag":482,"props":29300,"children":29302},{"id":29301},"how-to-have-a-global-view-of-the-configuration-used-by-your-application",[29303],{"type":420,"value":29304},"How to have a global view of the configuration used by your application?",{"type":415,"tag":416,"props":29306,"children":29307},{},[29308],{"type":420,"value":29309},"Having different providers to load the configuration in your application is great but one drawback is that the configuration is scattered all over the place. Indeed sometimes we want to have the complete list of settings an application uses and if we have to look everywhere (key vault, environment variables, JSON files,...) it becomes impossible to manage.",{"type":415,"tag":416,"props":29311,"children":29312},{},[29313,29315,29320],{"type":420,"value":29314},"What I advise is to put all the settings you use in your application in the ",{"type":415,"tag":468,"props":29316,"children":29318},{"className":29317},[],[29319],{"type":420,"value":28713},{"type":420,"value":29321}," file. It does not mean you will put all the values there too or that the values you put there will be the ones that your application will use. But it means that you will have one place where you can quickly look what are the different settings keys. And concerning the values of these settings, if they should come from another file or provider (because they are relative to an environment or because they are secrets for instance), that is not a problem just put a blank value.",{"type":415,"tag":416,"props":29323,"children":29324},{},[29325,29327,29332,29334,29339,29341,29346],{"type":420,"value":29326},"So why using the ",{"type":415,"tag":468,"props":29328,"children":29330},{"className":29329},[],[29331],{"type":420,"value":28713},{"type":420,"value":29333}," file for that? In the last section, I showed the code that loads some configuration by default and you may have noticed that this settings file is the first loaded into configuration. That means any following configuration source will override the existing values coming from the ",{"type":415,"tag":468,"props":29335,"children":29337},{"className":29336},[],[29338],{"type":420,"value":28713},{"type":420,"value":29340}," file, so having all the settings declared in the ",{"type":415,"tag":468,"props":29342,"children":29344},{"className":29343},[],[29345],{"type":420,"value":28713},{"type":420,"value":29347}," file won't be a problem even if some have blank values (they will be overridden by the values loaded after).",{"type":415,"tag":434,"props":29349,"children":29350},{"icon":1382},[29351],{"type":415,"tag":416,"props":29352,"children":29353},{},[29354,29356,29363,29365,29371],{"type":420,"value":29355},"When running your application locally, if you want to display what are the values of the settings in your configuration and where their values come from you can read ",{"type":415,"tag":423,"props":29357,"children":29360},{"href":29358,"rel":29359},"https://andrewlock.net/debugging-configuration-values-in-aspnetcore/",[427],[29361],{"type":420,"value":29362},"this article",{"type":420,"value":29364}," by Andrew Lock that explains how to do that using the ",{"type":415,"tag":468,"props":29366,"children":29368},{"className":29367},[],[29369],{"type":420,"value":29370},"IConfigurationRoot.GetDebugView()",{"type":420,"value":1766},{"type":415,"tag":482,"props":29373,"children":29375},{"id":29374},"what-about-configuration-in-an-app-service-or-an-azure-function-is-it-a-specific-configuration-provider",[29376],{"type":420,"value":29377},"What about configuration in an App Service or an Azure Function, is it a specific configuration provider?",{"type":415,"tag":416,"props":29379,"children":29380},{},[29381],{"type":420,"value":29382},"Well, the answer is no. Application settings in the configuration of an App Service or a Function App (the settings you can see in the Azure portal) are passed as environment variables to the application.",{"type":415,"tag":416,"props":29384,"children":29385},{},[29386],{"type":415,"tag":3882,"props":29387,"children":29391},{"alt":29388,"className":29389,"src":29390},"Application settings in the configuration of an App Service.",[3886,3887],"/posts/images/lostinconfiguration_azureconfig_1.png",[],{"type":415,"tag":416,"props":29393,"children":29394},{},[29395],{"type":420,"value":29396},"If you remember in which order the providers are registered, it means that configuration in Azure will override most of the configuration coming from other providers.",{"type":415,"tag":482,"props":29398,"children":29400},{"id":29399},"where-to-put-environment-dependent-configuration",[29401],{"type":420,"value":29402},"Where to put environment-dependent configuration?",{"type":415,"tag":416,"props":29404,"children":29405},{},[29406],{"type":420,"value":29407},"As the name suggests, environment variables are a good place to set your environment-dependent configuration. If you are deploying your ASP.NET Core application in an Azure App Service, you can set these environment variables in the application settings section of your App Service in the Azure portal. However, I guess you are probably using an Infrastructure as Code tool (like Pulumi or Terraform) instead of manually modifying your Azure resources in the portal, so that means your environment-dependent configuration will be stored among your infrastructure code and deployed to Azure with the rest of the infrastructure.",{"type":415,"tag":434,"props":29409,"children":29410},{"icon":1382},[29411],{"type":415,"tag":416,"props":29412,"children":29413},{},[29414,29416,29423],{"type":420,"value":29415},"To know more about how are managed Environments in ASP.NET Core you can read ",{"type":415,"tag":423,"props":29417,"children":29420},{"href":29418,"rel":29419},"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments",[427],[29421],{"type":420,"value":29422},"this page of the official documentation",{"type":420,"value":29424}," that talks about that.",{"type":415,"tag":416,"props":29426,"children":29427},{},[29428,29430,29435,29437,29443,29445,29451,29453,29459,29461,29466],{"type":420,"value":29429},"Using environment variables is a good approach but it is less convenient than having settings in your JSON settings files. Moreover, if these environment settings are only in your cloud resources, you will miss some settings when you debug your application locally. That's why I think it is a good idea to take advantage of ASP.NET Core default behavior  (see ",{"type":415,"tag":468,"props":29431,"children":29433},{"className":29432},[],[29434],{"type":420,"value":29233},{"type":420,"value":29436}," implementation above) of loading the ",{"type":415,"tag":468,"props":29438,"children":29440},{"className":29439},[],[29441],{"type":420,"value":29442},"appsettings",{"type":420,"value":29444}," JSON file corresponding to the current environment. That way, if you have for example a staging environment you can set the environment variable ",{"type":415,"tag":468,"props":29446,"children":29448},{"className":29447},[],[29449],{"type":420,"value":29450},"ASPNETCORE_ENVIRONMENT",{"type":420,"value":29452}," to staging and put all your configuration for staging in the ",{"type":415,"tag":468,"props":29454,"children":29456},{"className":29455},[],[29457],{"type":420,"value":29458},"appsettings.staging.json",{"type":420,"value":29460},". This may not work for everything as some settings depend on your infrastructure deployment (maybe you only know the value of a setting after the deployment of the infrastructure), but in that case you will put these settings in your environment variables thanks to your infrastructure code and anyway that should not prevent you from putting them in your ",{"type":415,"tag":468,"props":29462,"children":29464},{"className":29463},[],[29465],{"type":420,"value":28713},{"type":420,"value":29467}," files afterward to make local debug easier.",{"type":415,"tag":416,"props":29469,"children":29470},{},[29471],{"type":415,"tag":3882,"props":29472,"children":29476},{"alt":29473,"className":29474,"src":29475},"App settings files in files explorer of an IDE.",[3886,3887],"/posts/images/lostinconfiguration_appsettings_1.png",[],{"type":415,"tag":482,"props":29478,"children":29480},{"id":29479},"how-to-deal-with-secrets-in-my-application-configuration",[29481],{"type":420,"value":29482},"How to deal with secrets in my application configuration?",{"type":415,"tag":416,"props":29484,"children":29485},{},[29486],{"type":420,"value":29487},"There are multiple ways of handling secrets but there is one fundamental rule: 'never commit a secret in source control'. Whatever the context, there is no valid reason that justifies putting a value in source code, that's it.",{"type":415,"tag":416,"props":29489,"children":29490},{},[29491,29493,29500,29502,29508,29510,29517,29519,29524],{"type":420,"value":29492},"One easy way to avoid having secrets in your source code is to use ",{"type":415,"tag":423,"props":29494,"children":29497},{"href":29495,"rel":29496},"https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets#secret-manager",[427],[29498],{"type":420,"value":29499},"Secret Manager",{"type":420,"value":29501},". It is a nice tool that allows you to put your secrets in a ",{"type":415,"tag":468,"props":29503,"children":29505},{"className":29504},[],[29506],{"type":420,"value":29507},"secrets.json",{"type":420,"value":29509}," file stored in your user profile directory (thus not committed with the rest of the code). When your application runs locally, secrets are loaded from this file in your application configuration thanks to the ",{"type":415,"tag":423,"props":29511,"children":29514},{"href":29512,"rel":29513},"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#file-configuration-provider",[427],[29515],{"type":420,"value":29516},"File configuration provider",{"type":420,"value":29518}," and everything works fine without having to put secrets in the configuration files in source control (",{"type":415,"tag":468,"props":29520,"children":29522},{"className":29521},[],[29523],{"type":420,"value":28713},{"type":420,"value":11501},{"type":415,"tag":416,"props":29526,"children":29527},{},[29528],{"type":415,"tag":3882,"props":29529,"children":29533},{"alt":29530,"className":29531,"src":29532},"Secrets.json file and option to generate it in Visual Studio.",[3886,3887],"/posts/images/lostinconfiguration_secrets_1.png",[],{"type":415,"tag":416,"props":29535,"children":29536},{},[29537],{"type":420,"value":29538},"Secret manager is interesting to debug your application locally when developing but apart from that you will want to use a vault to safely store your secrets and make them available to your application. Each cloud provider has its vault solution: Azure Key Vault, AWS Secret Manager, Google Cloud Secret Manager, and there are also third-party vaults like HashiCorp Vault for instance. To integrate with a vault, you could write your own custom provider that loads the secrets from the vault into configuration but for each of these vaults, there is a configuration provider package supported by the editor or the community.",{"type":415,"tag":416,"props":29540,"children":29541},{},[29542],{"type":420,"value":29543},"For instance, to inject secrets from an Azure KeyVault in your configuration you should use the following code:",{"type":415,"tag":523,"props":29545,"children":29547},{"className":525,"code":29546,"language":326,"meta":401,"style":401},"public static IHostBuilder CreateHostBuilder(string[] args) =>\n    Host.CreateDefaultBuilder()\n        .ConfigureAppConfiguration((context, config) =>\n        {\n            var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable(\"VaultUri\"));\n            config.AddAzureKeyVault(keyVaultEndpoint, new DefaultAzureCredential());\n        })\n        .ConfigureWebHostDefaults(webBuilder =>\n        {\n            webBuilder.UseStartup\u003CStartup>();\n        });\n",[29548],{"type":415,"tag":468,"props":29549,"children":29550},{"__ignoreMap":401},[29551,29599,29619,29655,29662,29726,29767,29775,29800,29807,29837],{"type":415,"tag":532,"props":29552,"children":29553},{"class":534,"line":535},[29554,29558,29563,29568,29573,29577,29581,29586,29591,29595],{"type":415,"tag":532,"props":29555,"children":29556},{"style":954},[29557],{"type":420,"value":957},{"type":415,"tag":532,"props":29559,"children":29560},{"style":954},[29561],{"type":420,"value":29562}," static",{"type":415,"tag":532,"props":29564,"children":29565},{"style":631},[29566],{"type":420,"value":29567}," IHostBuilder",{"type":415,"tag":532,"props":29569,"children":29570},{"style":656},[29571],{"type":420,"value":29572}," CreateHostBuilder",{"type":415,"tag":532,"props":29574,"children":29575},{"style":551},[29576],{"type":420,"value":664},{"type":415,"tag":532,"props":29578,"children":29579},{"style":551},[29580],{"type":420,"value":10698},{"type":415,"tag":532,"props":29582,"children":29583},{"style":551},[29584],{"type":420,"value":29585},"[]",{"type":415,"tag":532,"props":29587,"children":29588},{"style":631},[29589],{"type":420,"value":29590}," args",{"type":415,"tag":532,"props":29592,"children":29593},{"style":551},[29594],{"type":420,"value":1349},{"type":415,"tag":532,"props":29596,"children":29597},{"style":551},[29598],{"type":420,"value":755},{"type":415,"tag":532,"props":29600,"children":29601},{"class":534,"line":566},[29602,29607,29611,29615],{"type":415,"tag":532,"props":29603,"children":29604},{"style":545},[29605],{"type":420,"value":29606},"    Host",{"type":415,"tag":532,"props":29608,"children":29609},{"style":551},[29610],{"type":420,"value":432},{"type":415,"tag":532,"props":29612,"children":29613},{"style":656},[29614],{"type":420,"value":29233},{"type":415,"tag":532,"props":29616,"children":29617},{"style":551},[29618],{"type":420,"value":7907},{"type":415,"tag":532,"props":29620,"children":29621},{"class":534,"line":583},[29622,29626,29630,29634,29639,29643,29647,29651],{"type":415,"tag":532,"props":29623,"children":29624},{"style":551},[29625],{"type":420,"value":1532},{"type":415,"tag":532,"props":29627,"children":29628},{"style":656},[29629],{"type":420,"value":28581},{"type":415,"tag":532,"props":29631,"children":29632},{"style":551},[29633],{"type":420,"value":28586},{"type":415,"tag":532,"props":29635,"children":29636},{"style":631},[29637],{"type":420,"value":29638},"context",{"type":415,"tag":532,"props":29640,"children":29641},{"style":551},[29642],{"type":420,"value":1099},{"type":415,"tag":532,"props":29644,"children":29645},{"style":631},[29646],{"type":420,"value":7206},{"type":415,"tag":532,"props":29648,"children":29649},{"style":551},[29650],{"type":420,"value":1349},{"type":415,"tag":532,"props":29652,"children":29653},{"style":551},[29654],{"type":420,"value":755},{"type":415,"tag":532,"props":29656,"children":29657},{"class":534,"line":617},[29658],{"type":415,"tag":532,"props":29659,"children":29660},{"style":551},[29661],{"type":420,"value":1308},{"type":415,"tag":532,"props":29663,"children":29664},{"class":534,"line":627},[29665,29670,29675,29679,29683,29687,29691,29696,29700,29705,29709,29713,29718,29722],{"type":415,"tag":532,"props":29666,"children":29667},{"style":631},[29668],{"type":420,"value":29669},"            var",{"type":415,"tag":532,"props":29671,"children":29672},{"style":631},[29673],{"type":420,"value":29674}," keyVaultEndpoint",{"type":415,"tag":532,"props":29676,"children":29677},{"style":551},[29678],{"type":420,"value":644},{"type":415,"tag":532,"props":29680,"children":29681},{"style":551},[29682],{"type":420,"value":3276},{"type":415,"tag":532,"props":29684,"children":29685},{"style":631},[29686],{"type":420,"value":792},{"type":415,"tag":532,"props":29688,"children":29689},{"style":551},[29690],{"type":420,"value":664},{"type":415,"tag":532,"props":29692,"children":29693},{"style":545},[29694],{"type":420,"value":29695},"Environment",{"type":415,"tag":532,"props":29697,"children":29698},{"style":551},[29699],{"type":420,"value":432},{"type":415,"tag":532,"props":29701,"children":29702},{"style":656},[29703],{"type":420,"value":29704},"GetEnvironmentVariable",{"type":415,"tag":532,"props":29706,"children":29707},{"style":551},[29708],{"type":420,"value":664},{"type":415,"tag":532,"props":29710,"children":29711},{"style":551},[29712],{"type":420,"value":801},{"type":415,"tag":532,"props":29714,"children":29715},{"style":804},[29716],{"type":420,"value":29717},"VaultUri",{"type":415,"tag":532,"props":29719,"children":29720},{"style":551},[29721],{"type":420,"value":801},{"type":415,"tag":532,"props":29723,"children":29724},{"style":551},[29725],{"type":420,"value":816},{"type":415,"tag":532,"props":29727,"children":29728},{"class":534,"line":677},[29729,29733,29737,29742,29746,29751,29755,29759,29763],{"type":415,"tag":532,"props":29730,"children":29731},{"style":545},[29732],{"type":420,"value":29040},{"type":415,"tag":532,"props":29734,"children":29735},{"style":551},[29736],{"type":420,"value":432},{"type":415,"tag":532,"props":29738,"children":29739},{"style":656},[29740],{"type":420,"value":29741},"AddAzureKeyVault",{"type":415,"tag":532,"props":29743,"children":29744},{"style":551},[29745],{"type":420,"value":664},{"type":415,"tag":532,"props":29747,"children":29748},{"style":545},[29749],{"type":420,"value":29750},"keyVaultEndpoint",{"type":415,"tag":532,"props":29752,"children":29753},{"style":551},[29754],{"type":420,"value":1099},{"type":415,"tag":532,"props":29756,"children":29757},{"style":551},[29758],{"type":420,"value":3276},{"type":415,"tag":532,"props":29760,"children":29761},{"style":631},[29762],{"type":420,"value":842},{"type":415,"tag":532,"props":29764,"children":29765},{"style":551},[29766],{"type":420,"value":847},{"type":415,"tag":532,"props":29768,"children":29769},{"class":534,"line":719},[29770],{"type":415,"tag":532,"props":29771,"children":29772},{"style":551},[29773],{"type":420,"value":29774},"        })\n",{"type":415,"tag":532,"props":29776,"children":29777},{"class":534,"line":758},[29778,29782,29787,29791,29796],{"type":415,"tag":532,"props":29779,"children":29780},{"style":551},[29781],{"type":420,"value":1532},{"type":415,"tag":532,"props":29783,"children":29784},{"style":656},[29785],{"type":420,"value":29786},"ConfigureWebHostDefaults",{"type":415,"tag":532,"props":29788,"children":29789},{"style":551},[29790],{"type":420,"value":664},{"type":415,"tag":532,"props":29792,"children":29793},{"style":631},[29794],{"type":420,"value":29795},"webBuilder",{"type":415,"tag":532,"props":29797,"children":29798},{"style":551},[29799],{"type":420,"value":755},{"type":415,"tag":532,"props":29801,"children":29802},{"class":534,"line":767},[29803],{"type":415,"tag":532,"props":29804,"children":29805},{"style":551},[29806],{"type":420,"value":1308},{"type":415,"tag":532,"props":29808,"children":29809},{"class":534,"line":819},[29810,29815,29819,29824,29828,29833],{"type":415,"tag":532,"props":29811,"children":29812},{"style":545},[29813],{"type":420,"value":29814},"            webBuilder",{"type":415,"tag":532,"props":29816,"children":29817},{"style":551},[29818],{"type":420,"value":432},{"type":415,"tag":532,"props":29820,"children":29821},{"style":656},[29822],{"type":420,"value":29823},"UseStartup",{"type":415,"tag":532,"props":29825,"children":29826},{"style":551},[29827],{"type":420,"value":706},{"type":415,"tag":532,"props":29829,"children":29830},{"style":631},[29831],{"type":420,"value":29832},"Startup",{"type":415,"tag":532,"props":29834,"children":29835},{"style":551},[29836],{"type":420,"value":716},{"type":415,"tag":532,"props":29838,"children":29839},{"class":534,"line":850},[29840],{"type":415,"tag":532,"props":29841,"children":29842},{"style":551},[29843],{"type":420,"value":2029},{"type":415,"tag":416,"props":29845,"children":29846},{},[29847],{"type":420,"value":29848},"Vaults are generally cheap and anyway it is not as if security was an optional feature we should choose to add or not, therefore there is no reason not to use a vault to keep your secrets safe.",{"type":415,"tag":482,"props":29850,"children":29852},{"id":29851},"how-to-share-configuration-between-different-applications",[29853],{"type":420,"value":29854},"How to share configuration between different applications?",{"type":415,"tag":416,"props":29856,"children":29857},{},[29858,29860,29867],{"type":420,"value":29859},"There is a specific Azure component for that which is ",{"type":415,"tag":423,"props":29861,"children":29864},{"href":29862,"rel":29863},"https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview",[427],[29865],{"type":420,"value":29866},"Azure App Configuration",{"type":420,"value":29868},". It provides you a centralized place to manage your configuration for different applications, environments and locations. It also provides you other interesting features like the ability to dynamically change the value of an application setting without the need to restart this application.",{"type":415,"tag":416,"props":29870,"children":29871},{},[29872],{"type":415,"tag":3882,"props":29873,"children":29877},{"alt":29874,"className":29875,"src":29876},"Configuration explorer in an Azure App Configuration resource.",[3886,3887],"/posts/images/lostinconfiguration_appconfig_1.png",[],{"type":415,"tag":416,"props":29879,"children":29880},{},[29881],{"type":420,"value":29882},"Azure App Configuration has its configuration provider that you can register like that:",{"type":415,"tag":523,"props":29884,"children":29886},{"className":525,"code":29885,"language":326,"meta":401,"style":401},"public static IHostBuilder CreateHostBuilder(string[] args) =>\n    Host.CreateDefaultBuilder()\n        .ConfigureAppConfiguration((context, config) =>\n        {\n            var settings = config.Build();\n            var appConfigurationConnectionUri = new Uri(settings.GetValue\u003Cstring>(\"Endpoints:AppConfig\"));\n            config.AddAzureAppConfiguration(options =>\n            {\n                options.Connect(appConfigurationConnectionUri, new DefaultAzureCredential());\n            });\n        })\n        .ConfigureWebHostDefaults(webBuilder =>\n        {\n            webBuilder.UseStartup\u003CStartup>();\n        });\n",[29887],{"type":415,"tag":468,"props":29888,"children":29889},{"__ignoreMap":401},[29890,29933,29952,29987,29994,30026,30098,30126,30134,30176,30184,30191,30214,30221,30248],{"type":415,"tag":532,"props":29891,"children":29892},{"class":534,"line":535},[29893,29897,29901,29905,29909,29913,29917,29921,29925,29929],{"type":415,"tag":532,"props":29894,"children":29895},{"style":954},[29896],{"type":420,"value":957},{"type":415,"tag":532,"props":29898,"children":29899},{"style":954},[29900],{"type":420,"value":29562},{"type":415,"tag":532,"props":29902,"children":29903},{"style":631},[29904],{"type":420,"value":29567},{"type":415,"tag":532,"props":29906,"children":29907},{"style":656},[29908],{"type":420,"value":29572},{"type":415,"tag":532,"props":29910,"children":29911},{"style":551},[29912],{"type":420,"value":664},{"type":415,"tag":532,"props":29914,"children":29915},{"style":551},[29916],{"type":420,"value":10698},{"type":415,"tag":532,"props":29918,"children":29919},{"style":551},[29920],{"type":420,"value":29585},{"type":415,"tag":532,"props":29922,"children":29923},{"style":631},[29924],{"type":420,"value":29590},{"type":415,"tag":532,"props":29926,"children":29927},{"style":551},[29928],{"type":420,"value":1349},{"type":415,"tag":532,"props":29930,"children":29931},{"style":551},[29932],{"type":420,"value":755},{"type":415,"tag":532,"props":29934,"children":29935},{"class":534,"line":566},[29936,29940,29944,29948],{"type":415,"tag":532,"props":29937,"children":29938},{"style":545},[29939],{"type":420,"value":29606},{"type":415,"tag":532,"props":29941,"children":29942},{"style":551},[29943],{"type":420,"value":432},{"type":415,"tag":532,"props":29945,"children":29946},{"style":656},[29947],{"type":420,"value":29233},{"type":415,"tag":532,"props":29949,"children":29950},{"style":551},[29951],{"type":420,"value":7907},{"type":415,"tag":532,"props":29953,"children":29954},{"class":534,"line":583},[29955,29959,29963,29967,29971,29975,29979,29983],{"type":415,"tag":532,"props":29956,"children":29957},{"style":551},[29958],{"type":420,"value":1532},{"type":415,"tag":532,"props":29960,"children":29961},{"style":656},[29962],{"type":420,"value":28581},{"type":415,"tag":532,"props":29964,"children":29965},{"style":551},[29966],{"type":420,"value":28586},{"type":415,"tag":532,"props":29968,"children":29969},{"style":631},[29970],{"type":420,"value":29638},{"type":415,"tag":532,"props":29972,"children":29973},{"style":551},[29974],{"type":420,"value":1099},{"type":415,"tag":532,"props":29976,"children":29977},{"style":631},[29978],{"type":420,"value":7206},{"type":415,"tag":532,"props":29980,"children":29981},{"style":551},[29982],{"type":420,"value":1349},{"type":415,"tag":532,"props":29984,"children":29985},{"style":551},[29986],{"type":420,"value":755},{"type":415,"tag":532,"props":29988,"children":29989},{"class":534,"line":617},[29990],{"type":415,"tag":532,"props":29991,"children":29992},{"style":551},[29993],{"type":420,"value":1308},{"type":415,"tag":532,"props":29995,"children":29996},{"class":534,"line":627},[29997,30001,30006,30010,30014,30018,30022],{"type":415,"tag":532,"props":29998,"children":29999},{"style":631},[30000],{"type":420,"value":29669},{"type":415,"tag":532,"props":30002,"children":30003},{"style":631},[30004],{"type":420,"value":30005}," settings",{"type":415,"tag":532,"props":30007,"children":30008},{"style":551},[30009],{"type":420,"value":644},{"type":415,"tag":532,"props":30011,"children":30012},{"style":545},[30013],{"type":420,"value":7206},{"type":415,"tag":532,"props":30015,"children":30016},{"style":551},[30017],{"type":420,"value":432},{"type":415,"tag":532,"props":30019,"children":30020},{"style":656},[30021],{"type":420,"value":894},{"type":415,"tag":532,"props":30023,"children":30024},{"style":551},[30025],{"type":420,"value":899},{"type":415,"tag":532,"props":30027,"children":30028},{"class":534,"line":677},[30029,30033,30038,30042,30046,30050,30054,30059,30063,30068,30072,30076,30081,30085,30090,30094],{"type":415,"tag":532,"props":30030,"children":30031},{"style":631},[30032],{"type":420,"value":29669},{"type":415,"tag":532,"props":30034,"children":30035},{"style":631},[30036],{"type":420,"value":30037}," appConfigurationConnectionUri",{"type":415,"tag":532,"props":30039,"children":30040},{"style":551},[30041],{"type":420,"value":644},{"type":415,"tag":532,"props":30043,"children":30044},{"style":551},[30045],{"type":420,"value":3276},{"type":415,"tag":532,"props":30047,"children":30048},{"style":631},[30049],{"type":420,"value":792},{"type":415,"tag":532,"props":30051,"children":30052},{"style":551},[30053],{"type":420,"value":664},{"type":415,"tag":532,"props":30055,"children":30056},{"style":545},[30057],{"type":420,"value":30058},"settings",{"type":415,"tag":532,"props":30060,"children":30061},{"style":551},[30062],{"type":420,"value":432},{"type":415,"tag":532,"props":30064,"children":30065},{"style":656},[30066],{"type":420,"value":30067},"GetValue",{"type":415,"tag":532,"props":30069,"children":30070},{"style":551},[30071],{"type":420,"value":706},{"type":415,"tag":532,"props":30073,"children":30074},{"style":551},[30075],{"type":420,"value":10698},{"type":415,"tag":532,"props":30077,"children":30078},{"style":551},[30079],{"type":420,"value":30080},">(",{"type":415,"tag":532,"props":30082,"children":30083},{"style":551},[30084],{"type":420,"value":801},{"type":415,"tag":532,"props":30086,"children":30087},{"style":804},[30088],{"type":420,"value":30089},"Endpoints:AppConfig",{"type":415,"tag":532,"props":30091,"children":30092},{"style":551},[30093],{"type":420,"value":801},{"type":415,"tag":532,"props":30095,"children":30096},{"style":551},[30097],{"type":420,"value":816},{"type":415,"tag":532,"props":30099,"children":30100},{"class":534,"line":719},[30101,30105,30109,30114,30118,30122],{"type":415,"tag":532,"props":30102,"children":30103},{"style":545},[30104],{"type":420,"value":29040},{"type":415,"tag":532,"props":30106,"children":30107},{"style":551},[30108],{"type":420,"value":432},{"type":415,"tag":532,"props":30110,"children":30111},{"style":656},[30112],{"type":420,"value":30113},"AddAzureAppConfiguration",{"type":415,"tag":532,"props":30115,"children":30116},{"style":551},[30117],{"type":420,"value":664},{"type":415,"tag":532,"props":30119,"children":30120},{"style":631},[30121],{"type":420,"value":1903},{"type":415,"tag":532,"props":30123,"children":30124},{"style":551},[30125],{"type":420,"value":755},{"type":415,"tag":532,"props":30127,"children":30128},{"class":534,"line":758},[30129],{"type":415,"tag":532,"props":30130,"children":30131},{"style":551},[30132],{"type":420,"value":30133},"            {\n",{"type":415,"tag":532,"props":30135,"children":30136},{"class":534,"line":767},[30137,30142,30146,30151,30155,30160,30164,30168,30172],{"type":415,"tag":532,"props":30138,"children":30139},{"style":545},[30140],{"type":420,"value":30141},"                options",{"type":415,"tag":532,"props":30143,"children":30144},{"style":551},[30145],{"type":420,"value":432},{"type":415,"tag":532,"props":30147,"children":30148},{"style":656},[30149],{"type":420,"value":30150},"Connect",{"type":415,"tag":532,"props":30152,"children":30153},{"style":551},[30154],{"type":420,"value":664},{"type":415,"tag":532,"props":30156,"children":30157},{"style":545},[30158],{"type":420,"value":30159},"appConfigurationConnectionUri",{"type":415,"tag":532,"props":30161,"children":30162},{"style":551},[30163],{"type":420,"value":1099},{"type":415,"tag":532,"props":30165,"children":30166},{"style":551},[30167],{"type":420,"value":3276},{"type":415,"tag":532,"props":30169,"children":30170},{"style":631},[30171],{"type":420,"value":842},{"type":415,"tag":532,"props":30173,"children":30174},{"style":551},[30175],{"type":420,"value":847},{"type":415,"tag":532,"props":30177,"children":30178},{"class":534,"line":819},[30179],{"type":415,"tag":532,"props":30180,"children":30181},{"style":551},[30182],{"type":420,"value":30183},"            });\n",{"type":415,"tag":532,"props":30185,"children":30186},{"class":534,"line":850},[30187],{"type":415,"tag":532,"props":30188,"children":30189},{"style":551},[30190],{"type":420,"value":29774},{"type":415,"tag":532,"props":30192,"children":30193},{"class":534,"line":859},[30194,30198,30202,30206,30210],{"type":415,"tag":532,"props":30195,"children":30196},{"style":551},[30197],{"type":420,"value":1532},{"type":415,"tag":532,"props":30199,"children":30200},{"style":656},[30201],{"type":420,"value":29786},{"type":415,"tag":532,"props":30203,"children":30204},{"style":551},[30205],{"type":420,"value":664},{"type":415,"tag":532,"props":30207,"children":30208},{"style":631},[30209],{"type":420,"value":29795},{"type":415,"tag":532,"props":30211,"children":30212},{"style":551},[30213],{"type":420,"value":755},{"type":415,"tag":532,"props":30215,"children":30216},{"class":534,"line":867},[30217],{"type":415,"tag":532,"props":30218,"children":30219},{"style":551},[30220],{"type":420,"value":1308},{"type":415,"tag":532,"props":30222,"children":30223},{"class":534,"line":902},[30224,30228,30232,30236,30240,30244],{"type":415,"tag":532,"props":30225,"children":30226},{"style":545},[30227],{"type":420,"value":29814},{"type":415,"tag":532,"props":30229,"children":30230},{"style":551},[30231],{"type":420,"value":432},{"type":415,"tag":532,"props":30233,"children":30234},{"style":656},[30235],{"type":420,"value":29823},{"type":415,"tag":532,"props":30237,"children":30238},{"style":551},[30239],{"type":420,"value":706},{"type":415,"tag":532,"props":30241,"children":30242},{"style":631},[30243],{"type":420,"value":29832},{"type":415,"tag":532,"props":30245,"children":30246},{"style":551},[30247],{"type":420,"value":716},{"type":415,"tag":532,"props":30249,"children":30250},{"class":534,"line":1302},[30251],{"type":415,"tag":532,"props":30252,"children":30253},{"style":551},[30254],{"type":420,"value":2029},{"type":415,"tag":482,"props":30256,"children":30258},{"id":30257},"which-configuration-provider-can-help-me-to-use-ab-testing-and-feature-flags-in-my-code",[30259],{"type":420,"value":30260},"Which configuration provider can help me to use A/B testing and feature flags in my code?",{"type":415,"tag":416,"props":30262,"children":30263},{},[30264,30269],{"type":415,"tag":423,"props":30265,"children":30267},{"href":29862,"rel":30266},[427],[30268],{"type":420,"value":29866},{"type":420,"value":30270}," is also the configuration provider to use when you want to use A/B testing or feature flags.\nThere are probably other configuration providers that allow you to do that but this is the one I know.",{"type":415,"tag":482,"props":30272,"children":30274},{"id":30273},"what-is-the-point-of-using-the-launchsettingsjson-file",[30275,30277,30283],{"type":420,"value":30276},"What is the point of using the ",{"type":415,"tag":468,"props":30278,"children":30280},{"className":30279},[],[30281],{"type":420,"value":30282},"launchsettings.json",{"type":420,"value":30284}," file?",{"type":415,"tag":416,"props":30286,"children":30287},{},[30288,30290,30295,30297,30302,30304,30309,30311,30317,30319,30324,30326,30331],{"type":420,"value":30289},"Unlike the ",{"type":415,"tag":468,"props":30291,"children":30293},{"className":30292},[],[30294],{"type":420,"value":29442},{"type":420,"value":30296}," files, the ",{"type":415,"tag":468,"props":30298,"children":30300},{"className":30299},[],[30301],{"type":420,"value":30282},{"type":420,"value":30303}," file is not used when you build and deploy your application somewhere. It is only useful to debug your application code locally. The tools you use to run your application on your local machine (your IDE or the .NET Core CLI) will use the settings in this file to provide configuration to your apps through environments variables or command line arguments. By default, this file will set the ",{"type":415,"tag":468,"props":30305,"children":30307},{"className":30306},[],[30308],{"type":420,"value":29450},{"type":420,"value":30310}," environment variable (or ",{"type":415,"tag":468,"props":30312,"children":30314},{"className":30313},[],[30315],{"type":420,"value":30316},"DOTNET_ENVIRONMENT",{"type":420,"value":30318}," depending on whether your application is an ASP.NET Core application or not) to ",{"type":415,"tag":468,"props":30320,"children":30322},{"className":30321},[],[30323],{"type":420,"value":408},{"type":420,"value":30325}," so that you debug your code with the ",{"type":415,"tag":468,"props":30327,"children":30329},{"className":30328},[],[30330],{"type":420,"value":408},{"type":420,"value":30332}," configuration",{"type":415,"tag":416,"props":30334,"children":30335},{},[30336],{"type":415,"tag":3882,"props":30337,"children":30341},{"alt":30338,"className":30339,"src":30340},"Example of a launchsettings.json file.",[3886,3887],"/posts/images/lostinconfiguration_launchsettings_1.png",[],{"type":415,"tag":434,"props":30343,"children":30344},{"icon":1382},[30345],{"type":415,"tag":416,"props":30346,"children":30347},{},[30348,30350,30355,30357,30363,30365,30371],{"type":420,"value":30349},"You can define multiple profiles in the ",{"type":415,"tag":468,"props":30351,"children":30353},{"className":30352},[],[30354],{"type":420,"value":30282},{"type":420,"value":30356}," file to be able to run your application with multiple configurations. It can be interesting to create a ",{"type":415,"tag":468,"props":30358,"children":30360},{"className":30359},[],[30361],{"type":420,"value":30362},"Staging profile",{"type":420,"value":30364}," to debug your application with the ",{"type":415,"tag":468,"props":30366,"children":30368},{"className":30367},[],[30369],{"type":420,"value":30370},"Staging",{"type":420,"value":30372}," configuration; for instance to reproduce a bug that only happens in Staging environment.",{"type":415,"tag":482,"props":30374,"children":30376},{"id":30375},"lets-recap",[30377],{"type":420,"value":30378},"Let's recap.",{"type":415,"tag":416,"props":30380,"children":30381},{},[30382],{"type":420,"value":30383},"To know where to put your settings in an ASP.NET Core project you have to ask yourself some questions: is this setting secret or not, does its value depends on the environment, will it be shared with other applications... ?",{"type":415,"tag":416,"props":30385,"children":30386},{},[30387],{"type":420,"value":30388},"My point of view about how to handle the configuration in an ASP.NET Core project is the following:",{"type":415,"tag":508,"props":30390,"children":30391},{},[30392,30404,30417,30422,30434,30446],{"type":415,"tag":512,"props":30393,"children":30394},{},[30395,30397,30402],{"type":420,"value":30396},"put all your settings in the ",{"type":415,"tag":468,"props":30398,"children":30400},{"className":30399},[],[30401],{"type":420,"value":28713},{"type":420,"value":30403}," file (without necessarily putting the values of the settings) to have a global view of the configuration used by your application",{"type":415,"tag":512,"props":30405,"children":30406},{},[30407,30409,30415],{"type":420,"value":30408},"keep a ",{"type":415,"tag":468,"props":30410,"children":30412},{"className":30411},[],[30413],{"type":420,"value":30414},"appsettings.{EnvironmentName}.json",{"type":420,"value":30416}," file by environment in your project with only the settings that are dependent on the environment",{"type":415,"tag":512,"props":30418,"children":30419},{},[30420],{"type":420,"value":30421},"never store secrets in source code and use an Azure Key Vault to store the settings that are secrets",{"type":415,"tag":512,"props":30423,"children":30424},{},[30425,30427,30432],{"type":420,"value":30426},"create different profiles in your ",{"type":415,"tag":468,"props":30428,"children":30430},{"className":30429},[],[30431],{"type":420,"value":30282},{"type":420,"value":30433},"file to debug your application locally with different configurations",{"type":415,"tag":512,"props":30435,"children":30436},{},[30437,30439,30444],{"type":420,"value":30438},"use environment variables (through ",{"type":415,"tag":468,"props":30440,"children":30442},{"className":30441},[],[30443],{"type":420,"value":30282},{"type":420,"value":30445}," locally and application settings in Azure) to override settings previously defined in other configuration sources",{"type":415,"tag":512,"props":30447,"children":30448},{},[30449],{"type":420,"value":30450},"think about Azure App Configuration if you need to share some settings among different applications",{"type":415,"tag":416,"props":30452,"children":30453},{},[30454],{"type":420,"value":30455},"I hope this article has answered some of your questions about configuration ASP.NET Core and that you feel less lost now. Have fun with configuration providers!",{"type":415,"tag":3470,"props":30457,"children":30458},{},[30459],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":30461},[30462,30463,30464,30465,30466,30467,30468,30469,30470,30472],{"id":28503,"depth":566,"text":28506},{"id":28528,"depth":566,"text":28531},{"id":29301,"depth":566,"text":29304},{"id":29374,"depth":566,"text":29377},{"id":29399,"depth":566,"text":29402},{"id":29479,"depth":566,"text":29482},{"id":29851,"depth":566,"text":29854},{"id":30257,"depth":566,"text":30260},{"id":30273,"depth":566,"text":30471},"What is the point of using the launchsettings.json file?",{"id":30375,"depth":566,"text":30378},"content:1.posts:24.lost-in-configuration.md","1.posts/24.lost-in-configuration.md",{"_path":76,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":75,"description":30476,"date":30477,"image":30478,"badge":30480,"tags":30481,"body":30482,"_type":3483,"_id":32410,"_source":3485,"_file":32411,"_extension":3487},"If you are using Azure Functions chances are you are using the setting AzureWebJobsStorage in your Function App configuration. And it is quite likely that the value of this setting which is a secret is stored in a non-secured way directly in your Function App configuration, available to anyone who has access to this configuration. But do not worry, we will see in this article how we can make your Function App more secure by removing this secret.","2021-09-15T00:00:00.000Z",{"src":30479},"/images/lightning_2.jpg",{"label":266},[257,312,315,252,228],{"type":412,"children":30483,"toc":32399},[30484,30497,30502,30508,30521,30533,30542,30548,30553,30562,30567,30573,30587,30596,30609,30622,30638,30644,30657,30663,30668,30686,30691,30697,30710,30715,30821,30834,31044,31049,31319,31331,31985,32007,32224,32232,32251,32264,32270,32275,32311,32320,32333,32338,32367,32372,32380,32385,32390,32395],{"type":415,"tag":416,"props":30485,"children":30486},{},[30487,30489,30495],{"type":420,"value":30488},"If you are using Azure Functions chances are you are using the setting ",{"type":415,"tag":468,"props":30490,"children":30492},{"className":30491},[],[30493],{"type":420,"value":30494},"AzureWebJobsStorage",{"type":420,"value":30496}," in your Function App configuration. And it is quite likely that the value of this setting which is a secret is stored in a non-secured way directly in your Function App configuration, available to anyone who has access to this configuration. But do not worry, we will see in this article how we can make your Function App more secure by removing this secret.",{"type":415,"tag":416,"props":30498,"children":30499},{},[30500],{"type":420,"value":30501},"But first, let's start at the beginning.",{"type":415,"tag":482,"props":30503,"children":30505},{"id":30504},"what-is-this-azurewebjobsstorage-setting",[30506],{"type":420,"value":30507},"What is this AzureWebJobsStorage setting?",{"type":415,"tag":416,"props":30509,"children":30510},{},[30511,30513,30519],{"type":420,"value":30512},"As explained in the ",{"type":415,"tag":423,"props":30514,"children":30517},{"href":30515,"rel":30516},"https://docs.microsoft.com/en-us/azure/azure-functions/storage-considerations#storage-account-requirements",[427],[30518],{"type":420,"value":499},{"type":420,"value":30520},", Azure Functions \"rely on Azure Storage for operations such as managing triggers and logging function executions\" which explains why you must associate a storage account to your Function App when you create one.",{"type":415,"tag":416,"props":30522,"children":30523},{},[30524,30526,30531],{"type":420,"value":30525},"By default when you create a Function App with its storage account from Azure Portal, the setting ",{"type":415,"tag":468,"props":30527,"children":30529},{"className":30528},[],[30530],{"type":420,"value":30494},{"type":420,"value":30532}," is automatically created in the Function App configuration and its value contains the secret connection string of the storage account. Thanks to that it will allow your Function App to have access to this storage and to work properly.",{"type":415,"tag":416,"props":30534,"children":30535},{},[30536],{"type":415,"tag":3882,"props":30537,"children":30541},{"alt":30538,"className":30539,"src":30540},"AzureWebJobsStorage setting with a secret value in Function App settings.",[3886,3887],"/posts/images/functionsidentity_portal_1.png",[],{"type":415,"tag":482,"props":30543,"children":30545},{"id":30544},"why-azurewebjobsstorage-poses-a-security-risk",[30546],{"type":420,"value":30547},"Why AzureWebJobsStorage poses a security risk?",{"type":415,"tag":416,"props":30549,"children":30550},{},[30551],{"type":420,"value":30552},"App settings of your Function App are stored encrypted in Azure so having secrets in a Function App configuration in Azure does not seem a big security threat. Yet,  secrets in Azure application settings will be available to anyone who has access to the configuration screen of your Function App (or to Kudu) which does not seem a great idea. Moreover in the application settings of a Function App, there is no proper access monitoring, alerting, and auditing as you would have in an Azure Key Vault. So your secret is not really \"safe\" there.",{"type":415,"tag":416,"props":30554,"children":30555},{},[30556],{"type":415,"tag":3882,"props":30557,"children":30561},{"alt":30558,"className":30559,"src":30560},"Padlock on a keyboard.",[3886,3887],"/posts/images/functionsidentity_padlock_1.jpgpng",[],{"type":415,"tag":416,"props":30563,"children":30564},{},[30565],{"type":420,"value":30566},"To avoid having someone gaining access to your storage account without you knowing, you probably do not want your storage account connection string to stay in a Function App configuration on Azure Portal.",{"type":415,"tag":482,"props":30568,"children":30570},{"id":30569},"what-can-we-do-about-it",[30571],{"type":420,"value":30572},"What can we do about it?",{"type":415,"tag":416,"props":30574,"children":30575},{},[30576,30578,30585],{"type":420,"value":30577},"A solution could be to store the AzureWebJobsStorage secret value in an Azure Key Vault and use a ",{"type":415,"tag":423,"props":30579,"children":30582},{"href":30580,"rel":30581},"https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references",[427],[30583],{"type":420,"value":30584},"Key Vault reference",{"type":420,"value":30586}," to link the secret in Key Vault to the AzureWebJobsStorage setting like on the example below.",{"type":415,"tag":416,"props":30588,"children":30589},{},[30590],{"type":415,"tag":3882,"props":30591,"children":30595},{"alt":30592,"className":30593,"src":30594},"AzureWebJobsStorage setting as a keyvault reference in Function App settings.",[3886,3887],"/posts/images/functionsidentity_portal_2.png",[],{"type":415,"tag":416,"props":30597,"children":30598},{},[30599,30601,30607],{"type":420,"value":30600},"Another solution that is far more interesting I think (as it does not require any secret) is to assign the Storage Blob Data Owner role to your Function App identity and to replace the AzureWebJobsStorage connection string setting by the setting ",{"type":415,"tag":468,"props":30602,"children":30604},{"className":30603},[],[30605],{"type":420,"value":30606},"AzureWebJobsStorage__accountName",{"type":420,"value":30608}," that only contains the name of the storage account and no secret value at all.",{"type":415,"tag":416,"props":30610,"children":30611},{},[30612,30614,30620],{"type":420,"value":30613},"If you want more details about connecting to the storage with the Function App identity you can find it ",{"type":415,"tag":423,"props":30615,"children":30618},{"href":30616,"rel":30617},"https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference#connecting-to-host-storage-with-an-identity",[427],[30619],{"type":420,"value":4427},{"type":420,"value":30621},". There is no point for me to paraphrase the documentation just to explain how you can set this up. However, I can show you how to implement that using Infrastructure as Code.",{"type":415,"tag":434,"props":30623,"children":30624},{"icon":1382},[30625],{"type":415,"tag":416,"props":30626,"children":30627},{},[30628,30630,30636],{"type":420,"value":30629},"If you have read ",{"type":415,"tag":423,"props":30631,"children":30633},{"href":22707,"rel":30632},[427],[30634],{"type":420,"value":30635},"my article",{"type":420,"value":30637}," about connecting to an Azure SQL Database using Azure AD to authenticate instead of a secret connection, you probably know that I am not a big fan of secrets when we can avoid using them. From a security perspective, I think it is always a gain to remove the need for secrets while ensuring a resource can only be accessed by authorized people/applications.",{"type":415,"tag":482,"props":30639,"children":30641},{"id":30640},"how-to-configure-a-function-app-to-work-with-its-storage-account-without-a-secret-connection-string",[30642],{"type":420,"value":30643},"How to configure a Function App to work with its storage account without a secret connection string?",{"type":415,"tag":416,"props":30645,"children":30646},{},[30647,30649,30655],{"type":420,"value":30648},"To do that, I will use ",{"type":415,"tag":423,"props":30650,"children":30653},{"href":30651,"rel":30652},"https://www.pulumi.com/",[427],[30654],{"type":420,"value":312},{"type":420,"value":30656}," which is an Infrastructure as Code platform that uses programming languages instead of DSL to deploy infrastructure. As I am usually programming in C# for my application code, I will use C# as well for my infrastructure code.",{"type":415,"tag":3914,"props":30658,"children":30660},{"id":30659},"what-resources-do-we-need-to-create",[30661],{"type":420,"value":30662},"What resources do we need to create?",{"type":415,"tag":416,"props":30664,"children":30665},{},[30666],{"type":420,"value":30667},"We need to create 3 different Azure resources:",{"type":415,"tag":508,"props":30669,"children":30670},{},[30671,30676,30681],{"type":415,"tag":512,"props":30672,"children":30673},{},[30674],{"type":420,"value":30675},"a consumption App Service Plan",{"type":415,"tag":512,"props":30677,"children":30678},{},[30679],{"type":420,"value":30680},"a Function App",{"type":415,"tag":512,"props":30682,"children":30683},{},[30684],{"type":420,"value":30685},"a Storage Account",{"type":415,"tag":416,"props":30687,"children":30688},{},[30689],{"type":420,"value":30690},"A resource group will also be created to contain these resources.\nAnd we will also need to assign the Storage Blob Data Owner role to the Function App, so to create a Role Assignment \"resource\".",{"type":415,"tag":3914,"props":30692,"children":30694},{"id":30693},"what-the-infrastructure-code-looks-like",[30695],{"type":420,"value":30696},"What the infrastructure code looks like?",{"type":415,"tag":416,"props":30698,"children":30699},{},[30700,30702,30708],{"type":420,"value":30701},"The infrastructure code looks like standard C# code, but it describes the Azure resources we need using the ",{"type":415,"tag":423,"props":30703,"children":30706},{"href":30704,"rel":30705},"https://www.pulumi.com/blog/full-coverage-of-azure-resources-with-azure-native/",[427],[30707],{"type":420,"value":7102},{"type":420,"value":30709}," for Pulumi.",{"type":415,"tag":416,"props":30711,"children":30712},{},[30713],{"type":420,"value":30714},"Declaring a resource group is quite easy. Here we use C# string interpolation to build the resource group name from the project name and the stack name (two Pulumi notions that correspond to the name of the project and the environment):",{"type":415,"tag":523,"props":30716,"children":30718},{"className":525,"code":30717,"language":326,"meta":401,"style":401},"var resourceGroup = new ResourceGroup($\"rg-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\");\n",[30719],{"type":415,"tag":468,"props":30720,"children":30721},{"__ignoreMap":401},[30722],{"type":415,"tag":532,"props":30723,"children":30724},{"class":534,"line":535},[30725,30729,30733,30737,30741,30745,30749,30753,30757,30761,30765,30769,30773,30777,30781,30785,30789,30793,30797,30801,30805,30809,30813,30817],{"type":415,"tag":532,"props":30726,"children":30727},{"style":631},[30728],{"type":420,"value":634},{"type":415,"tag":532,"props":30730,"children":30731},{"style":631},[30732],{"type":420,"value":20155},{"type":415,"tag":532,"props":30734,"children":30735},{"style":551},[30736],{"type":420,"value":644},{"type":415,"tag":532,"props":30738,"children":30739},{"style":551},[30740],{"type":420,"value":3276},{"type":415,"tag":532,"props":30742,"children":30743},{"style":631},[30744],{"type":420,"value":20168},{"type":415,"tag":532,"props":30746,"children":30747},{"style":551},[30748],{"type":420,"value":664},{"type":415,"tag":532,"props":30750,"children":30751},{"style":551},[30752],{"type":420,"value":8738},{"type":415,"tag":532,"props":30754,"children":30755},{"style":804},[30756],{"type":420,"value":20181},{"type":415,"tag":532,"props":30758,"children":30759},{"style":551},[30760],{"type":420,"value":8748},{"type":415,"tag":532,"props":30762,"children":30763},{"style":545},[30764],{"type":420,"value":20190},{"type":415,"tag":532,"props":30766,"children":30767},{"style":551},[30768],{"type":420,"value":432},{"type":415,"tag":532,"props":30770,"children":30771},{"style":545},[30772],{"type":420,"value":20199},{"type":415,"tag":532,"props":30774,"children":30775},{"style":551},[30776],{"type":420,"value":432},{"type":415,"tag":532,"props":30778,"children":30779},{"style":545},[30780],{"type":420,"value":20208},{"type":415,"tag":532,"props":30782,"children":30783},{"style":551},[30784],{"type":420,"value":4864},{"type":415,"tag":532,"props":30786,"children":30787},{"style":804},[30788],{"type":420,"value":4216},{"type":415,"tag":532,"props":30790,"children":30791},{"style":551},[30792],{"type":420,"value":8748},{"type":415,"tag":532,"props":30794,"children":30795},{"style":545},[30796],{"type":420,"value":20190},{"type":415,"tag":532,"props":30798,"children":30799},{"style":551},[30800],{"type":420,"value":432},{"type":415,"tag":532,"props":30802,"children":30803},{"style":545},[30804],{"type":420,"value":20199},{"type":415,"tag":532,"props":30806,"children":30807},{"style":551},[30808],{"type":420,"value":432},{"type":415,"tag":532,"props":30810,"children":30811},{"style":545},[30812],{"type":420,"value":20241},{"type":415,"tag":532,"props":30814,"children":30815},{"style":551},[30816],{"type":420,"value":4502},{"type":415,"tag":532,"props":30818,"children":30819},{"style":551},[30820],{"type":420,"value":674},{"type":415,"tag":416,"props":30822,"children":30823},{},[30824,30826,30832],{"type":420,"value":30825},"To declare the resource group in which we want to create the storage account, we can use the property name of variable ",{"type":415,"tag":468,"props":30827,"children":30829},{"className":30828},[],[30830],{"type":420,"value":30831},"resourceGroup",{"type":420,"value":30833}," previously declared. We can see that for some arguments like the SKU names, Pulumi has types to help us choose between different possible values instead of specifying a magic string. It is not always the case but it is pretty handy when such things are available.",{"type":415,"tag":523,"props":30835,"children":30837},{"className":525,"code":30836,"language":326,"meta":401,"style":401},"var storageAccount = new StorageAccount($\"stnosecretfun{Deployment.Instance.StackName}\", new StorageAccountArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    Sku = new SkuArgs\n    {\n        Name = SkuName.Standard_LRS\n    },\n    Kind = Kind.StorageV2\n});\n",[30838],{"type":415,"tag":468,"props":30839,"children":30840},{"__ignoreMap":401},[30841,30920,30927,30954,30973,30980,31005,31012,31037],{"type":415,"tag":532,"props":30842,"children":30843},{"class":534,"line":535},[30844,30848,30853,30857,30861,30866,30870,30874,30879,30883,30887,30891,30895,30899,30903,30907,30911,30915],{"type":415,"tag":532,"props":30845,"children":30846},{"style":631},[30847],{"type":420,"value":634},{"type":415,"tag":532,"props":30849,"children":30850},{"style":631},[30851],{"type":420,"value":30852}," storageAccount",{"type":415,"tag":532,"props":30854,"children":30855},{"style":551},[30856],{"type":420,"value":644},{"type":415,"tag":532,"props":30858,"children":30859},{"style":551},[30860],{"type":420,"value":3276},{"type":415,"tag":532,"props":30862,"children":30863},{"style":631},[30864],{"type":420,"value":30865}," StorageAccount",{"type":415,"tag":532,"props":30867,"children":30868},{"style":551},[30869],{"type":420,"value":664},{"type":415,"tag":532,"props":30871,"children":30872},{"style":551},[30873],{"type":420,"value":8738},{"type":415,"tag":532,"props":30875,"children":30876},{"style":804},[30877],{"type":420,"value":30878},"stnosecretfun",{"type":415,"tag":532,"props":30880,"children":30881},{"style":551},[30882],{"type":420,"value":8748},{"type":415,"tag":532,"props":30884,"children":30885},{"style":545},[30886],{"type":420,"value":20190},{"type":415,"tag":532,"props":30888,"children":30889},{"style":551},[30890],{"type":420,"value":432},{"type":415,"tag":532,"props":30892,"children":30893},{"style":545},[30894],{"type":420,"value":20199},{"type":415,"tag":532,"props":30896,"children":30897},{"style":551},[30898],{"type":420,"value":432},{"type":415,"tag":532,"props":30900,"children":30901},{"style":545},[30902],{"type":420,"value":20241},{"type":415,"tag":532,"props":30904,"children":30905},{"style":551},[30906],{"type":420,"value":4502},{"type":415,"tag":532,"props":30908,"children":30909},{"style":551},[30910],{"type":420,"value":1099},{"type":415,"tag":532,"props":30912,"children":30913},{"style":551},[30914],{"type":420,"value":3276},{"type":415,"tag":532,"props":30916,"children":30917},{"style":631},[30918],{"type":420,"value":30919}," StorageAccountArgs\n",{"type":415,"tag":532,"props":30921,"children":30922},{"class":534,"line":566},[30923],{"type":415,"tag":532,"props":30924,"children":30925},{"style":551},[30926],{"type":420,"value":764},{"type":415,"tag":532,"props":30928,"children":30929},{"class":534,"line":583},[30930,30934,30938,30942,30946,30950],{"type":415,"tag":532,"props":30931,"children":30932},{"style":545},[30933],{"type":420,"value":20394},{"type":415,"tag":532,"props":30935,"children":30936},{"style":551},[30937],{"type":420,"value":1134},{"type":415,"tag":532,"props":30939,"children":30940},{"style":545},[30941],{"type":420,"value":20155},{"type":415,"tag":532,"props":30943,"children":30944},{"style":551},[30945],{"type":420,"value":432},{"type":415,"tag":532,"props":30947,"children":30948},{"style":545},[30949],{"type":420,"value":1344},{"type":415,"tag":532,"props":30951,"children":30952},{"style":551},[30953],{"type":420,"value":7400},{"type":415,"tag":532,"props":30955,"children":30956},{"class":534,"line":617},[30957,30961,30965,30969],{"type":415,"tag":532,"props":30958,"children":30959},{"style":545},[30960],{"type":420,"value":20459},{"type":415,"tag":532,"props":30962,"children":30963},{"style":551},[30964],{"type":420,"value":1134},{"type":415,"tag":532,"props":30966,"children":30967},{"style":551},[30968],{"type":420,"value":3276},{"type":415,"tag":532,"props":30970,"children":30971},{"style":631},[30972],{"type":420,"value":23528},{"type":415,"tag":532,"props":30974,"children":30975},{"class":534,"line":627},[30976],{"type":415,"tag":532,"props":30977,"children":30978},{"style":551},[30979],{"type":420,"value":1121},{"type":415,"tag":532,"props":30981,"children":30982},{"class":534,"line":677},[30983,30987,30991,30996,31000],{"type":415,"tag":532,"props":30984,"children":30985},{"style":545},[30986],{"type":420,"value":20528},{"type":415,"tag":532,"props":30988,"children":30989},{"style":551},[30990],{"type":420,"value":1134},{"type":415,"tag":532,"props":30992,"children":30993},{"style":545},[30994],{"type":420,"value":30995}," SkuName",{"type":415,"tag":532,"props":30997,"children":30998},{"style":551},[30999],{"type":420,"value":432},{"type":415,"tag":532,"props":31001,"children":31002},{"style":545},[31003],{"type":420,"value":31004},"Standard_LRS\n",{"type":415,"tag":532,"props":31006,"children":31007},{"class":534,"line":719},[31008],{"type":415,"tag":532,"props":31009,"children":31010},{"style":551},[31011],{"type":420,"value":7650},{"type":415,"tag":532,"props":31013,"children":31014},{"class":534,"line":758},[31015,31019,31023,31028,31032],{"type":415,"tag":532,"props":31016,"children":31017},{"style":545},[31018],{"type":420,"value":20426},{"type":415,"tag":532,"props":31020,"children":31021},{"style":551},[31022],{"type":420,"value":1134},{"type":415,"tag":532,"props":31024,"children":31025},{"style":545},[31026],{"type":420,"value":31027}," Kind",{"type":415,"tag":532,"props":31029,"children":31030},{"style":551},[31031],{"type":420,"value":432},{"type":415,"tag":532,"props":31033,"children":31034},{"style":545},[31035],{"type":420,"value":31036},"StorageV2\n",{"type":415,"tag":532,"props":31038,"children":31039},{"class":534,"line":767},[31040],{"type":415,"tag":532,"props":31041,"children":31042},{"style":551},[31043],{"type":420,"value":856},{"type":415,"tag":416,"props":31045,"children":31046},{},[31047],{"type":420,"value":31048},"This is the way of declaring a consumption App Service Plan:",{"type":415,"tag":523,"props":31050,"children":31052},{"className":525,"code":31051,"language":326,"meta":401,"style":401},"var appServicePlan = new AppServicePlan($\"plan-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\", new AppServicePlanArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    Kind = \"Windows\",\n    Sku = new SkuDescriptionArgs\n    {\n        Tier = \"Dynamic\",\n        Name = \"Y1\"\n    }\n});\n",[31053],{"type":415,"tag":468,"props":31054,"children":31055},{"__ignoreMap":401},[31056,31164,31171,31198,31226,31246,31253,31281,31305,31312],{"type":415,"tag":532,"props":31057,"children":31058},{"class":534,"line":535},[31059,31063,31067,31071,31075,31079,31083,31087,31091,31095,31099,31103,31107,31111,31115,31119,31123,31127,31131,31135,31139,31143,31147,31151,31155,31159],{"type":415,"tag":532,"props":31060,"children":31061},{"style":631},[31062],{"type":420,"value":634},{"type":415,"tag":532,"props":31064,"children":31065},{"style":631},[31066],{"type":420,"value":20272},{"type":415,"tag":532,"props":31068,"children":31069},{"style":551},[31070],{"type":420,"value":644},{"type":415,"tag":532,"props":31072,"children":31073},{"style":551},[31074],{"type":420,"value":3276},{"type":415,"tag":532,"props":31076,"children":31077},{"style":631},[31078],{"type":420,"value":20285},{"type":415,"tag":532,"props":31080,"children":31081},{"style":551},[31082],{"type":420,"value":664},{"type":415,"tag":532,"props":31084,"children":31085},{"style":551},[31086],{"type":420,"value":8738},{"type":415,"tag":532,"props":31088,"children":31089},{"style":804},[31090],{"type":420,"value":20298},{"type":415,"tag":532,"props":31092,"children":31093},{"style":551},[31094],{"type":420,"value":8748},{"type":415,"tag":532,"props":31096,"children":31097},{"style":545},[31098],{"type":420,"value":20190},{"type":415,"tag":532,"props":31100,"children":31101},{"style":551},[31102],{"type":420,"value":432},{"type":415,"tag":532,"props":31104,"children":31105},{"style":545},[31106],{"type":420,"value":20199},{"type":415,"tag":532,"props":31108,"children":31109},{"style":551},[31110],{"type":420,"value":432},{"type":415,"tag":532,"props":31112,"children":31113},{"style":545},[31114],{"type":420,"value":20208},{"type":415,"tag":532,"props":31116,"children":31117},{"style":551},[31118],{"type":420,"value":4864},{"type":415,"tag":532,"props":31120,"children":31121},{"style":804},[31122],{"type":420,"value":4216},{"type":415,"tag":532,"props":31124,"children":31125},{"style":551},[31126],{"type":420,"value":8748},{"type":415,"tag":532,"props":31128,"children":31129},{"style":545},[31130],{"type":420,"value":20190},{"type":415,"tag":532,"props":31132,"children":31133},{"style":551},[31134],{"type":420,"value":432},{"type":415,"tag":532,"props":31136,"children":31137},{"style":545},[31138],{"type":420,"value":20199},{"type":415,"tag":532,"props":31140,"children":31141},{"style":551},[31142],{"type":420,"value":432},{"type":415,"tag":532,"props":31144,"children":31145},{"style":545},[31146],{"type":420,"value":20241},{"type":415,"tag":532,"props":31148,"children":31149},{"style":551},[31150],{"type":420,"value":4502},{"type":415,"tag":532,"props":31152,"children":31153},{"style":551},[31154],{"type":420,"value":1099},{"type":415,"tag":532,"props":31156,"children":31157},{"style":551},[31158],{"type":420,"value":3276},{"type":415,"tag":532,"props":31160,"children":31161},{"style":631},[31162],{"type":420,"value":31163}," AppServicePlanArgs\n",{"type":415,"tag":532,"props":31165,"children":31166},{"class":534,"line":566},[31167],{"type":415,"tag":532,"props":31168,"children":31169},{"style":551},[31170],{"type":420,"value":764},{"type":415,"tag":532,"props":31172,"children":31173},{"class":534,"line":583},[31174,31178,31182,31186,31190,31194],{"type":415,"tag":532,"props":31175,"children":31176},{"style":545},[31177],{"type":420,"value":20394},{"type":415,"tag":532,"props":31179,"children":31180},{"style":551},[31181],{"type":420,"value":1134},{"type":415,"tag":532,"props":31183,"children":31184},{"style":545},[31185],{"type":420,"value":20155},{"type":415,"tag":532,"props":31187,"children":31188},{"style":551},[31189],{"type":420,"value":432},{"type":415,"tag":532,"props":31191,"children":31192},{"style":545},[31193],{"type":420,"value":1344},{"type":415,"tag":532,"props":31195,"children":31196},{"style":551},[31197],{"type":420,"value":7400},{"type":415,"tag":532,"props":31199,"children":31200},{"class":534,"line":617},[31201,31205,31209,31213,31218,31222],{"type":415,"tag":532,"props":31202,"children":31203},{"style":545},[31204],{"type":420,"value":20426},{"type":415,"tag":532,"props":31206,"children":31207},{"style":551},[31208],{"type":420,"value":1134},{"type":415,"tag":532,"props":31210,"children":31211},{"style":551},[31212],{"type":420,"value":4041},{"type":415,"tag":532,"props":31214,"children":31215},{"style":804},[31216],{"type":420,"value":31217},"Windows",{"type":415,"tag":532,"props":31219,"children":31220},{"style":551},[31221],{"type":420,"value":801},{"type":415,"tag":532,"props":31223,"children":31224},{"style":551},[31225],{"type":420,"value":7400},{"type":415,"tag":532,"props":31227,"children":31228},{"class":534,"line":627},[31229,31233,31237,31241],{"type":415,"tag":532,"props":31230,"children":31231},{"style":545},[31232],{"type":420,"value":20459},{"type":415,"tag":532,"props":31234,"children":31235},{"style":551},[31236],{"type":420,"value":1134},{"type":415,"tag":532,"props":31238,"children":31239},{"style":551},[31240],{"type":420,"value":3276},{"type":415,"tag":532,"props":31242,"children":31243},{"style":631},[31244],{"type":420,"value":31245}," SkuDescriptionArgs\n",{"type":415,"tag":532,"props":31247,"children":31248},{"class":534,"line":677},[31249],{"type":415,"tag":532,"props":31250,"children":31251},{"style":551},[31252],{"type":420,"value":1121},{"type":415,"tag":532,"props":31254,"children":31255},{"class":534,"line":719},[31256,31260,31264,31268,31273,31277],{"type":415,"tag":532,"props":31257,"children":31258},{"style":545},[31259],{"type":420,"value":20495},{"type":415,"tag":532,"props":31261,"children":31262},{"style":551},[31263],{"type":420,"value":1134},{"type":415,"tag":532,"props":31265,"children":31266},{"style":551},[31267],{"type":420,"value":4041},{"type":415,"tag":532,"props":31269,"children":31270},{"style":804},[31271],{"type":420,"value":31272},"Dynamic",{"type":415,"tag":532,"props":31274,"children":31275},{"style":551},[31276],{"type":420,"value":801},{"type":415,"tag":532,"props":31278,"children":31279},{"style":551},[31280],{"type":420,"value":7400},{"type":415,"tag":532,"props":31282,"children":31283},{"class":534,"line":758},[31284,31288,31292,31296,31301],{"type":415,"tag":532,"props":31285,"children":31286},{"style":545},[31287],{"type":420,"value":20528},{"type":415,"tag":532,"props":31289,"children":31290},{"style":551},[31291],{"type":420,"value":1134},{"type":415,"tag":532,"props":31293,"children":31294},{"style":551},[31295],{"type":420,"value":4041},{"type":415,"tag":532,"props":31297,"children":31298},{"style":804},[31299],{"type":420,"value":31300},"Y1",{"type":415,"tag":532,"props":31302,"children":31303},{"style":551},[31304],{"type":420,"value":4051},{"type":415,"tag":532,"props":31306,"children":31307},{"class":534,"line":767},[31308],{"type":415,"tag":532,"props":31309,"children":31310},{"style":551},[31311],{"type":420,"value":1170},{"type":415,"tag":532,"props":31313,"children":31314},{"class":534,"line":819},[31315],{"type":415,"tag":532,"props":31316,"children":31317},{"style":551},[31318],{"type":420,"value":856},{"type":415,"tag":416,"props":31320,"children":31321},{},[31322,31324,31329],{"type":420,"value":31323},"In Azure APIs, a FunctionApp is just a WebApp of a special kind \"FunctionApp\". You can notice that we enabled the System Managed Identity on the Function App by setting the Identity property. And as expected we added an app setting ",{"type":415,"tag":468,"props":31325,"children":31327},{"className":31326},[],[31328],{"type":420,"value":30606},{"type":420,"value":31330}," whose value is the name of the storage account.",{"type":415,"tag":523,"props":31332,"children":31334},{"className":525,"code":31333,"language":326,"meta":401,"style":401},"var functionApp = new WebApp($\"func-nosecret-{Deployment.Instance.StackName}\", new WebAppArgs\n{\n    Kind = \"FunctionApp\",\n    ResourceGroupName = resourceGroup.Name,\n    ServerFarmId = appServicePlan.Id,\n    Identity = new ManagedServiceIdentityArgs\n    {\n        Type = Pulumi.AzureNative.Web.ManagedServiceIdentityType.SystemAssigned\n    },\n    SiteConfig = new SiteConfigArgs\n    {\n        AppSettings = new[]\n        {\n            new NameValuePairArgs\n            {\n                Name = \"runtime\",\n                Value = \"dotnet\",\n            },\n            new NameValuePairArgs\n            {\n                Name = \"FUNCTIONS_WORKER_RUNTIME\",\n                Value = \"dotnet\",\n            },\n            new NameValuePairArgs\n            {\n                Name = \"FUNCTIONS_EXTENSION_VERSION\",\n                Value = \"~4\"\n            },\n            new NameValuePairArgs\n            {\n                Name = \"AzureWebJobsStorage__accountName\",\n                Value = storageAccount.Name\n            }\n        },\n    },\n});\n",[31335],{"type":415,"tag":468,"props":31336,"children":31337},{"__ignoreMap":401},[31338,31416,31423,31451,31478,31505,31526,31533,31586,31593,31614,31621,31638,31645,31657,31664,31693,31722,31730,31741,31748,31776,31803,31810,31821,31828,31856,31880,31887,31898,31905,31932,31955,31963,31971,31978],{"type":415,"tag":532,"props":31339,"children":31340},{"class":534,"line":535},[31341,31345,31350,31354,31358,31362,31366,31370,31375,31379,31383,31387,31391,31395,31399,31403,31407,31411],{"type":415,"tag":532,"props":31342,"children":31343},{"style":631},[31344],{"type":420,"value":634},{"type":415,"tag":532,"props":31346,"children":31347},{"style":631},[31348],{"type":420,"value":31349}," functionApp",{"type":415,"tag":532,"props":31351,"children":31352},{"style":551},[31353],{"type":420,"value":644},{"type":415,"tag":532,"props":31355,"children":31356},{"style":551},[31357],{"type":420,"value":3276},{"type":415,"tag":532,"props":31359,"children":31360},{"style":631},[31361],{"type":420,"value":20609},{"type":415,"tag":532,"props":31363,"children":31364},{"style":551},[31365],{"type":420,"value":664},{"type":415,"tag":532,"props":31367,"children":31368},{"style":551},[31369],{"type":420,"value":8738},{"type":415,"tag":532,"props":31371,"children":31372},{"style":804},[31373],{"type":420,"value":31374},"func-nosecret-",{"type":415,"tag":532,"props":31376,"children":31377},{"style":551},[31378],{"type":420,"value":8748},{"type":415,"tag":532,"props":31380,"children":31381},{"style":545},[31382],{"type":420,"value":20190},{"type":415,"tag":532,"props":31384,"children":31385},{"style":551},[31386],{"type":420,"value":432},{"type":415,"tag":532,"props":31388,"children":31389},{"style":545},[31390],{"type":420,"value":20199},{"type":415,"tag":532,"props":31392,"children":31393},{"style":551},[31394],{"type":420,"value":432},{"type":415,"tag":532,"props":31396,"children":31397},{"style":545},[31398],{"type":420,"value":20241},{"type":415,"tag":532,"props":31400,"children":31401},{"style":551},[31402],{"type":420,"value":4502},{"type":415,"tag":532,"props":31404,"children":31405},{"style":551},[31406],{"type":420,"value":1099},{"type":415,"tag":532,"props":31408,"children":31409},{"style":551},[31410],{"type":420,"value":3276},{"type":415,"tag":532,"props":31412,"children":31413},{"style":631},[31414],{"type":420,"value":31415}," WebAppArgs\n",{"type":415,"tag":532,"props":31417,"children":31418},{"class":534,"line":566},[31419],{"type":415,"tag":532,"props":31420,"children":31421},{"style":551},[31422],{"type":420,"value":764},{"type":415,"tag":532,"props":31424,"children":31425},{"class":534,"line":583},[31426,31430,31434,31438,31443,31447],{"type":415,"tag":532,"props":31427,"children":31428},{"style":545},[31429],{"type":420,"value":20426},{"type":415,"tag":532,"props":31431,"children":31432},{"style":551},[31433],{"type":420,"value":1134},{"type":415,"tag":532,"props":31435,"children":31436},{"style":551},[31437],{"type":420,"value":4041},{"type":415,"tag":532,"props":31439,"children":31440},{"style":804},[31441],{"type":420,"value":31442},"FunctionApp",{"type":415,"tag":532,"props":31444,"children":31445},{"style":551},[31446],{"type":420,"value":801},{"type":415,"tag":532,"props":31448,"children":31449},{"style":551},[31450],{"type":420,"value":7400},{"type":415,"tag":532,"props":31452,"children":31453},{"class":534,"line":617},[31454,31458,31462,31466,31470,31474],{"type":415,"tag":532,"props":31455,"children":31456},{"style":545},[31457],{"type":420,"value":20394},{"type":415,"tag":532,"props":31459,"children":31460},{"style":551},[31461],{"type":420,"value":1134},{"type":415,"tag":532,"props":31463,"children":31464},{"style":545},[31465],{"type":420,"value":20155},{"type":415,"tag":532,"props":31467,"children":31468},{"style":551},[31469],{"type":420,"value":432},{"type":415,"tag":532,"props":31471,"children":31472},{"style":545},[31473],{"type":420,"value":1344},{"type":415,"tag":532,"props":31475,"children":31476},{"style":551},[31477],{"type":420,"value":7400},{"type":415,"tag":532,"props":31479,"children":31480},{"class":534,"line":627},[31481,31485,31489,31493,31497,31501],{"type":415,"tag":532,"props":31482,"children":31483},{"style":545},[31484],{"type":420,"value":20750},{"type":415,"tag":532,"props":31486,"children":31487},{"style":551},[31488],{"type":420,"value":1134},{"type":415,"tag":532,"props":31490,"children":31491},{"style":545},[31492],{"type":420,"value":20272},{"type":415,"tag":532,"props":31494,"children":31495},{"style":551},[31496],{"type":420,"value":432},{"type":415,"tag":532,"props":31498,"children":31499},{"style":545},[31500],{"type":420,"value":7750},{"type":415,"tag":532,"props":31502,"children":31503},{"style":551},[31504],{"type":420,"value":7400},{"type":415,"tag":532,"props":31506,"children":31507},{"class":534,"line":677},[31508,31513,31517,31521],{"type":415,"tag":532,"props":31509,"children":31510},{"style":545},[31511],{"type":420,"value":31512},"    Identity ",{"type":415,"tag":532,"props":31514,"children":31515},{"style":551},[31516],{"type":420,"value":1134},{"type":415,"tag":532,"props":31518,"children":31519},{"style":551},[31520],{"type":420,"value":3276},{"type":415,"tag":532,"props":31522,"children":31523},{"style":631},[31524],{"type":420,"value":31525}," ManagedServiceIdentityArgs\n",{"type":415,"tag":532,"props":31527,"children":31528},{"class":534,"line":719},[31529],{"type":415,"tag":532,"props":31530,"children":31531},{"style":551},[31532],{"type":420,"value":1121},{"type":415,"tag":532,"props":31534,"children":31535},{"class":534,"line":758},[31536,31541,31545,31550,31554,31559,31563,31568,31572,31577,31581],{"type":415,"tag":532,"props":31537,"children":31538},{"style":545},[31539],{"type":420,"value":31540},"        Type ",{"type":415,"tag":532,"props":31542,"children":31543},{"style":551},[31544],{"type":420,"value":1134},{"type":415,"tag":532,"props":31546,"children":31547},{"style":545},[31548],{"type":420,"value":31549}," Pulumi",{"type":415,"tag":532,"props":31551,"children":31552},{"style":551},[31553],{"type":420,"value":432},{"type":415,"tag":532,"props":31555,"children":31556},{"style":545},[31557],{"type":420,"value":31558},"AzureNative",{"type":415,"tag":532,"props":31560,"children":31561},{"style":551},[31562],{"type":420,"value":432},{"type":415,"tag":532,"props":31564,"children":31565},{"style":545},[31566],{"type":420,"value":31567},"Web",{"type":415,"tag":532,"props":31569,"children":31570},{"style":551},[31571],{"type":420,"value":432},{"type":415,"tag":532,"props":31573,"children":31574},{"style":545},[31575],{"type":420,"value":31576},"ManagedServiceIdentityType",{"type":415,"tag":532,"props":31578,"children":31579},{"style":551},[31580],{"type":420,"value":432},{"type":415,"tag":532,"props":31582,"children":31583},{"style":545},[31584],{"type":420,"value":31585},"SystemAssigned\n",{"type":415,"tag":532,"props":31587,"children":31588},{"class":534,"line":767},[31589],{"type":415,"tag":532,"props":31590,"children":31591},{"style":551},[31592],{"type":420,"value":7650},{"type":415,"tag":532,"props":31594,"children":31595},{"class":534,"line":819},[31596,31601,31605,31609],{"type":415,"tag":532,"props":31597,"children":31598},{"style":545},[31599],{"type":420,"value":31600},"    SiteConfig ",{"type":415,"tag":532,"props":31602,"children":31603},{"style":551},[31604],{"type":420,"value":1134},{"type":415,"tag":532,"props":31606,"children":31607},{"style":551},[31608],{"type":420,"value":3276},{"type":415,"tag":532,"props":31610,"children":31611},{"style":631},[31612],{"type":420,"value":31613}," SiteConfigArgs\n",{"type":415,"tag":532,"props":31615,"children":31616},{"class":534,"line":850},[31617],{"type":415,"tag":532,"props":31618,"children":31619},{"style":551},[31620],{"type":420,"value":1121},{"type":415,"tag":532,"props":31622,"children":31623},{"class":534,"line":859},[31624,31629,31633],{"type":415,"tag":532,"props":31625,"children":31626},{"style":545},[31627],{"type":420,"value":31628},"        AppSettings ",{"type":415,"tag":532,"props":31630,"children":31631},{"style":551},[31632],{"type":420,"value":1134},{"type":415,"tag":532,"props":31634,"children":31635},{"style":551},[31636],{"type":420,"value":31637}," new[]\n",{"type":415,"tag":532,"props":31639,"children":31640},{"class":534,"line":867},[31641],{"type":415,"tag":532,"props":31642,"children":31643},{"style":551},[31644],{"type":420,"value":1308},{"type":415,"tag":532,"props":31646,"children":31647},{"class":534,"line":902},[31648,31652],{"type":415,"tag":532,"props":31649,"children":31650},{"style":551},[31651],{"type":420,"value":22394},{"type":415,"tag":532,"props":31653,"children":31654},{"style":631},[31655],{"type":420,"value":31656}," NameValuePairArgs\n",{"type":415,"tag":532,"props":31658,"children":31659},{"class":534,"line":1302},[31660],{"type":415,"tag":532,"props":31661,"children":31662},{"style":551},[31663],{"type":420,"value":30133},{"type":415,"tag":532,"props":31665,"children":31666},{"class":534,"line":1311},[31667,31672,31676,31680,31685,31689],{"type":415,"tag":532,"props":31668,"children":31669},{"style":545},[31670],{"type":420,"value":31671},"                Name ",{"type":415,"tag":532,"props":31673,"children":31674},{"style":551},[31675],{"type":420,"value":1134},{"type":415,"tag":532,"props":31677,"children":31678},{"style":551},[31679],{"type":420,"value":4041},{"type":415,"tag":532,"props":31681,"children":31682},{"style":804},[31683],{"type":420,"value":31684},"runtime",{"type":415,"tag":532,"props":31686,"children":31687},{"style":551},[31688],{"type":420,"value":801},{"type":415,"tag":532,"props":31690,"children":31691},{"style":551},[31692],{"type":420,"value":7400},{"type":415,"tag":532,"props":31694,"children":31695},{"class":534,"line":1356},[31696,31701,31705,31709,31714,31718],{"type":415,"tag":532,"props":31697,"children":31698},{"style":545},[31699],{"type":420,"value":31700},"                Value ",{"type":415,"tag":532,"props":31702,"children":31703},{"style":551},[31704],{"type":420,"value":1134},{"type":415,"tag":532,"props":31706,"children":31707},{"style":551},[31708],{"type":420,"value":4041},{"type":415,"tag":532,"props":31710,"children":31711},{"style":804},[31712],{"type":420,"value":31713},"dotnet",{"type":415,"tag":532,"props":31715,"children":31716},{"style":551},[31717],{"type":420,"value":801},{"type":415,"tag":532,"props":31719,"children":31720},{"style":551},[31721],{"type":420,"value":7400},{"type":415,"tag":532,"props":31723,"children":31724},{"class":534,"line":1365},[31725],{"type":415,"tag":532,"props":31726,"children":31727},{"style":551},[31728],{"type":420,"value":31729},"            },\n",{"type":415,"tag":532,"props":31731,"children":31732},{"class":534,"line":1373},[31733,31737],{"type":415,"tag":532,"props":31734,"children":31735},{"style":551},[31736],{"type":420,"value":22394},{"type":415,"tag":532,"props":31738,"children":31739},{"style":631},[31740],{"type":420,"value":31656},{"type":415,"tag":532,"props":31742,"children":31743},{"class":534,"line":3825},[31744],{"type":415,"tag":532,"props":31745,"children":31746},{"style":551},[31747],{"type":420,"value":30133},{"type":415,"tag":532,"props":31749,"children":31750},{"class":534,"line":3843},[31751,31755,31759,31763,31768,31772],{"type":415,"tag":532,"props":31752,"children":31753},{"style":545},[31754],{"type":420,"value":31671},{"type":415,"tag":532,"props":31756,"children":31757},{"style":551},[31758],{"type":420,"value":1134},{"type":415,"tag":532,"props":31760,"children":31761},{"style":551},[31762],{"type":420,"value":4041},{"type":415,"tag":532,"props":31764,"children":31765},{"style":804},[31766],{"type":420,"value":31767},"FUNCTIONS_WORKER_RUNTIME",{"type":415,"tag":532,"props":31769,"children":31770},{"style":551},[31771],{"type":420,"value":801},{"type":415,"tag":532,"props":31773,"children":31774},{"style":551},[31775],{"type":420,"value":7400},{"type":415,"tag":532,"props":31777,"children":31778},{"class":534,"line":3852},[31779,31783,31787,31791,31795,31799],{"type":415,"tag":532,"props":31780,"children":31781},{"style":545},[31782],{"type":420,"value":31700},{"type":415,"tag":532,"props":31784,"children":31785},{"style":551},[31786],{"type":420,"value":1134},{"type":415,"tag":532,"props":31788,"children":31789},{"style":551},[31790],{"type":420,"value":4041},{"type":415,"tag":532,"props":31792,"children":31793},{"style":804},[31794],{"type":420,"value":31713},{"type":415,"tag":532,"props":31796,"children":31797},{"style":551},[31798],{"type":420,"value":801},{"type":415,"tag":532,"props":31800,"children":31801},{"style":551},[31802],{"type":420,"value":7400},{"type":415,"tag":532,"props":31804,"children":31805},{"class":534,"line":5941},[31806],{"type":415,"tag":532,"props":31807,"children":31808},{"style":551},[31809],{"type":420,"value":31729},{"type":415,"tag":532,"props":31811,"children":31812},{"class":534,"line":6053},[31813,31817],{"type":415,"tag":532,"props":31814,"children":31815},{"style":551},[31816],{"type":420,"value":22394},{"type":415,"tag":532,"props":31818,"children":31819},{"style":631},[31820],{"type":420,"value":31656},{"type":415,"tag":532,"props":31822,"children":31823},{"class":534,"line":6061},[31824],{"type":415,"tag":532,"props":31825,"children":31826},{"style":551},[31827],{"type":420,"value":30133},{"type":415,"tag":532,"props":31829,"children":31830},{"class":534,"line":6070},[31831,31835,31839,31843,31848,31852],{"type":415,"tag":532,"props":31832,"children":31833},{"style":545},[31834],{"type":420,"value":31671},{"type":415,"tag":532,"props":31836,"children":31837},{"style":551},[31838],{"type":420,"value":1134},{"type":415,"tag":532,"props":31840,"children":31841},{"style":551},[31842],{"type":420,"value":4041},{"type":415,"tag":532,"props":31844,"children":31845},{"style":804},[31846],{"type":420,"value":31847},"FUNCTIONS_EXTENSION_VERSION",{"type":415,"tag":532,"props":31849,"children":31850},{"style":551},[31851],{"type":420,"value":801},{"type":415,"tag":532,"props":31853,"children":31854},{"style":551},[31855],{"type":420,"value":7400},{"type":415,"tag":532,"props":31857,"children":31858},{"class":534,"line":6094},[31859,31863,31867,31871,31876],{"type":415,"tag":532,"props":31860,"children":31861},{"style":545},[31862],{"type":420,"value":31700},{"type":415,"tag":532,"props":31864,"children":31865},{"style":551},[31866],{"type":420,"value":1134},{"type":415,"tag":532,"props":31868,"children":31869},{"style":551},[31870],{"type":420,"value":4041},{"type":415,"tag":532,"props":31872,"children":31873},{"style":804},[31874],{"type":420,"value":31875},"~4",{"type":415,"tag":532,"props":31877,"children":31878},{"style":551},[31879],{"type":420,"value":4051},{"type":415,"tag":532,"props":31881,"children":31882},{"class":534,"line":6118},[31883],{"type":415,"tag":532,"props":31884,"children":31885},{"style":551},[31886],{"type":420,"value":31729},{"type":415,"tag":532,"props":31888,"children":31889},{"class":534,"line":6142},[31890,31894],{"type":415,"tag":532,"props":31891,"children":31892},{"style":551},[31893],{"type":420,"value":22394},{"type":415,"tag":532,"props":31895,"children":31896},{"style":631},[31897],{"type":420,"value":31656},{"type":415,"tag":532,"props":31899,"children":31900},{"class":534,"line":6182},[31901],{"type":415,"tag":532,"props":31902,"children":31903},{"style":551},[31904],{"type":420,"value":30133},{"type":415,"tag":532,"props":31906,"children":31907},{"class":534,"line":6214},[31908,31912,31916,31920,31924,31928],{"type":415,"tag":532,"props":31909,"children":31910},{"style":545},[31911],{"type":420,"value":31671},{"type":415,"tag":532,"props":31913,"children":31914},{"style":551},[31915],{"type":420,"value":1134},{"type":415,"tag":532,"props":31917,"children":31918},{"style":551},[31919],{"type":420,"value":4041},{"type":415,"tag":532,"props":31921,"children":31922},{"style":804},[31923],{"type":420,"value":30606},{"type":415,"tag":532,"props":31925,"children":31926},{"style":551},[31927],{"type":420,"value":801},{"type":415,"tag":532,"props":31929,"children":31930},{"style":551},[31931],{"type":420,"value":7400},{"type":415,"tag":532,"props":31933,"children":31934},{"class":534,"line":6234},[31935,31939,31943,31947,31951],{"type":415,"tag":532,"props":31936,"children":31937},{"style":545},[31938],{"type":420,"value":31700},{"type":415,"tag":532,"props":31940,"children":31941},{"style":551},[31942],{"type":420,"value":1134},{"type":415,"tag":532,"props":31944,"children":31945},{"style":545},[31946],{"type":420,"value":30852},{"type":415,"tag":532,"props":31948,"children":31949},{"style":551},[31950],{"type":420,"value":432},{"type":415,"tag":532,"props":31952,"children":31953},{"style":545},[31954],{"type":420,"value":7779},{"type":415,"tag":532,"props":31956,"children":31957},{"class":534,"line":6250},[31958],{"type":415,"tag":532,"props":31959,"children":31960},{"style":551},[31961],{"type":420,"value":31962},"            }\n",{"type":415,"tag":532,"props":31964,"children":31965},{"class":534,"line":6258},[31966],{"type":415,"tag":532,"props":31967,"children":31968},{"style":551},[31969],{"type":420,"value":31970},"        },\n",{"type":415,"tag":532,"props":31972,"children":31973},{"class":534,"line":6266},[31974],{"type":415,"tag":532,"props":31975,"children":31976},{"style":551},[31977],{"type":420,"value":7650},{"type":415,"tag":532,"props":31979,"children":31980},{"class":534,"line":6274},[31981],{"type":415,"tag":532,"props":31982,"children":31983},{"style":551},[31984],{"type":420,"value":856},{"type":415,"tag":416,"props":31986,"children":31987},{},[31988,31990,31997,31999,32005],{"type":420,"value":31989},"The last thing to do is to assign the role Storage Blob Data Owner to the Function App. To find the resource id I needed I looked at ",{"type":415,"tag":423,"props":31991,"children":31994},{"href":31992,"rel":31993},"https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles",[427],[31995],{"type":420,"value":31996},"this page of the Microsoft documentation",{"type":420,"value":31998}," but I hope that in the future Pulumi will provide an ",{"type":415,"tag":468,"props":32000,"children":32002},{"className":32001},[],[32003],{"type":420,"value":32004},"enum",{"type":420,"value":32006}," or something like that with the possible values to make that easier to find and assign.",{"type":415,"tag":523,"props":32008,"children":32010},{"className":525,"code":32009,"language":326,"meta":401,"style":401},"var storageBlobDataOwnerRole = new RoleAssignment(\"storageBlobDataOwner\", new RoleAssignmentArgs\n{\n    PrincipalId = functionApp.Identity.Apply(i => i.PrincipalId),\n    PrincipalType = PrincipalType.ServicePrincipal,\n    RoleDefinitionId = \"/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b\",\n    Scope = storageAccount.Id\n});\n",[32011],{"type":415,"tag":468,"props":32012,"children":32013},{"__ignoreMap":401},[32014,32068,32075,32138,32166,32194,32217],{"type":415,"tag":532,"props":32015,"children":32016},{"class":534,"line":535},[32017,32021,32026,32030,32034,32038,32042,32046,32051,32055,32059,32063],{"type":415,"tag":532,"props":32018,"children":32019},{"style":631},[32020],{"type":420,"value":634},{"type":415,"tag":532,"props":32022,"children":32023},{"style":631},[32024],{"type":420,"value":32025}," storageBlobDataOwnerRole",{"type":415,"tag":532,"props":32027,"children":32028},{"style":551},[32029],{"type":420,"value":644},{"type":415,"tag":532,"props":32031,"children":32032},{"style":551},[32033],{"type":420,"value":3276},{"type":415,"tag":532,"props":32035,"children":32036},{"style":631},[32037],{"type":420,"value":9147},{"type":415,"tag":532,"props":32039,"children":32040},{"style":551},[32041],{"type":420,"value":664},{"type":415,"tag":532,"props":32043,"children":32044},{"style":551},[32045],{"type":420,"value":801},{"type":415,"tag":532,"props":32047,"children":32048},{"style":804},[32049],{"type":420,"value":32050},"storageBlobDataOwner",{"type":415,"tag":532,"props":32052,"children":32053},{"style":551},[32054],{"type":420,"value":801},{"type":415,"tag":532,"props":32056,"children":32057},{"style":551},[32058],{"type":420,"value":1099},{"type":415,"tag":532,"props":32060,"children":32061},{"style":551},[32062],{"type":420,"value":3276},{"type":415,"tag":532,"props":32064,"children":32065},{"style":631},[32066],{"type":420,"value":32067}," RoleAssignmentArgs\n",{"type":415,"tag":532,"props":32069,"children":32070},{"class":534,"line":566},[32071],{"type":415,"tag":532,"props":32072,"children":32073},{"style":551},[32074],{"type":420,"value":764},{"type":415,"tag":532,"props":32076,"children":32077},{"class":534,"line":583},[32078,32083,32087,32091,32095,32099,32103,32107,32111,32116,32120,32125,32129,32134],{"type":415,"tag":532,"props":32079,"children":32080},{"style":545},[32081],{"type":420,"value":32082},"    PrincipalId ",{"type":415,"tag":532,"props":32084,"children":32085},{"style":551},[32086],{"type":420,"value":1134},{"type":415,"tag":532,"props":32088,"children":32089},{"style":545},[32090],{"type":420,"value":31349},{"type":415,"tag":532,"props":32092,"children":32093},{"style":551},[32094],{"type":420,"value":432},{"type":415,"tag":532,"props":32096,"children":32097},{"style":545},[32098],{"type":420,"value":558},{"type":415,"tag":532,"props":32100,"children":32101},{"style":551},[32102],{"type":420,"value":432},{"type":415,"tag":532,"props":32104,"children":32105},{"style":656},[32106],{"type":420,"value":8485},{"type":415,"tag":532,"props":32108,"children":32109},{"style":551},[32110],{"type":420,"value":664},{"type":415,"tag":532,"props":32112,"children":32113},{"style":631},[32114],{"type":420,"value":32115},"i",{"type":415,"tag":532,"props":32117,"children":32118},{"style":551},[32119],{"type":420,"value":8499},{"type":415,"tag":532,"props":32121,"children":32122},{"style":545},[32123],{"type":420,"value":32124}," i",{"type":415,"tag":532,"props":32126,"children":32127},{"style":551},[32128],{"type":420,"value":432},{"type":415,"tag":532,"props":32130,"children":32131},{"style":545},[32132],{"type":420,"value":32133},"PrincipalId",{"type":415,"tag":532,"props":32135,"children":32136},{"style":551},[32137],{"type":420,"value":10087},{"type":415,"tag":532,"props":32139,"children":32140},{"class":534,"line":617},[32141,32146,32150,32154,32158,32162],{"type":415,"tag":532,"props":32142,"children":32143},{"style":545},[32144],{"type":420,"value":32145},"    PrincipalType ",{"type":415,"tag":532,"props":32147,"children":32148},{"style":551},[32149],{"type":420,"value":1134},{"type":415,"tag":532,"props":32151,"children":32152},{"style":545},[32153],{"type":420,"value":9224},{"type":415,"tag":532,"props":32155,"children":32156},{"style":551},[32157],{"type":420,"value":432},{"type":415,"tag":532,"props":32159,"children":32160},{"style":545},[32161],{"type":420,"value":9233},{"type":415,"tag":532,"props":32163,"children":32164},{"style":551},[32165],{"type":420,"value":7400},{"type":415,"tag":532,"props":32167,"children":32168},{"class":534,"line":627},[32169,32173,32177,32181,32186,32190],{"type":415,"tag":532,"props":32170,"children":32171},{"style":545},[32172],{"type":420,"value":9245},{"type":415,"tag":532,"props":32174,"children":32175},{"style":551},[32176],{"type":420,"value":1134},{"type":415,"tag":532,"props":32178,"children":32179},{"style":551},[32180],{"type":420,"value":4041},{"type":415,"tag":532,"props":32182,"children":32183},{"style":804},[32184],{"type":420,"value":32185},"/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b",{"type":415,"tag":532,"props":32187,"children":32188},{"style":551},[32189],{"type":420,"value":801},{"type":415,"tag":532,"props":32191,"children":32192},{"style":551},[32193],{"type":420,"value":7400},{"type":415,"tag":532,"props":32195,"children":32196},{"class":534,"line":677},[32197,32201,32205,32209,32213],{"type":415,"tag":532,"props":32198,"children":32199},{"style":545},[32200],{"type":420,"value":9275},{"type":415,"tag":532,"props":32202,"children":32203},{"style":551},[32204],{"type":420,"value":1134},{"type":415,"tag":532,"props":32206,"children":32207},{"style":545},[32208],{"type":420,"value":30852},{"type":415,"tag":532,"props":32210,"children":32211},{"style":551},[32212],{"type":420,"value":432},{"type":415,"tag":532,"props":32214,"children":32215},{"style":545},[32216],{"type":420,"value":10653},{"type":415,"tag":532,"props":32218,"children":32219},{"class":534,"line":719},[32220],{"type":415,"tag":532,"props":32221,"children":32222},{"style":551},[32223],{"type":420,"value":856},{"type":415,"tag":434,"props":32225,"children":32226},{"icon":1382},[32227],{"type":415,"tag":416,"props":32228,"children":32229},{},[32230],{"type":420,"value":32231},"Because the Azure provider is auto-generated from the Azure Resource Manager APIs, it is not always obvious to figure out what object and properties we should use to implement the infrastructure we want. Hopefully, because we are using a programming language in an IDE (C# in Visual Studio in my case), IntelliSense can help us.",{"type":415,"tag":416,"props":32233,"children":32234},{},[32235,32237,32242,32244,32249],{"type":420,"value":32236},"And that's just it, with this code the Function App will go well without needing the secret connection string of the storage in the AzureWebJobsStorage setting. Everything works fine thanks to the Managed Identity, the assignment of the correct role, and the setting ",{"type":415,"tag":468,"props":32238,"children":32240},{"className":32239},[],[32241],{"type":420,"value":30606},{"type":420,"value":32243},". One thing we could do is to remove the ",{"type":415,"tag":468,"props":32245,"children":32247},{"className":32246},[],[32248],{"type":420,"value":30606},{"type":420,"value":32250}," setting from the configuration to observe that without it, the Function App will not work properly: for instance, we would not be able to create function keys as a storage is needed to store them.",{"type":415,"tag":416,"props":32252,"children":32253},{},[32254,32256,32262],{"type":420,"value":32255},"You can find all this code on ",{"type":415,"tag":423,"props":32257,"children":32260},{"href":32258,"rel":32259},"https://github.com/TechWatching/FunctionAppWithoutSecretConnectionString",[427],[32261],{"type":420,"value":28371},{"type":420,"value":32263}," if you want to test it by yourself. You will also find an HttpTrigger Azure Function created from the templates in Visual Studio that I only used to have something deployed on my Function App.",{"type":415,"tag":482,"props":32265,"children":32267},{"id":32266},"how-can-we-remove-the-azurewebjobsstorage-secret-setting-using-terraform",[32268],{"type":420,"value":32269},"How can we remove the AzureWebJobsStorage secret setting using Terraform?",{"type":415,"tag":416,"props":32271,"children":32272},{},[32273],{"type":420,"value":32274},"I am a big fan of Pulumi's approach to build and deploy infrastructure but as Terraform is pretty popular for doing Infrastructure as Code, I thought it might be a good idea to explain how to solve the same issue using Terraform instead of Pulumi.",{"type":415,"tag":416,"props":32276,"children":32277},{},[32278,32280,32287,32288,32294,32296,32302,32303,32309],{"type":420,"value":32279},"Well, in fact, you can't. 🤔 Currently there is no way to remove AzureWebJobsStorage secret using Terraform. Indeed as you can see in the ",{"type":415,"tag":423,"props":32281,"children":32284},{"href":32282,"rel":32283},"https://www.pulumi.com/blog/pulumiup-native-providers/",[427],[32285],{"type":420,"value":32286},"Terraform documentation of a Function App resource",{"type":420,"value":16037},{"type":415,"tag":468,"props":32289,"children":32291},{"className":32290},[],[32292],{"type":420,"value":32293},"azurerm_function_app",{"type":420,"value":32295},", the AzureWebJobsStorage setting is automatically filled based on the ",{"type":415,"tag":468,"props":32297,"children":32299},{"className":32298},[],[32300],{"type":420,"value":32301},"storage_account_name",{"type":420,"value":6722},{"type":415,"tag":468,"props":32304,"children":32306},{"className":32305},[],[32307],{"type":420,"value":32308},"storage_account_access_key",{"type":420,"value":32310}," parameters which are required. So not only you can't use the Managed Identity access to storage as we did in Pulumi but also you can't use a key vault reference for the AzureWebJobsStorage setting (see the documentation screenshot below).",{"type":415,"tag":416,"props":32312,"children":32313},{},[32314],{"type":415,"tag":3882,"props":32315,"children":32319},{"alt":32316,"className":32317,"src":32318},"Azure RM provider for Terraform documentation about AzureWebJobsStorage.",[3886,3887],"/posts/images/functionsidentity_terraform_1.png",[],{"type":415,"tag":416,"props":32321,"children":32322},{},[32323,32325,32331],{"type":420,"value":32324},"The only possibility right now is to use an ARM template in your Terraform project thanks to the ",{"type":415,"tag":468,"props":32326,"children":32328},{"className":32327},[],[32329],{"type":420,"value":32330},"azurerm_resource_group_template_deployment",{"type":420,"value":32332}," resource but that defeats the whole point of using Terraform especially for a major resource like a Function App.",{"type":415,"tag":416,"props":32334,"children":32335},{},[32336],{"type":420,"value":32337},"In the GitHub repository of the Terraform provider for Azure RM there are 2 issues relative to this problem (do not hesitate to vote for them):",{"type":415,"tag":508,"props":32339,"children":32340},{},[32341,32354],{"type":415,"tag":512,"props":32342,"children":32343},{},[32344,32345,32352],{"type":420,"value":7095},{"type":415,"tag":423,"props":32346,"children":32349},{"href":32347,"rel":32348},"https://github.com/hashicorp/terraform-provider-azurerm/issues/8977",[427],[32350],{"type":420,"value":32351},"8977 issue",{"type":420,"value":32353}," that aims at supporting a KeyVault reference for the AzureWebJobsStorage setting",{"type":415,"tag":512,"props":32355,"children":32356},{},[32357,32358,32365],{"type":420,"value":7095},{"type":415,"tag":423,"props":32359,"children":32362},{"href":32360,"rel":32361},"https://github.com/hashicorp/terraform-provider-azurerm/issues/13240",[427],[32363],{"type":420,"value":32364},"13240 issue",{"type":420,"value":32366}," that aims at supporting the Managed Identity access to storage",{"type":415,"tag":416,"props":32368,"children":32369},{},[32370],{"type":420,"value":32371},"I guess this will be implemented someday in Terraform provider for Azure RM, so that may not be a big deal but that clearly shows the limitations of Terraform providers.",{"type":415,"tag":434,"props":32373,"children":32374},{"icon":1382},[32375],{"type":415,"tag":416,"props":32376,"children":32377},{},[32378],{"type":420,"value":32379},"Because Terraform provider for Azure RM is manually implemented using the Azure SDK, it does not match Azure APIs hence not all new resources and features are available (they have to be implemented in the provider as new features in Azure are released and it can take time). It's something that is not a problem with Pulumi Azure Native provider as the SDKs are generated automatically from the Azure API specifications which makes Pulumi Azure Native provider always up-to-date.",{"type":415,"tag":482,"props":32381,"children":32382},{"id":6689},[32383],{"type":420,"value":32384},"Final thoughts",{"type":415,"tag":416,"props":32386,"children":32387},{},[32388],{"type":420,"value":32389},"I hope that after reading this article if you are working on a Function App with an AzureWebJobsStorage setting you will take the time to replace it with an access to storage through the Managed Identity of your Function. One question you could ask me is why this is not the default behavior when creating a new Function App instead of using the AzureWebJobsStorage. And that would be an excellent question... for the Azure Functions team 😀.",{"type":415,"tag":416,"props":32391,"children":32392},{},[32393],{"type":420,"value":32394},"If you did not know Pulumi before reading this article, I hope it made you want to give it a try.\nHappy learning.",{"type":415,"tag":3470,"props":32396,"children":32397},{},[32398],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":32400},[32401,32402,32403,32404,32408,32409],{"id":30504,"depth":566,"text":30507},{"id":30544,"depth":566,"text":30547},{"id":30569,"depth":566,"text":30572},{"id":30640,"depth":566,"text":30643,"children":32405},[32406,32407],{"id":30659,"depth":583,"text":30662},{"id":30693,"depth":583,"text":30696},{"id":32266,"depth":566,"text":32269},{"id":6689,"depth":566,"text":32384},"content:1.posts:23.azure-functions-without-azurewebjobsstorage.md","1.posts/23.azure-functions-without-azurewebjobsstorage.md",{"_path":67,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":66,"description":32413,"lead":32414,"date":32415,"image":32416,"badge":32418,"tags":32419,"body":32420,"_type":3483,"_id":34780,"_source":3485,"_file":34781,"_extension":3487},"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":32417},"/images/cloud-azure_1.jpg",{"label":408},[252,299,302,228,225,236],{"type":412,"children":32421,"toc":34769},[32422,32441,32464,32469,32475,32495,32618,32629,32634,32657,32662,32668,32673,32678,32690,32702,32901,32939,32944,32957,32991,33069,33084,33090,33095,33101,33115,34083,34088,34123,34128,34142,34148,34162,34174,34660,34665,34723,34732,34748,34752,34765],{"type":415,"tag":416,"props":32423,"children":32424},{},[32425,32426,32431,32433,32439],{"type":420,"value":22704},{"type":415,"tag":468,"props":32427,"children":32429},{"className":32428},[],[32430],{"type":420,"value":22719},{"type":420,"value":32432}," v3.0.0, a new authentication mode ",{"type":415,"tag":468,"props":32434,"children":32436},{"className":32435},[],[32437],{"type":420,"value":32438},"Active Directory Default",{"type":420,"value":32440}," has been released. Let's see what this means when querying an Azure SQL Database from some C# code.",{"type":415,"tag":434,"props":32442,"children":32443},{"icon":1382},[32444],{"type":415,"tag":416,"props":32445,"children":32446},{},[32447,32449,32454,32456,32462],{"type":420,"value":32448},"If you do not have heard about ",{"type":415,"tag":468,"props":32450,"children":32452},{"className":32451},[],[32453],{"type":420,"value":22719},{"type":420,"value":32455},", 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":415,"tag":468,"props":32457,"children":32459},{"className":32458},[],[32460],{"type":420,"value":32461},"System.Data.SqlClient",{"type":420,"value":32463}," components.",{"type":415,"tag":416,"props":32465,"children":32466},{},[32467],{"type":420,"value":32468},"But first, let's talk about how we used to do that before.",{"type":415,"tag":482,"props":32470,"children":32472},{"id":32471},"the-traditional-way-using-a-secret-connection-string",[32473],{"type":420,"value":32474},"The traditional way: using a secret connection string",{"type":415,"tag":416,"props":32476,"children":32477},{},[32478,32479,32485,32487,32493],{"type":420,"value":4968},{"type":415,"tag":468,"props":32480,"children":32482},{"className":32481},[],[32483],{"type":420,"value":32484},"traditional way",{"type":420,"value":32486}," to connect to an Azure SQL database from an application in C# is to provide to the ",{"type":415,"tag":468,"props":32488,"children":32490},{"className":32489},[],[32491],{"type":420,"value":32492},"SqlConnection",{"type":420,"value":32494}," constructor a connection string that contains a username and a password. The corresponding C# code is quite simple:",{"type":415,"tag":523,"props":32496,"children":32498},{"className":525,"code":32497,"language":326,"meta":401,"style":401},"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",[32499],{"type":415,"tag":468,"props":32500,"children":32501},{"__ignoreMap":401},[32502,32539,32546,32592],{"type":415,"tag":532,"props":32503,"children":32504},{"class":534,"line":535},[32505,32509,32514,32518,32522,32527,32531,32535],{"type":415,"tag":532,"props":32506,"children":32507},{"style":631},[32508],{"type":420,"value":634},{"type":415,"tag":532,"props":32510,"children":32511},{"style":631},[32512],{"type":420,"value":32513}," connectionString",{"type":415,"tag":532,"props":32515,"children":32516},{"style":551},[32517],{"type":420,"value":644},{"type":415,"tag":532,"props":32519,"children":32520},{"style":551},[32521],{"type":420,"value":4041},{"type":415,"tag":532,"props":32523,"children":32524},{"style":804},[32525],{"type":420,"value":32526},"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;User ID=globalSqlAdmin;Password=MySecretPassword;",{"type":415,"tag":532,"props":32528,"children":32529},{"style":551},[32530],{"type":420,"value":801},{"type":415,"tag":532,"props":32532,"children":32533},{"style":545},[32534],{"type":420,"value":1349},{"type":415,"tag":532,"props":32536,"children":32537},{"style":551},[32538],{"type":420,"value":563},{"type":415,"tag":532,"props":32540,"children":32541},{"class":534,"line":566},[32542],{"type":415,"tag":532,"props":32543,"children":32544},{"emptyLinePlaceholder":621},[32545],{"type":420,"value":624},{"type":415,"tag":532,"props":32547,"children":32548},{"class":534,"line":583},[32549,32553,32557,32561,32566,32570,32574,32579,32583,32588],{"type":415,"tag":532,"props":32550,"children":32551},{"style":1241},[32552],{"type":420,"value":542},{"type":415,"tag":532,"props":32554,"children":32555},{"style":551},[32556],{"type":420,"value":1249},{"type":415,"tag":532,"props":32558,"children":32559},{"style":631},[32560],{"type":420,"value":634},{"type":415,"tag":532,"props":32562,"children":32563},{"style":631},[32564],{"type":420,"value":32565}," sqlConnection",{"type":415,"tag":532,"props":32567,"children":32568},{"style":551},[32569],{"type":420,"value":644},{"type":415,"tag":532,"props":32571,"children":32572},{"style":551},[32573],{"type":420,"value":3276},{"type":415,"tag":532,"props":32575,"children":32576},{"style":631},[32577],{"type":420,"value":32578}," SqlConnection",{"type":415,"tag":532,"props":32580,"children":32581},{"style":551},[32582],{"type":420,"value":664},{"type":415,"tag":532,"props":32584,"children":32585},{"style":545},[32586],{"type":420,"value":32587},"connectionString",{"type":415,"tag":532,"props":32589,"children":32590},{"style":551},[32591],{"type":420,"value":816},{"type":415,"tag":532,"props":32593,"children":32594},{"class":534,"line":617},[32595,32600,32605,32609,32614],{"type":415,"tag":532,"props":32596,"children":32597},{"style":551},[32598],{"type":420,"value":32599},"await",{"type":415,"tag":532,"props":32601,"children":32602},{"style":545},[32603],{"type":420,"value":32604}," connection",{"type":415,"tag":532,"props":32606,"children":32607},{"style":551},[32608],{"type":420,"value":432},{"type":415,"tag":532,"props":32610,"children":32611},{"style":656},[32612],{"type":420,"value":32613},"OpenAsync",{"type":415,"tag":532,"props":32615,"children":32616},{"style":551},[32617],{"type":420,"value":899},{"type":415,"tag":416,"props":32619,"children":32620},{},[32621,32623,32628],{"type":420,"value":32622},"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":415,"tag":468,"props":32624,"children":32626},{"className":32625},[],[32627],{"type":420,"value":260},{"type":420,"value":432},{"type":415,"tag":416,"props":32630,"children":32631},{},[32632],{"type":420,"value":32633},"However, even if you secure it appropriately, using a connection string with a username/password in it has some disadvantages:",{"type":415,"tag":508,"props":32635,"children":32636},{},[32637,32642,32647,32652],{"type":415,"tag":512,"props":32638,"children":32639},{},[32640],{"type":420,"value":32641},"you need to handle who has access to it (so who has access to the key vault)",{"type":415,"tag":512,"props":32643,"children":32644},{},[32645],{"type":420,"value":32646},"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":415,"tag":512,"props":32648,"children":32649},{},[32650],{"type":420,"value":32651},"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":415,"tag":512,"props":32653,"children":32654},{},[32655],{"type":420,"value":32656},"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":415,"tag":416,"props":32658,"children":32659},{},[32660],{"type":420,"value":32661},"For all these reasons, using a secret connection string to connect to an Azure SQL Database is not the right approach.",{"type":415,"tag":482,"props":32663,"children":32665},{"id":32664},"the-new-way-using-azure-active-directory-authentication",[32666],{"type":420,"value":32667},"The new way: using Azure Active Directory Authentication",{"type":415,"tag":416,"props":32669,"children":32670},{},[32671],{"type":420,"value":32672},"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":415,"tag":416,"props":32674,"children":32675},{},[32676],{"type":420,"value":32677},"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":415,"tag":416,"props":32679,"children":32680},{},[32681,32683,32689],{"type":420,"value":32682},"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":415,"tag":423,"props":32684,"children":32687},{"href":32685,"rel":32686},"https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-overview",[427],[32688],{"type":420,"value":28498},{"type":420,"value":432},{"type":415,"tag":416,"props":32691,"children":32692},{},[32693,32695,32700],{"type":420,"value":32694},"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":415,"tag":468,"props":32696,"children":32698},{"className":32697},[],[32699],{"type":420,"value":32492},{"type":420,"value":32701}," instance:",{"type":415,"tag":523,"props":32703,"children":32705},{"className":525,"code":32704,"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",[32706],{"type":415,"tag":468,"props":32707,"children":32708},{"__ignoreMap":401},[32709,32791,32839,32846,32871,32878],{"type":415,"tag":532,"props":32710,"children":32711},{"class":534,"line":535},[32712,32716,32721,32725,32730,32734,32738,32742,32747,32751,32756,32760,32765,32769,32773,32777,32782,32786],{"type":415,"tag":532,"props":32713,"children":32714},{"style":631},[32715],{"type":420,"value":634},{"type":415,"tag":532,"props":32717,"children":32718},{"style":631},[32719],{"type":420,"value":32720}," accessToken",{"type":415,"tag":532,"props":32722,"children":32723},{"style":551},[32724],{"type":420,"value":644},{"type":415,"tag":532,"props":32726,"children":32727},{"style":551},[32728],{"type":420,"value":32729}," await",{"type":415,"tag":532,"props":32731,"children":32732},{"style":551},[32733],{"type":420,"value":3276},{"type":415,"tag":532,"props":32735,"children":32736},{"style":631},[32737],{"type":420,"value":842},{"type":415,"tag":532,"props":32739,"children":32740},{"style":551},[32741],{"type":420,"value":24299},{"type":415,"tag":532,"props":32743,"children":32744},{"style":656},[32745],{"type":420,"value":32746},"GetTokenAsync",{"type":415,"tag":532,"props":32748,"children":32749},{"style":551},[32750],{"type":420,"value":787},{"type":415,"tag":532,"props":32752,"children":32753},{"style":631},[32754],{"type":420,"value":32755}," TokenRequestContext",{"type":415,"tag":532,"props":32757,"children":32758},{"style":551},[32759],{"type":420,"value":787},{"type":415,"tag":532,"props":32761,"children":32762},{"style":551},[32763],{"type":420,"value":32764}," string",{"type":415,"tag":532,"props":32766,"children":32767},{"style":551},[32768],{"type":420,"value":29585},{"type":415,"tag":532,"props":32770,"children":32771},{"style":551},[32772],{"type":420,"value":3347},{"type":415,"tag":532,"props":32774,"children":32775},{"style":551},[32776],{"type":420,"value":4041},{"type":415,"tag":532,"props":32778,"children":32779},{"style":804},[32780],{"type":420,"value":32781},"https://database.windows.net//.default",{"type":415,"tag":532,"props":32783,"children":32784},{"style":551},[32785],{"type":420,"value":801},{"type":415,"tag":532,"props":32787,"children":32788},{"style":551},[32789],{"type":420,"value":32790}," }));\n",{"type":415,"tag":532,"props":32792,"children":32793},{"class":534,"line":566},[32794,32798,32802,32806,32810,32814,32818,32822,32826,32831,32835],{"type":415,"tag":532,"props":32795,"children":32796},{"style":1241},[32797],{"type":420,"value":542},{"type":415,"tag":532,"props":32799,"children":32800},{"style":631},[32801],{"type":420,"value":22149},{"type":415,"tag":532,"props":32803,"children":32804},{"style":631},[32805],{"type":420,"value":32604},{"type":415,"tag":532,"props":32807,"children":32808},{"style":551},[32809],{"type":420,"value":644},{"type":415,"tag":532,"props":32811,"children":32812},{"style":551},[32813],{"type":420,"value":3276},{"type":415,"tag":532,"props":32815,"children":32816},{"style":631},[32817],{"type":420,"value":32578},{"type":415,"tag":532,"props":32819,"children":32820},{"style":551},[32821],{"type":420,"value":664},{"type":415,"tag":532,"props":32823,"children":32824},{"style":551},[32825],{"type":420,"value":801},{"type":415,"tag":532,"props":32827,"children":32828},{"style":804},[32829],{"type":420,"value":32830},"Server=server-testingmsi6499.database.windows.net; Database=database-testingmsi6499;",{"type":415,"tag":532,"props":32832,"children":32833},{"style":551},[32834],{"type":420,"value":801},{"type":415,"tag":532,"props":32836,"children":32837},{"style":551},[32838],{"type":420,"value":1113},{"type":415,"tag":532,"props":32840,"children":32841},{"class":534,"line":583},[32842],{"type":415,"tag":532,"props":32843,"children":32844},{"style":551},[32845],{"type":420,"value":764},{"type":415,"tag":532,"props":32847,"children":32848},{"class":534,"line":617},[32849,32854,32858,32862,32866],{"type":415,"tag":532,"props":32850,"children":32851},{"style":545},[32852],{"type":420,"value":32853},"    AccessToken ",{"type":415,"tag":532,"props":32855,"children":32856},{"style":551},[32857],{"type":420,"value":1134},{"type":415,"tag":532,"props":32859,"children":32860},{"style":545},[32861],{"type":420,"value":32720},{"type":415,"tag":532,"props":32863,"children":32864},{"style":551},[32865],{"type":420,"value":432},{"type":415,"tag":532,"props":32867,"children":32868},{"style":545},[32869],{"type":420,"value":32870},"Token\n",{"type":415,"tag":532,"props":32872,"children":32873},{"class":534,"line":627},[32874],{"type":415,"tag":532,"props":32875,"children":32876},{"style":551},[32877],{"type":420,"value":10828},{"type":415,"tag":532,"props":32879,"children":32880},{"class":534,"line":677},[32881,32885,32889,32893,32897],{"type":415,"tag":532,"props":32882,"children":32883},{"style":551},[32884],{"type":420,"value":32599},{"type":415,"tag":532,"props":32886,"children":32887},{"style":545},[32888],{"type":420,"value":32604},{"type":415,"tag":532,"props":32890,"children":32891},{"style":551},[32892],{"type":420,"value":432},{"type":415,"tag":532,"props":32894,"children":32895},{"style":656},[32896],{"type":420,"value":32613},{"type":415,"tag":532,"props":32898,"children":32899},{"style":551},[32900],{"type":420,"value":899},{"type":415,"tag":416,"props":32902,"children":32903},{},[32904,32906,32913,32915,32920,32922,32929,32931,32937],{"type":420,"value":32905},"The code is using the ",{"type":415,"tag":423,"props":32907,"children":32910},{"href":32908,"rel":32909},"https://docs.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme",[427],[32911],{"type":420,"value":32912},"Azure Identity library",{"type":420,"value":32914}," which as the documentation says \"",{"type":415,"tag":7033,"props":32916,"children":32917},{},[32918],{"type":420,"value":32919},"provides Azure Active Directory token authentication support across the Azure SDK",{"type":420,"value":32921},"\". It is the recommended way to get an Azure token although you may have seen code that uses another library ",{"type":415,"tag":423,"props":32923,"children":32926},{"href":32924,"rel":32925},"https://www.nuget.org/packages/Microsoft.Azure.Services.AppAuthentication",[427],[32927],{"type":420,"value":32928},"Microsoft.Azure.Services.AppAuthentication",{"type":420,"value":32930}," to do the same thing. The class ",{"type":415,"tag":468,"props":32932,"children":32934},{"className":32933},[],[32935],{"type":420,"value":32936},"DefaultAzureCredential",{"type":420,"value":32938}," 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":415,"tag":416,"props":32940,"children":32941},{},[32942],{"type":420,"value":32943},"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":415,"tag":482,"props":32945,"children":32947},{"id":32946},"here-comes-active-directory-default-authentication-mode",[32948,32950,32955],{"type":420,"value":32949},"Here comes ",{"type":415,"tag":468,"props":32951,"children":32953},{"className":32952},[],[32954],{"type":420,"value":32438},{"type":420,"value":32956}," authentication mode",{"type":415,"tag":416,"props":32958,"children":32959},{},[32960,32962,32967,32969,32974,32976,32982,32984,32989],{"type":420,"value":32961},"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":415,"tag":468,"props":32963,"children":32965},{"className":32964},[],[32966],{"type":420,"value":32438},{"type":420,"value":32968}," new authentication mode was introduced in ",{"type":415,"tag":468,"props":32970,"children":32972},{"className":32971},[],[32973],{"type":420,"value":22719},{"type":420,"value":32975}," v3.0.0. Under the hood, ",{"type":415,"tag":468,"props":32977,"children":32979},{"className":32978},[],[32980],{"type":420,"value":32981},"SqlClient",{"type":420,"value":32983}," 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":415,"tag":468,"props":32985,"children":32987},{"className":32986},[],[32988],{"type":420,"value":32438},{"type":420,"value":32990}," in the connection string is enough to make it work.",{"type":415,"tag":523,"props":32992,"children":32994},{"className":525,"code":32993,"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",[32995],{"type":415,"tag":468,"props":32996,"children":32997},{"__ignoreMap":401},[32998,33046],{"type":415,"tag":532,"props":32999,"children":33000},{"class":534,"line":535},[33001,33005,33009,33013,33017,33021,33025,33029,33033,33038,33042],{"type":415,"tag":532,"props":33002,"children":33003},{"style":1241},[33004],{"type":420,"value":542},{"type":415,"tag":532,"props":33006,"children":33007},{"style":631},[33008],{"type":420,"value":22149},{"type":415,"tag":532,"props":33010,"children":33011},{"style":631},[33012],{"type":420,"value":32604},{"type":415,"tag":532,"props":33014,"children":33015},{"style":551},[33016],{"type":420,"value":644},{"type":415,"tag":532,"props":33018,"children":33019},{"style":551},[33020],{"type":420,"value":3276},{"type":415,"tag":532,"props":33022,"children":33023},{"style":631},[33024],{"type":420,"value":32578},{"type":415,"tag":532,"props":33026,"children":33027},{"style":551},[33028],{"type":420,"value":664},{"type":415,"tag":532,"props":33030,"children":33031},{"style":551},[33032],{"type":420,"value":801},{"type":415,"tag":532,"props":33034,"children":33035},{"style":804},[33036],{"type":420,"value":33037},"Server=server-testingmsi6499.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi6499;",{"type":415,"tag":532,"props":33039,"children":33040},{"style":551},[33041],{"type":420,"value":801},{"type":415,"tag":532,"props":33043,"children":33044},{"style":551},[33045],{"type":420,"value":674},{"type":415,"tag":532,"props":33047,"children":33048},{"class":534,"line":566},[33049,33053,33057,33061,33065],{"type":415,"tag":532,"props":33050,"children":33051},{"style":551},[33052],{"type":420,"value":32599},{"type":415,"tag":532,"props":33054,"children":33055},{"style":545},[33056],{"type":420,"value":32604},{"type":415,"tag":532,"props":33058,"children":33059},{"style":551},[33060],{"type":420,"value":432},{"type":415,"tag":532,"props":33062,"children":33063},{"style":656},[33064],{"type":420,"value":32613},{"type":415,"tag":532,"props":33066,"children":33067},{"style":551},[33068],{"type":420,"value":899},{"type":415,"tag":434,"props":33070,"children":33071},{"icon":1382},[33072],{"type":415,"tag":416,"props":33073,"children":33074},{},[33075,33077,33083],{"type":420,"value":33076},"There are other Azure Active Directory authentication methods available, you can find them in the documentation ",{"type":415,"tag":423,"props":33078,"children":33081},{"href":33079,"rel":33080},"https://docs.microsoft.com/en-us/sql/connect/ado-net/sql/azure-active-directory-authentication?view=sql-server-ver15#using-active-directory-password-authentication",[427],[33082],{"type":420,"value":4427},{"type":420,"value":432},{"type":415,"tag":482,"props":33085,"children":33087},{"id":33086},"a-complete-example",[33088],{"type":420,"value":33089},"A complete example",{"type":415,"tag":416,"props":33091,"children":33092},{},[33093],{"type":420,"value":33094},"Enough theory, what if you want to quickly test this by yourself?",{"type":415,"tag":3914,"props":33096,"children":33098},{"id":33097},"a-bit-of-azure-cli-to-initialize-the-database",[33099],{"type":420,"value":33100},"A bit of Azure CLI to initialize the database",{"type":415,"tag":416,"props":33102,"children":33103},{},[33104,33106,33113],{"type":420,"value":33105},"I took an ",{"type":415,"tag":423,"props":33107,"children":33110},{"href":33108,"rel":33109},"https://docs.microsoft.com/en-us/azure/azure-sql/database/scripts/create-and-configure-database-cli",[427],[33111],{"type":420,"value":33112},"Azure CLI sample script",{"type":420,"value":33114}," 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":415,"tag":523,"props":33116,"children":33118},{"className":3984,"code":33117,"language":3986,"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",[33119],{"type":415,"tag":468,"props":33120,"children":33121},{"__ignoreMap":401},[33122,33130,33158,33205,33212,33241,33270,33298,33305,33330,33360,33367,33375,33383,33419,33436,33443,33451,33459,33519,33526,33557,33600,33607,33644,33719,33726,33746,33817,33824,33861,33937,33944,33964,34025,34032],{"type":415,"tag":532,"props":33123,"children":33124},{"class":534,"line":535},[33125],{"type":415,"tag":532,"props":33126,"children":33127},{"style":5425},[33128],{"type":420,"value":33129},"#!/bin/bash\n",{"type":415,"tag":532,"props":33131,"children":33132},{"class":534,"line":566},[33133,33137,33141,33145,33149,33153],{"type":415,"tag":532,"props":33134,"children":33135},{"style":545},[33136],{"type":420,"value":25872},{"type":415,"tag":532,"props":33138,"children":33139},{"style":551},[33140],{"type":420,"value":1134},{"type":415,"tag":532,"props":33142,"children":33143},{"style":551},[33144],{"type":420,"value":801},{"type":415,"tag":532,"props":33146,"children":33147},{"style":804},[33148],{"type":420,"value":25885},{"type":415,"tag":532,"props":33150,"children":33151},{"style":551},[33152],{"type":420,"value":801},{"type":415,"tag":532,"props":33154,"children":33155},{"style":5425},[33156],{"type":420,"value":33157}," # to change with your preferred location\n",{"type":415,"tag":532,"props":33159,"children":33160},{"class":534,"line":583},[33161,33166,33170,33175,33179,33184,33188,33192,33196,33201],{"type":415,"tag":532,"props":33162,"children":33163},{"style":545},[33164],{"type":420,"value":33165},"randomIdentifier",{"type":415,"tag":532,"props":33167,"children":33168},{"style":551},[33169],{"type":420,"value":1134},{"type":415,"tag":532,"props":33171,"children":33172},{"style":804},[33173],{"type":420,"value":33174},"testingmsi",{"type":415,"tag":532,"props":33176,"children":33177},{"style":551},[33178],{"type":420,"value":4493},{"type":415,"tag":532,"props":33180,"children":33181},{"style":545},[33182],{"type":420,"value":33183},"RANDOM",{"type":415,"tag":532,"props":33185,"children":33186},{"style":551},[33187],{"type":420,"value":1290},{"type":415,"tag":532,"props":33189,"children":33190},{"style":545},[33191],{"type":420,"value":28206},{"type":415,"tag":532,"props":33193,"children":33194},{"style":551},[33195],{"type":420,"value":1290},{"type":415,"tag":532,"props":33197,"children":33198},{"style":545},[33199],{"type":420,"value":33200},"5",{"type":415,"tag":532,"props":33202,"children":33203},{"style":551},[33204],{"type":420,"value":1379},{"type":415,"tag":532,"props":33206,"children":33207},{"class":534,"line":617},[33208],{"type":415,"tag":532,"props":33209,"children":33210},{"emptyLinePlaceholder":621},[33211],{"type":420,"value":624},{"type":415,"tag":532,"props":33213,"children":33214},{"class":534,"line":627},[33215,33219,33223,33227,33232,33237],{"type":415,"tag":532,"props":33216,"children":33217},{"style":545},[33218],{"type":420,"value":30831},{"type":415,"tag":532,"props":33220,"children":33221},{"style":551},[33222],{"type":420,"value":1134},{"type":415,"tag":532,"props":33224,"children":33225},{"style":551},[33226],{"type":420,"value":801},{"type":415,"tag":532,"props":33228,"children":33229},{"style":804},[33230],{"type":420,"value":33231},"resource-",{"type":415,"tag":532,"props":33233,"children":33234},{"style":545},[33235],{"type":420,"value":33236},"$randomIdentifier",{"type":415,"tag":532,"props":33238,"children":33239},{"style":551},[33240],{"type":420,"value":4051},{"type":415,"tag":532,"props":33242,"children":33243},{"class":534,"line":677},[33244,33249,33253,33257,33262,33266],{"type":415,"tag":532,"props":33245,"children":33246},{"style":545},[33247],{"type":420,"value":33248},"server",{"type":415,"tag":532,"props":33250,"children":33251},{"style":551},[33252],{"type":420,"value":1134},{"type":415,"tag":532,"props":33254,"children":33255},{"style":551},[33256],{"type":420,"value":801},{"type":415,"tag":532,"props":33258,"children":33259},{"style":804},[33260],{"type":420,"value":33261},"server-",{"type":415,"tag":532,"props":33263,"children":33264},{"style":545},[33265],{"type":420,"value":33236},{"type":415,"tag":532,"props":33267,"children":33268},{"style":551},[33269],{"type":420,"value":4051},{"type":415,"tag":532,"props":33271,"children":33272},{"class":534,"line":719},[33273,33277,33281,33285,33290,33294],{"type":415,"tag":532,"props":33274,"children":33275},{"style":545},[33276],{"type":420,"value":23921},{"type":415,"tag":532,"props":33278,"children":33279},{"style":551},[33280],{"type":420,"value":1134},{"type":415,"tag":532,"props":33282,"children":33283},{"style":551},[33284],{"type":420,"value":801},{"type":415,"tag":532,"props":33286,"children":33287},{"style":804},[33288],{"type":420,"value":33289},"database-",{"type":415,"tag":532,"props":33291,"children":33292},{"style":545},[33293],{"type":420,"value":33236},{"type":415,"tag":532,"props":33295,"children":33296},{"style":551},[33297],{"type":420,"value":4051},{"type":415,"tag":532,"props":33299,"children":33300},{"class":534,"line":758},[33301],{"type":415,"tag":532,"props":33302,"children":33303},{"emptyLinePlaceholder":621},[33304],{"type":420,"value":624},{"type":415,"tag":532,"props":33306,"children":33307},{"class":534,"line":767},[33308,33313,33317,33321,33326],{"type":415,"tag":532,"props":33309,"children":33310},{"style":545},[33311],{"type":420,"value":33312},"login",{"type":415,"tag":532,"props":33314,"children":33315},{"style":551},[33316],{"type":420,"value":1134},{"type":415,"tag":532,"props":33318,"children":33319},{"style":551},[33320],{"type":420,"value":801},{"type":415,"tag":532,"props":33322,"children":33323},{"style":804},[33324],{"type":420,"value":33325},"globalSqlAdmin",{"type":415,"tag":532,"props":33327,"children":33328},{"style":551},[33329],{"type":420,"value":4051},{"type":415,"tag":532,"props":33331,"children":33332},{"class":534,"line":819},[33333,33338,33342,33346,33351,33355],{"type":415,"tag":532,"props":33334,"children":33335},{"style":545},[33336],{"type":420,"value":33337},"password",{"type":415,"tag":532,"props":33339,"children":33340},{"style":551},[33341],{"type":420,"value":1134},{"type":415,"tag":532,"props":33343,"children":33344},{"style":551},[33345],{"type":420,"value":801},{"type":415,"tag":532,"props":33347,"children":33348},{"style":804},[33349],{"type":420,"value":33350},"P@ssw0rdToChange!",{"type":415,"tag":532,"props":33352,"children":33353},{"style":551},[33354],{"type":420,"value":801},{"type":415,"tag":532,"props":33356,"children":33357},{"style":5425},[33358],{"type":420,"value":33359}," # to change to have a more secured password\n",{"type":415,"tag":532,"props":33361,"children":33362},{"class":534,"line":850},[33363],{"type":415,"tag":532,"props":33364,"children":33365},{"emptyLinePlaceholder":621},[33366],{"type":420,"value":624},{"type":415,"tag":532,"props":33368,"children":33369},{"class":534,"line":859},[33370],{"type":415,"tag":532,"props":33371,"children":33372},{"style":5425},[33373],{"type":420,"value":33374},"# Retrieve your public IP.\n",{"type":415,"tag":532,"props":33376,"children":33377},{"class":534,"line":867},[33378],{"type":415,"tag":532,"props":33379,"children":33380},{"style":5425},[33381],{"type":420,"value":33382},"# Replace by your local machine IP if you are executing this script from cloud shell.\n",{"type":415,"tag":532,"props":33384,"children":33385},{"class":534,"line":902},[33386,33391,33395,33400,33405,33410,33415],{"type":415,"tag":532,"props":33387,"children":33388},{"style":545},[33389],{"type":420,"value":33390},"startIP",{"type":415,"tag":532,"props":33392,"children":33393},{"style":551},[33394],{"type":420,"value":4197},{"type":415,"tag":532,"props":33396,"children":33397},{"style":631},[33398],{"type":420,"value":33399},"dig",{"type":415,"tag":532,"props":33401,"children":33402},{"style":804},[33403],{"type":420,"value":33404}," +short",{"type":415,"tag":532,"props":33406,"children":33407},{"style":804},[33408],{"type":420,"value":33409}," myip.opendns.com",{"type":415,"tag":532,"props":33411,"children":33412},{"style":804},[33413],{"type":420,"value":33414}," @resolver1.opendns.com",{"type":415,"tag":532,"props":33416,"children":33417},{"style":551},[33418],{"type":420,"value":1113},{"type":415,"tag":532,"props":33420,"children":33421},{"class":534,"line":1302},[33422,33427,33431],{"type":415,"tag":532,"props":33423,"children":33424},{"style":545},[33425],{"type":420,"value":33426},"endIP",{"type":415,"tag":532,"props":33428,"children":33429},{"style":551},[33430],{"type":420,"value":1134},{"type":415,"tag":532,"props":33432,"children":33433},{"style":545},[33434],{"type":420,"value":33435},"$startIP\n",{"type":415,"tag":532,"props":33437,"children":33438},{"class":534,"line":1311},[33439],{"type":415,"tag":532,"props":33440,"children":33441},{"emptyLinePlaceholder":621},[33442],{"type":420,"value":624},{"type":415,"tag":532,"props":33444,"children":33445},{"class":534,"line":1356},[33446],{"type":415,"tag":532,"props":33447,"children":33448},{"style":5425},[33449],{"type":420,"value":33450},"# Retrieve your current logged-in user to be used as SQL server admin. \n",{"type":415,"tag":532,"props":33452,"children":33453},{"class":534,"line":1365},[33454],{"type":415,"tag":532,"props":33455,"children":33456},{"style":5425},[33457],{"type":420,"value":33458},"# Change with another user id if you want another user to be an admin.\n",{"type":415,"tag":532,"props":33460,"children":33461},{"class":534,"line":1373},[33462,33467,33471,33475,33480,33485,33490,33494,33498,33502,33506,33511,33515],{"type":415,"tag":532,"props":33463,"children":33464},{"style":545},[33465],{"type":420,"value":33466},"azureaduser",{"type":415,"tag":532,"props":33468,"children":33469},{"style":551},[33470],{"type":420,"value":4197},{"type":415,"tag":532,"props":33472,"children":33473},{"style":631},[33474],{"type":420,"value":25983},{"type":415,"tag":532,"props":33476,"children":33477},{"style":804},[33478],{"type":420,"value":33479}," ad",{"type":415,"tag":532,"props":33481,"children":33482},{"style":804},[33483],{"type":420,"value":33484}," signed-in-user",{"type":415,"tag":532,"props":33486,"children":33487},{"style":804},[33488],{"type":420,"value":33489}," show",{"type":415,"tag":532,"props":33491,"children":33492},{"style":804},[33493],{"type":420,"value":26139},{"type":415,"tag":532,"props":33495,"children":33496},{"style":551},[33497],{"type":420,"value":4041},{"type":415,"tag":532,"props":33499,"children":33500},{"style":804},[33501],{"type":420,"value":12332},{"type":415,"tag":532,"props":33503,"children":33504},{"style":551},[33505],{"type":420,"value":801},{"type":415,"tag":532,"props":33507,"children":33508},{"style":804},[33509],{"type":420,"value":33510}," -o",{"type":415,"tag":532,"props":33512,"children":33513},{"style":804},[33514],{"type":420,"value":26134},{"type":415,"tag":532,"props":33516,"children":33517},{"style":551},[33518],{"type":420,"value":1113},{"type":415,"tag":532,"props":33520,"children":33521},{"class":534,"line":3825},[33522],{"type":415,"tag":532,"props":33523,"children":33524},{"emptyLinePlaceholder":621},[33525],{"type":420,"value":624},{"type":415,"tag":532,"props":33527,"children":33528},{"class":534,"line":3843},[33529,33534,33538,33543,33548,33553],{"type":415,"tag":532,"props":33530,"children":33531},{"style":656},[33532],{"type":420,"value":33533},"echo",{"type":415,"tag":532,"props":33535,"children":33536},{"style":551},[33537],{"type":420,"value":4041},{"type":415,"tag":532,"props":33539,"children":33540},{"style":804},[33541],{"type":420,"value":33542},"Creating ",{"type":415,"tag":532,"props":33544,"children":33545},{"style":545},[33546],{"type":420,"value":33547},"$resourceGroup",{"type":415,"tag":532,"props":33549,"children":33550},{"style":804},[33551],{"type":420,"value":33552},"...",{"type":415,"tag":532,"props":33554,"children":33555},{"style":551},[33556],{"type":420,"value":4051},{"type":415,"tag":532,"props":33558,"children":33559},{"class":534,"line":3852},[33560,33564,33568,33572,33577,33582,33587,33591,33596],{"type":415,"tag":532,"props":33561,"children":33562},{"style":631},[33563],{"type":420,"value":25983},{"type":415,"tag":532,"props":33565,"children":33566},{"style":804},[33567],{"type":420,"value":25988},{"type":415,"tag":532,"props":33569,"children":33570},{"style":804},[33571],{"type":420,"value":25993},{"type":415,"tag":532,"props":33573,"children":33574},{"style":804},[33575],{"type":420,"value":33576}," --name",{"type":415,"tag":532,"props":33578,"children":33579},{"style":545},[33580],{"type":420,"value":33581}," $resourceGroup ",{"type":415,"tag":532,"props":33583,"children":33584},{"style":804},[33585],{"type":420,"value":33586},"--location",{"type":415,"tag":532,"props":33588,"children":33589},{"style":551},[33590],{"type":420,"value":4041},{"type":415,"tag":532,"props":33592,"children":33593},{"style":545},[33594],{"type":420,"value":33595},"$location",{"type":415,"tag":532,"props":33597,"children":33598},{"style":551},[33599],{"type":420,"value":4051},{"type":415,"tag":532,"props":33601,"children":33602},{"class":534,"line":5941},[33603],{"type":415,"tag":532,"props":33604,"children":33605},{"emptyLinePlaceholder":621},[33606],{"type":420,"value":624},{"type":415,"tag":532,"props":33608,"children":33609},{"class":534,"line":6053},[33610,33614,33618,33622,33627,33632,33636,33640],{"type":415,"tag":532,"props":33611,"children":33612},{"style":656},[33613],{"type":420,"value":33533},{"type":415,"tag":532,"props":33615,"children":33616},{"style":551},[33617],{"type":420,"value":4041},{"type":415,"tag":532,"props":33619,"children":33620},{"style":804},[33621],{"type":420,"value":33542},{"type":415,"tag":532,"props":33623,"children":33624},{"style":545},[33625],{"type":420,"value":33626},"$server",{"type":415,"tag":532,"props":33628,"children":33629},{"style":804},[33630],{"type":420,"value":33631}," in ",{"type":415,"tag":532,"props":33633,"children":33634},{"style":545},[33635],{"type":420,"value":33595},{"type":415,"tag":532,"props":33637,"children":33638},{"style":804},[33639],{"type":420,"value":33552},{"type":415,"tag":532,"props":33641,"children":33642},{"style":551},[33643],{"type":420,"value":4051},{"type":415,"tag":532,"props":33645,"children":33646},{"class":534,"line":6061},[33647,33651,33656,33661,33665,33669,33674,33679,33683,33687,33691,33695,33699,33704,33709,33714],{"type":415,"tag":532,"props":33648,"children":33649},{"style":631},[33650],{"type":420,"value":25983},{"type":415,"tag":532,"props":33652,"children":33653},{"style":804},[33654],{"type":420,"value":33655}," sql",{"type":415,"tag":532,"props":33657,"children":33658},{"style":804},[33659],{"type":420,"value":33660}," server",{"type":415,"tag":532,"props":33662,"children":33663},{"style":804},[33664],{"type":420,"value":25993},{"type":415,"tag":532,"props":33666,"children":33667},{"style":804},[33668],{"type":420,"value":33576},{"type":415,"tag":532,"props":33670,"children":33671},{"style":545},[33672],{"type":420,"value":33673}," $server ",{"type":415,"tag":532,"props":33675,"children":33676},{"style":804},[33677],{"type":420,"value":33678},"--resource-group",{"type":415,"tag":532,"props":33680,"children":33681},{"style":545},[33682],{"type":420,"value":33581},{"type":415,"tag":532,"props":33684,"children":33685},{"style":804},[33686],{"type":420,"value":33586},{"type":415,"tag":532,"props":33688,"children":33689},{"style":551},[33690],{"type":420,"value":4041},{"type":415,"tag":532,"props":33692,"children":33693},{"style":545},[33694],{"type":420,"value":33595},{"type":415,"tag":532,"props":33696,"children":33697},{"style":551},[33698],{"type":420,"value":801},{"type":415,"tag":532,"props":33700,"children":33701},{"style":804},[33702],{"type":420,"value":33703}," --admin-user",{"type":415,"tag":532,"props":33705,"children":33706},{"style":545},[33707],{"type":420,"value":33708}," $login ",{"type":415,"tag":532,"props":33710,"children":33711},{"style":804},[33712],{"type":420,"value":33713},"--admin-password",{"type":415,"tag":532,"props":33715,"children":33716},{"style":545},[33717],{"type":420,"value":33718}," $password\n",{"type":415,"tag":532,"props":33720,"children":33721},{"class":534,"line":6070},[33722],{"type":415,"tag":532,"props":33723,"children":33724},{"emptyLinePlaceholder":621},[33725],{"type":420,"value":624},{"type":415,"tag":532,"props":33727,"children":33728},{"class":534,"line":6094},[33729,33733,33737,33742],{"type":415,"tag":532,"props":33730,"children":33731},{"style":656},[33732],{"type":420,"value":33533},{"type":415,"tag":532,"props":33734,"children":33735},{"style":551},[33736],{"type":420,"value":4041},{"type":415,"tag":532,"props":33738,"children":33739},{"style":804},[33740],{"type":420,"value":33741},"Configuring firewall...",{"type":415,"tag":532,"props":33743,"children":33744},{"style":551},[33745],{"type":420,"value":4051},{"type":415,"tag":532,"props":33747,"children":33748},{"class":534,"line":6118},[33749,33753,33757,33761,33766,33770,33775,33779,33784,33788,33792,33797,33802,33807,33812],{"type":415,"tag":532,"props":33750,"children":33751},{"style":631},[33752],{"type":420,"value":25983},{"type":415,"tag":532,"props":33754,"children":33755},{"style":804},[33756],{"type":420,"value":33655},{"type":415,"tag":532,"props":33758,"children":33759},{"style":804},[33760],{"type":420,"value":33660},{"type":415,"tag":532,"props":33762,"children":33763},{"style":804},[33764],{"type":420,"value":33765}," firewall-rule",{"type":415,"tag":532,"props":33767,"children":33768},{"style":804},[33769],{"type":420,"value":25993},{"type":415,"tag":532,"props":33771,"children":33772},{"style":804},[33773],{"type":420,"value":33774}," --resource-group",{"type":415,"tag":532,"props":33776,"children":33777},{"style":545},[33778],{"type":420,"value":33581},{"type":415,"tag":532,"props":33780,"children":33781},{"style":804},[33782],{"type":420,"value":33783},"--server",{"type":415,"tag":532,"props":33785,"children":33786},{"style":545},[33787],{"type":420,"value":33673},{"type":415,"tag":532,"props":33789,"children":33790},{"style":804},[33791],{"type":420,"value":7045},{"type":415,"tag":532,"props":33793,"children":33794},{"style":804},[33795],{"type":420,"value":33796}," AllowYourIp",{"type":415,"tag":532,"props":33798,"children":33799},{"style":804},[33800],{"type":420,"value":33801}," --start-ip-address",{"type":415,"tag":532,"props":33803,"children":33804},{"style":545},[33805],{"type":420,"value":33806}," $startIP ",{"type":415,"tag":532,"props":33808,"children":33809},{"style":804},[33810],{"type":420,"value":33811},"--end-ip-address",{"type":415,"tag":532,"props":33813,"children":33814},{"style":545},[33815],{"type":420,"value":33816}," $endIP\n",{"type":415,"tag":532,"props":33818,"children":33819},{"class":534,"line":6142},[33820],{"type":415,"tag":532,"props":33821,"children":33822},{"emptyLinePlaceholder":621},[33823],{"type":420,"value":624},{"type":415,"tag":532,"props":33825,"children":33826},{"class":534,"line":6182},[33827,33831,33835,33839,33844,33849,33853,33857],{"type":415,"tag":532,"props":33828,"children":33829},{"style":656},[33830],{"type":420,"value":33533},{"type":415,"tag":532,"props":33832,"children":33833},{"style":551},[33834],{"type":420,"value":4041},{"type":415,"tag":532,"props":33836,"children":33837},{"style":804},[33838],{"type":420,"value":33542},{"type":415,"tag":532,"props":33840,"children":33841},{"style":545},[33842],{"type":420,"value":33843},"$database",{"type":415,"tag":532,"props":33845,"children":33846},{"style":804},[33847],{"type":420,"value":33848}," on ",{"type":415,"tag":532,"props":33850,"children":33851},{"style":545},[33852],{"type":420,"value":33626},{"type":415,"tag":532,"props":33854,"children":33855},{"style":804},[33856],{"type":420,"value":33552},{"type":415,"tag":532,"props":33858,"children":33859},{"style":551},[33860],{"type":420,"value":4051},{"type":415,"tag":532,"props":33862,"children":33863},{"class":534,"line":6214},[33864,33868,33872,33877,33881,33885,33889,33893,33897,33902,33907,33912,33917,33922,33927,33932],{"type":415,"tag":532,"props":33865,"children":33866},{"style":631},[33867],{"type":420,"value":25983},{"type":415,"tag":532,"props":33869,"children":33870},{"style":804},[33871],{"type":420,"value":33655},{"type":415,"tag":532,"props":33873,"children":33874},{"style":804},[33875],{"type":420,"value":33876}," db",{"type":415,"tag":532,"props":33878,"children":33879},{"style":804},[33880],{"type":420,"value":25993},{"type":415,"tag":532,"props":33882,"children":33883},{"style":804},[33884],{"type":420,"value":33774},{"type":415,"tag":532,"props":33886,"children":33887},{"style":545},[33888],{"type":420,"value":33581},{"type":415,"tag":532,"props":33890,"children":33891},{"style":804},[33892],{"type":420,"value":33783},{"type":415,"tag":532,"props":33894,"children":33895},{"style":545},[33896],{"type":420,"value":33673},{"type":415,"tag":532,"props":33898,"children":33899},{"style":804},[33900],{"type":420,"value":33901},"--name",{"type":415,"tag":532,"props":33903,"children":33904},{"style":545},[33905],{"type":420,"value":33906}," $database ",{"type":415,"tag":532,"props":33908,"children":33909},{"style":804},[33910],{"type":420,"value":33911},"--sample-name",{"type":415,"tag":532,"props":33913,"children":33914},{"style":804},[33915],{"type":420,"value":33916}," AdventureWorksLT",{"type":415,"tag":532,"props":33918,"children":33919},{"style":804},[33920],{"type":420,"value":33921}," --service-objective",{"type":415,"tag":532,"props":33923,"children":33924},{"style":804},[33925],{"type":420,"value":33926}," Basic",{"type":415,"tag":532,"props":33928,"children":33929},{"style":804},[33930],{"type":420,"value":33931}," --zone-redundant",{"type":415,"tag":532,"props":33933,"children":33934},{"style":551},[33935],{"type":420,"value":33936}," false\n",{"type":415,"tag":532,"props":33938,"children":33939},{"class":534,"line":6234},[33940],{"type":415,"tag":532,"props":33941,"children":33942},{"emptyLinePlaceholder":621},[33943],{"type":420,"value":624},{"type":415,"tag":532,"props":33945,"children":33946},{"class":534,"line":6250},[33947,33951,33955,33960],{"type":415,"tag":532,"props":33948,"children":33949},{"style":656},[33950],{"type":420,"value":33533},{"type":415,"tag":532,"props":33952,"children":33953},{"style":551},[33954],{"type":420,"value":4041},{"type":415,"tag":532,"props":33956,"children":33957},{"style":804},[33958],{"type":420,"value":33959},"Creating AD admin in sql server...",{"type":415,"tag":532,"props":33961,"children":33962},{"style":551},[33963],{"type":420,"value":4051},{"type":415,"tag":532,"props":33965,"children":33966},{"class":534,"line":6258},[33967,33971,33975,33979,33984,33988,33992,33996,34001,34005,34010,34015,34020],{"type":415,"tag":532,"props":33968,"children":33969},{"style":631},[33970],{"type":420,"value":25983},{"type":415,"tag":532,"props":33972,"children":33973},{"style":804},[33974],{"type":420,"value":33655},{"type":415,"tag":532,"props":33976,"children":33977},{"style":804},[33978],{"type":420,"value":33660},{"type":415,"tag":532,"props":33980,"children":33981},{"style":804},[33982],{"type":420,"value":33983}," ad-admin",{"type":415,"tag":532,"props":33985,"children":33986},{"style":804},[33987],{"type":420,"value":25993},{"type":415,"tag":532,"props":33989,"children":33990},{"style":804},[33991],{"type":420,"value":33774},{"type":415,"tag":532,"props":33993,"children":33994},{"style":545},[33995],{"type":420,"value":33581},{"type":415,"tag":532,"props":33997,"children":33998},{"style":804},[33999],{"type":420,"value":34000},"--server-name",{"type":415,"tag":532,"props":34002,"children":34003},{"style":545},[34004],{"type":420,"value":33673},{"type":415,"tag":532,"props":34006,"children":34007},{"style":804},[34008],{"type":420,"value":34009},"--display-name",{"type":415,"tag":532,"props":34011,"children":34012},{"style":804},[34013],{"type":420,"value":34014}," ADMIN",{"type":415,"tag":532,"props":34016,"children":34017},{"style":804},[34018],{"type":420,"value":34019}," --object-id",{"type":415,"tag":532,"props":34021,"children":34022},{"style":545},[34023],{"type":420,"value":34024}," $azureaduser\n",{"type":415,"tag":532,"props":34026,"children":34027},{"class":534,"line":6266},[34028],{"type":415,"tag":532,"props":34029,"children":34030},{"emptyLinePlaceholder":621},[34031],{"type":420,"value":624},{"type":415,"tag":532,"props":34033,"children":34034},{"class":534,"line":6274},[34035,34039,34043,34048,34053,34058,34062,34067,34071,34075,34079],{"type":415,"tag":532,"props":34036,"children":34037},{"style":656},[34038],{"type":420,"value":33533},{"type":415,"tag":532,"props":34040,"children":34041},{"style":551},[34042],{"type":420,"value":4041},{"type":415,"tag":532,"props":34044,"children":34045},{"style":804},[34046],{"type":420,"value":34047},"Database connection string to use: ",{"type":415,"tag":532,"props":34049,"children":34050},{"style":545},[34051],{"type":420,"value":34052},"\\\"",{"type":415,"tag":532,"props":34054,"children":34055},{"style":804},[34056],{"type":420,"value":34057},"Server=",{"type":415,"tag":532,"props":34059,"children":34060},{"style":545},[34061],{"type":420,"value":33626},{"type":415,"tag":532,"props":34063,"children":34064},{"style":804},[34065],{"type":420,"value":34066},".database.windows.net; Authentication=Active Directory Default; Database=",{"type":415,"tag":532,"props":34068,"children":34069},{"style":545},[34070],{"type":420,"value":33843},{"type":415,"tag":532,"props":34072,"children":34073},{"style":804},[34074],{"type":420,"value":15807},{"type":415,"tag":532,"props":34076,"children":34077},{"style":545},[34078],{"type":420,"value":34052},{"type":415,"tag":532,"props":34080,"children":34081},{"style":551},[34082],{"type":420,"value":4051},{"type":415,"tag":416,"props":34084,"children":34085},{},[34086],{"type":420,"value":34087},"This script should be self-explanatory if you have already played a little with Azure CLI. Basically, what it does is:",{"type":415,"tag":508,"props":34089,"children":34090},{},[34091,34096,34108,34113,34118],{"type":415,"tag":512,"props":34092,"children":34093},{},[34094],{"type":420,"value":34095},"create an azure SQL server",{"type":415,"tag":512,"props":34097,"children":34098},{},[34099,34101,34106],{"type":420,"value":34100},"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":415,"tag":468,"props":34102,"children":34104},{"className":34103},[],[34105],{"type":420,"value":33390},{"type":420,"value":34107}," variable with your local machine IP)",{"type":415,"tag":512,"props":34109,"children":34110},{},[34111],{"type":420,"value":34112},"create an azure SQL database with already tables and data in it from the sample AdventureWorksLT",{"type":415,"tag":512,"props":34114,"children":34115},{},[34116],{"type":420,"value":34117},"set you logged in azure ad user as the AD administrator of the database",{"type":415,"tag":512,"props":34119,"children":34120},{},[34121],{"type":420,"value":34122},"write in the console the connection string to use in your C# code to access the database",{"type":415,"tag":416,"props":34124,"children":34125},{},[34126],{"type":420,"value":34127},"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":415,"tag":434,"props":34129,"children":34130},{"icon":1382},[34131],{"type":415,"tag":416,"props":34132,"children":34133},{},[34134,34136,34141],{"type":420,"value":34135},"If you are new to Azure CLI, you can read my article ",{"type":415,"tag":423,"props":34137,"children":34139},{"href":4423,"rel":34138},[427],[34140],{"type":420,"value":15},{"type":420,"value":432},{"type":415,"tag":3914,"props":34143,"children":34145},{"id":34144},"querying-the-database-from-a-minima-api-in-c",[34146],{"type":420,"value":34147},"Querying the database from a minima API in C#",{"type":415,"tag":416,"props":34149,"children":34150},{},[34151,34153,34160],{"type":420,"value":34152},"Usually, I like to create a console application (with the ",{"type":415,"tag":423,"props":34154,"children":34157},{"href":34155,"rel":34156},"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio#worker-service-template",[427],[34158],{"type":420,"value":34159},"worker service template",{"type":420,"value":34161}," for instance) for my samples, yet this time I decided to try the new minimal APIs from .NET 6 (currently in preview).",{"type":415,"tag":416,"props":34163,"children":34164},{},[34165,34167,34172],{"type":420,"value":34166},"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":415,"tag":468,"props":34168,"children":34170},{"className":34169},[],[34171],{"type":420,"value":20062},{"type":420,"value":34173}," 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":415,"tag":523,"props":34175,"children":34177},{"className":525,"code":34176,"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",[34178],{"type":415,"tag":468,"props":34179,"children":34180},{"__ignoreMap":401},[34181,34197,34228,34235,34276,34308,34315,34352,34359,34380,34387,34394,34442,34449,34498,34561,34576,34583,34590,34609,34616],{"type":415,"tag":532,"props":34182,"children":34183},{"class":534,"line":535},[34184,34188,34193],{"type":415,"tag":532,"props":34185,"children":34186},{"style":539},[34187],{"type":420,"value":542},{"type":415,"tag":532,"props":34189,"children":34190},{"style":545},[34191],{"type":420,"value":34192}," Dapper",{"type":415,"tag":532,"props":34194,"children":34195},{"style":551},[34196],{"type":420,"value":563},{"type":415,"tag":532,"props":34198,"children":34199},{"class":534,"line":566},[34200,34204,34208,34212,34216,34220,34224],{"type":415,"tag":532,"props":34201,"children":34202},{"style":539},[34203],{"type":420,"value":542},{"type":415,"tag":532,"props":34205,"children":34206},{"style":545},[34207],{"type":420,"value":593},{"type":415,"tag":532,"props":34209,"children":34210},{"style":551},[34211],{"type":420,"value":432},{"type":415,"tag":532,"props":34213,"children":34214},{"style":545},[34215],{"type":420,"value":8799},{"type":415,"tag":532,"props":34217,"children":34218},{"style":551},[34219],{"type":420,"value":432},{"type":415,"tag":532,"props":34221,"children":34222},{"style":545},[34223],{"type":420,"value":32981},{"type":415,"tag":532,"props":34225,"children":34226},{"style":551},[34227],{"type":420,"value":563},{"type":415,"tag":532,"props":34229,"children":34230},{"class":534,"line":583},[34231],{"type":415,"tag":532,"props":34232,"children":34233},{"emptyLinePlaceholder":621},[34234],{"type":420,"value":624},{"type":415,"tag":532,"props":34236,"children":34237},{"class":534,"line":617},[34238,34242,34246,34250,34255,34259,34264,34268,34272],{"type":415,"tag":532,"props":34239,"children":34240},{"style":631},[34241],{"type":420,"value":634},{"type":415,"tag":532,"props":34243,"children":34244},{"style":631},[34245],{"type":420,"value":639},{"type":415,"tag":532,"props":34247,"children":34248},{"style":551},[34249],{"type":420,"value":644},{"type":415,"tag":532,"props":34251,"children":34252},{"style":545},[34253],{"type":420,"value":34254}," WebApplication",{"type":415,"tag":532,"props":34256,"children":34257},{"style":551},[34258],{"type":420,"value":432},{"type":415,"tag":532,"props":34260,"children":34261},{"style":656},[34262],{"type":420,"value":34263},"CreateBuilder",{"type":415,"tag":532,"props":34265,"children":34266},{"style":551},[34267],{"type":420,"value":664},{"type":415,"tag":532,"props":34269,"children":34270},{"style":545},[34271],{"type":420,"value":669},{"type":415,"tag":532,"props":34273,"children":34274},{"style":551},[34275],{"type":420,"value":674},{"type":415,"tag":532,"props":34277,"children":34278},{"class":534,"line":627},[34279,34283,34288,34292,34296,34300,34304],{"type":415,"tag":532,"props":34280,"children":34281},{"style":631},[34282],{"type":420,"value":634},{"type":415,"tag":532,"props":34284,"children":34285},{"style":631},[34286],{"type":420,"value":34287}," app",{"type":415,"tag":532,"props":34289,"children":34290},{"style":551},[34291],{"type":420,"value":644},{"type":415,"tag":532,"props":34293,"children":34294},{"style":545},[34295],{"type":420,"value":639},{"type":415,"tag":532,"props":34297,"children":34298},{"style":551},[34299],{"type":420,"value":432},{"type":415,"tag":532,"props":34301,"children":34302},{"style":656},[34303],{"type":420,"value":894},{"type":415,"tag":532,"props":34305,"children":34306},{"style":551},[34307],{"type":420,"value":899},{"type":415,"tag":532,"props":34309,"children":34310},{"class":534,"line":677},[34311],{"type":415,"tag":532,"props":34312,"children":34313},{"emptyLinePlaceholder":621},[34314],{"type":420,"value":624},{"type":415,"tag":532,"props":34316,"children":34317},{"class":534,"line":719},[34318,34323,34327,34332,34336,34340,34344,34348],{"type":415,"tag":532,"props":34319,"children":34320},{"style":1241},[34321],{"type":420,"value":34322},"if",{"type":415,"tag":532,"props":34324,"children":34325},{"style":551},[34326],{"type":420,"value":1249},{"type":415,"tag":532,"props":34328,"children":34329},{"style":545},[34330],{"type":420,"value":34331},"app",{"type":415,"tag":532,"props":34333,"children":34334},{"style":551},[34335],{"type":420,"value":432},{"type":415,"tag":532,"props":34337,"children":34338},{"style":545},[34339],{"type":420,"value":29695},{"type":415,"tag":532,"props":34341,"children":34342},{"style":551},[34343],{"type":420,"value":432},{"type":415,"tag":532,"props":34345,"children":34346},{"style":656},[34347],{"type":420,"value":28872},{"type":415,"tag":532,"props":34349,"children":34350},{"style":551},[34351],{"type":420,"value":1882},{"type":415,"tag":532,"props":34353,"children":34354},{"class":534,"line":758},[34355],{"type":415,"tag":532,"props":34356,"children":34357},{"style":551},[34358],{"type":420,"value":764},{"type":415,"tag":532,"props":34360,"children":34361},{"class":534,"line":767},[34362,34367,34371,34376],{"type":415,"tag":532,"props":34363,"children":34364},{"style":545},[34365],{"type":420,"value":34366},"    app",{"type":415,"tag":532,"props":34368,"children":34369},{"style":551},[34370],{"type":420,"value":432},{"type":415,"tag":532,"props":34372,"children":34373},{"style":656},[34374],{"type":420,"value":34375},"UseDeveloperExceptionPage",{"type":415,"tag":532,"props":34377,"children":34378},{"style":551},[34379],{"type":420,"value":899},{"type":415,"tag":532,"props":34381,"children":34382},{"class":534,"line":819},[34383],{"type":415,"tag":532,"props":34384,"children":34385},{"style":551},[34386],{"type":420,"value":1379},{"type":415,"tag":532,"props":34388,"children":34389},{"class":534,"line":850},[34390],{"type":415,"tag":532,"props":34391,"children":34392},{"emptyLinePlaceholder":621},[34393],{"type":420,"value":624},{"type":415,"tag":532,"props":34395,"children":34396},{"class":534,"line":859},[34397,34401,34405,34410,34414,34418,34422,34426,34430,34434,34438],{"type":415,"tag":532,"props":34398,"children":34399},{"style":545},[34400],{"type":420,"value":34331},{"type":415,"tag":532,"props":34402,"children":34403},{"style":551},[34404],{"type":420,"value":432},{"type":415,"tag":532,"props":34406,"children":34407},{"style":656},[34408],{"type":420,"value":34409},"MapGet",{"type":415,"tag":532,"props":34411,"children":34412},{"style":551},[34413],{"type":420,"value":664},{"type":415,"tag":532,"props":34415,"children":34416},{"style":551},[34417],{"type":420,"value":801},{"type":415,"tag":532,"props":34419,"children":34420},{"style":804},[34421],{"type":420,"value":4728},{"type":415,"tag":532,"props":34423,"children":34424},{"style":551},[34425],{"type":420,"value":801},{"type":415,"tag":532,"props":34427,"children":34428},{"style":551},[34429],{"type":420,"value":1099},{"type":415,"tag":532,"props":34431,"children":34432},{"style":954},[34433],{"type":420,"value":1195},{"type":415,"tag":532,"props":34435,"children":34436},{"style":551},[34437],{"type":420,"value":3342},{"type":415,"tag":532,"props":34439,"children":34440},{"style":551},[34441],{"type":420,"value":755},{"type":415,"tag":532,"props":34443,"children":34444},{"class":534,"line":867},[34445],{"type":415,"tag":532,"props":34446,"children":34447},{"style":551},[34448],{"type":420,"value":764},{"type":415,"tag":532,"props":34450,"children":34451},{"class":534,"line":902},[34452,34457,34461,34465,34469,34473,34477,34481,34485,34490,34494],{"type":415,"tag":532,"props":34453,"children":34454},{"style":1241},[34455],{"type":420,"value":34456},"    using",{"type":415,"tag":532,"props":34458,"children":34459},{"style":631},[34460],{"type":420,"value":22149},{"type":415,"tag":532,"props":34462,"children":34463},{"style":631},[34464],{"type":420,"value":32604},{"type":415,"tag":532,"props":34466,"children":34467},{"style":551},[34468],{"type":420,"value":644},{"type":415,"tag":532,"props":34470,"children":34471},{"style":551},[34472],{"type":420,"value":3276},{"type":415,"tag":532,"props":34474,"children":34475},{"style":631},[34476],{"type":420,"value":32578},{"type":415,"tag":532,"props":34478,"children":34479},{"style":551},[34480],{"type":420,"value":664},{"type":415,"tag":532,"props":34482,"children":34483},{"style":551},[34484],{"type":420,"value":801},{"type":415,"tag":532,"props":34486,"children":34487},{"style":804},[34488],{"type":420,"value":34489},"Server=server-testingmsi28497.database.windows.net; Authentication=Active Directory Default; Database=database-testingmsi28497;",{"type":415,"tag":532,"props":34491,"children":34492},{"style":551},[34493],{"type":420,"value":801},{"type":415,"tag":532,"props":34495,"children":34496},{"style":551},[34497],{"type":420,"value":674},{"type":415,"tag":532,"props":34499,"children":34500},{"class":534,"line":1302},[34501,34505,34510,34514,34518,34522,34526,34531,34535,34540,34544,34548,34553,34557],{"type":415,"tag":532,"props":34502,"children":34503},{"style":631},[34504],{"type":420,"value":8661},{"type":415,"tag":532,"props":34506,"children":34507},{"style":631},[34508],{"type":420,"value":34509}," products",{"type":415,"tag":532,"props":34511,"children":34512},{"style":551},[34513],{"type":420,"value":644},{"type":415,"tag":532,"props":34515,"children":34516},{"style":551},[34517],{"type":420,"value":32729},{"type":415,"tag":532,"props":34519,"children":34520},{"style":545},[34521],{"type":420,"value":32604},{"type":415,"tag":532,"props":34523,"children":34524},{"style":551},[34525],{"type":420,"value":432},{"type":415,"tag":532,"props":34527,"children":34528},{"style":656},[34529],{"type":420,"value":34530},"QueryAsync",{"type":415,"tag":532,"props":34532,"children":34533},{"style":551},[34534],{"type":420,"value":706},{"type":415,"tag":532,"props":34536,"children":34537},{"style":631},[34538],{"type":420,"value":34539},"Product",{"type":415,"tag":532,"props":34541,"children":34542},{"style":551},[34543],{"type":420,"value":30080},{"type":415,"tag":532,"props":34545,"children":34546},{"style":551},[34547],{"type":420,"value":801},{"type":415,"tag":532,"props":34549,"children":34550},{"style":804},[34551],{"type":420,"value":34552},"SELECT TOP 10 ProductID, Name from [SalesLT].[Product]",{"type":415,"tag":532,"props":34554,"children":34555},{"style":551},[34556],{"type":420,"value":801},{"type":415,"tag":532,"props":34558,"children":34559},{"style":551},[34560],{"type":420,"value":674},{"type":415,"tag":532,"props":34562,"children":34563},{"class":534,"line":1311},[34564,34568,34572],{"type":415,"tag":532,"props":34565,"children":34566},{"style":1241},[34567],{"type":420,"value":8778},{"type":415,"tag":532,"props":34569,"children":34570},{"style":545},[34571],{"type":420,"value":34509},{"type":415,"tag":532,"props":34573,"children":34574},{"style":551},[34575],{"type":420,"value":563},{"type":415,"tag":532,"props":34577,"children":34578},{"class":534,"line":1356},[34579],{"type":415,"tag":532,"props":34580,"children":34581},{"style":551},[34582],{"type":420,"value":856},{"type":415,"tag":532,"props":34584,"children":34585},{"class":534,"line":1365},[34586],{"type":415,"tag":532,"props":34587,"children":34588},{"emptyLinePlaceholder":621},[34589],{"type":420,"value":624},{"type":415,"tag":532,"props":34591,"children":34592},{"class":534,"line":1373},[34593,34597,34601,34605],{"type":415,"tag":532,"props":34594,"children":34595},{"style":545},[34596],{"type":420,"value":34331},{"type":415,"tag":532,"props":34598,"children":34599},{"style":551},[34600],{"type":420,"value":432},{"type":415,"tag":532,"props":34602,"children":34603},{"style":656},[34604],{"type":420,"value":917},{"type":415,"tag":532,"props":34606,"children":34607},{"style":551},[34608],{"type":420,"value":899},{"type":415,"tag":532,"props":34610,"children":34611},{"class":534,"line":3825},[34612],{"type":415,"tag":532,"props":34613,"children":34614},{"emptyLinePlaceholder":621},[34615],{"type":420,"value":624},{"type":415,"tag":532,"props":34617,"children":34618},{"class":534,"line":3843},[34619,34623,34628,34633,34638,34643,34647,34651,34656],{"type":415,"tag":532,"props":34620,"children":34621},{"style":954},[34622],{"type":420,"value":957},{"type":415,"tag":532,"props":34624,"children":34625},{"style":631},[34626],{"type":420,"value":34627}," record",{"type":415,"tag":532,"props":34629,"children":34630},{"style":631},[34631],{"type":420,"value":34632}," Product",{"type":415,"tag":532,"props":34634,"children":34635},{"style":551},[34636],{"type":420,"value":34637},"(int",{"type":415,"tag":532,"props":34639,"children":34640},{"style":631},[34641],{"type":420,"value":34642}," ProductID",{"type":415,"tag":532,"props":34644,"children":34645},{"style":551},[34646],{"type":420,"value":1099},{"type":415,"tag":532,"props":34648,"children":34649},{"style":551},[34650],{"type":420,"value":32764},{"type":415,"tag":532,"props":34652,"children":34653},{"style":631},[34654],{"type":420,"value":34655}," Name",{"type":415,"tag":532,"props":34657,"children":34658},{"style":551},[34659],{"type":420,"value":674},{"type":415,"tag":416,"props":34661,"children":34662},{},[34663],{"type":420,"value":34664},"As you can see this code is only 26 lines long:",{"type":415,"tag":508,"props":34666,"children":34667},{},[34668,34681,34693,34705],{"type":415,"tag":512,"props":34669,"children":34670},{},[34671,34673,34679],{"type":420,"value":34672},"there is only one route, that returns the Product identifiers and names from the table ",{"type":415,"tag":468,"props":34674,"children":34676},{"className":34675},[],[34677],{"type":420,"value":34678},"[SalesLT].[Product]",{"type":420,"value":34680}," of the database created with the previous Azure CLI script",{"type":415,"tag":512,"props":34682,"children":34683},{},[34684,34686,34691],{"type":420,"value":34685},"the SQL query is done by using the micro ORM ",{"type":415,"tag":423,"props":34687,"children":34689},{"href":23883,"rel":34688},[427],[34690],{"type":420,"value":23887},{"type":420,"value":34692}," which simplifies the boilerplate code to query an SQL database while keeping performance",{"type":415,"tag":512,"props":34694,"children":34695},{},[34696,34698,34703],{"type":420,"value":34697},"the result of the SQL query is mapped to a record class ",{"type":415,"tag":468,"props":34699,"children":34701},{"className":34700},[],[34702],{"type":420,"value":34539},{"type":420,"value":34704}," which is declared in one line",{"type":415,"tag":512,"props":34706,"children":34707},{},[34708,34710,34715,34717,34722],{"type":420,"value":34709},"the code uses ",{"type":415,"tag":468,"props":34711,"children":34713},{"className":34712},[],[34714],{"type":420,"value":22719},{"type":420,"value":34716}," v3.0.0 with the ",{"type":415,"tag":468,"props":34718,"children":34720},{"className":34719},[],[34721],{"type":420,"value":32438},{"type":420,"value":32956},{"type":415,"tag":416,"props":34724,"children":34725},{},[34726],{"type":415,"tag":3882,"props":34727,"children":34731},{"alt":34728,"className":34729,"src":34730},"C# code querying an SQL Database using Active Directory Default authentication mode.",[3886,3887],"/posts/images/sqlclient_minapi_1.png",[],{"type":415,"tag":434,"props":34733,"children":34734},{"icon":1382},[34735],{"type":415,"tag":416,"props":34736,"children":34737},{},[34738,34740,34746],{"type":420,"value":34739},"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":415,"tag":423,"props":34741,"children":34744},{"href":34742,"rel":34743},"https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi#grant-permissions-to-managed-identity",[427],[34745],{"type":420,"value":4427},{"type":420,"value":34747}," for more information on how to do that.",{"type":415,"tag":482,"props":34749,"children":34750},{"id":10889},[34751],{"type":420,"value":10892},{"type":415,"tag":416,"props":34753,"children":34754},{},[34755,34757,34763],{"type":420,"value":34756},"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":415,"tag":468,"props":34758,"children":34760},{"className":34759},[],[34761],{"type":420,"value":34762},"Microsoft.Data.Sql.Client",{"type":420,"value":34764}," 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":415,"tag":3470,"props":34766,"children":34767},{},[34768],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":34770},[34771,34772,34773,34775,34779],{"id":32471,"depth":566,"text":32474},{"id":32664,"depth":566,"text":32667},{"id":32946,"depth":566,"text":34774},"Here comes Active Directory Default authentication mode",{"id":33086,"depth":566,"text":33089,"children":34776},[34777,34778],{"id":33097,"depth":583,"text":33100},{"id":34144,"depth":583,"text":34147},{"id":10889,"depth":566,"text":10892},"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":34783,"lead":34784,"date":34785,"image":34786,"badge":34787,"tags":34788,"body":34789,"_type":3483,"_id":35135,"_source":3485,"_file":35136,"_extension":3487},"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":28110},{"label":28112},[272,208,225,228],{"type":412,"children":34790,"toc":35130},[34791,34795,34801,34806,34819,34828,34833,34846,34852,34872,34881,34907,34927,34969,34974,35085,35091,35103,35108,35117,35122,35126],{"type":415,"tag":416,"props":34792,"children":34793},{},[34794],{"type":420,"value":34783},{"type":415,"tag":482,"props":34796,"children":34798},{"id":34797},"autocompletion-and-schema-validation-when-editing-a-json-file-in-vscode",[34799],{"type":420,"value":34800},"Autocompletion and schema validation when editing a JSON file in vscode.",{"type":415,"tag":416,"props":34802,"children":34803},{},[34804],{"type":420,"value":34805},"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":415,"tag":416,"props":34807,"children":34808},{},[34809,34811,34817],{"type":420,"value":34810},"Well in fact it is possible, you just have to add at the beginning of your file a ",{"type":415,"tag":468,"props":34812,"children":34814},{"className":34813},[],[34815],{"type":420,"value":34816},"$schema",{"type":420,"value":34818}," key (with the URI of the JSON schema as the value) and you will have IntelliSense to edit your JSON in vscode.",{"type":415,"tag":416,"props":34820,"children":34821},{},[34822],{"type":415,"tag":3882,"props":34823,"children":34827},{"alt":34824,"className":34825,"src":34826},"Json file in vscode.",[3886,3887],"/posts/images/w222021tips_vscode_1.png",[],{"type":415,"tag":416,"props":34829,"children":34830},{},[34831],{"type":420,"value":34832},"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":415,"tag":416,"props":34834,"children":34835},{},[34836,34838,34845],{"type":420,"value":34837},"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":415,"tag":423,"props":34839,"children":34842},{"href":34840,"rel":34841},"https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings",[427],[34843],{"type":420,"value":34844},"vscode documentation",{"type":420,"value":432},{"type":415,"tag":482,"props":34847,"children":34849},{"id":34848},"listing-assigned-roles-for-a-user-on-a-subscription-with-azure-cli",[34850],{"type":420,"value":34851},"Listing assigned roles for a user on a subscription with Azure CLI",{"type":415,"tag":416,"props":34853,"children":34854},{},[34855,34857,34870],{"type":420,"value":34856},"I recently had to list all the roles assigned to my user on a subscription. 👮‍♀️\nFor that I used the ",{"type":415,"tag":423,"props":34858,"children":34861},{"href":34859,"rel":34860},"https://docs.microsoft.com/en-us/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_list",[427],[34862,34868],{"type":415,"tag":468,"props":34863,"children":34865},{"className":34864},[],[34866],{"type":420,"value":34867},"az role assignment list",{"type":420,"value":34869}," command",{"type":420,"value":34871}," like this:",{"type":415,"tag":416,"props":34873,"children":34874},{},[34875],{"type":415,"tag":3882,"props":34876,"children":34880},{"alt":34877,"className":34878,"src":34879},"Terminal showing az role assigment command.",[3886,3887],"/posts/images/w222021tips_azcli_1.png",[],{"type":415,"tag":416,"props":34882,"children":34883},{},[34884,34886,34891,34893,34899,34900,34906],{"type":420,"value":34885},"I am filtering the command result with the ",{"type":415,"tag":468,"props":34887,"children":34889},{"className":34888},[],[34890],{"type":420,"value":4410},{"type":420,"value":34892}," argument to only have the information I am interested in which are ",{"type":415,"tag":468,"props":34894,"children":34896},{"className":34895},[],[34897],{"type":420,"value":34898},"roleDefinitionName",{"type":420,"value":6722},{"type":415,"tag":468,"props":34901,"children":34903},{"className":34902},[],[34904],{"type":420,"value":34905},"scope",{"type":420,"value":432},{"type":415,"tag":416,"props":34908,"children":34909},{},[34910,34912,34918,34920,34926],{"type":420,"value":34911},"You can specify a subscription by using the optional parameter ",{"type":415,"tag":468,"props":34913,"children":34915},{"className":34914},[],[34916],{"type":420,"value":34917},"--subscription",{"type":420,"value":34919}," but by default, the subscription selected is the current subscription which you can see by doing an ",{"type":415,"tag":468,"props":34921,"children":34923},{"className":34922},[],[34924],{"type":420,"value":34925},"az account show",{"type":420,"value":432},{"type":415,"tag":416,"props":34928,"children":34929},{},[34930,34932,34938,34940,34946,34948,34954,34956,34967],{"type":420,"value":34931},"The variable ",{"type":415,"tag":468,"props":34933,"children":34935},{"className":34934},[],[34936],{"type":420,"value":34937},"UserId",{"type":420,"value":34939}," which is passed to the option ",{"type":415,"tag":468,"props":34941,"children":34943},{"className":34942},[],[34944],{"type":420,"value":34945},"--assignee",{"type":420,"value":34947}," 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":415,"tag":468,"props":34949,"children":34951},{"className":34950},[],[34952],{"type":420,"value":34953},"#EXT#",{"type":420,"value":34955}," 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":415,"tag":423,"props":34957,"children":34960},{"href":34958,"rel":34959},"https://docs.microsoft.com/en-us/cli/azure/ad/user?view=azure-cli-latest#az_ad_user_show",[427],[34961],{"type":415,"tag":468,"props":34962,"children":34964},{"className":34963},[],[34965],{"type":420,"value":34966},"az ad signed-in-user show",{"type":420,"value":34968}," command to get my user id.",{"type":415,"tag":416,"props":34970,"children":34971},{},[34972],{"type":420,"value":34973},"So at the end my command to list the assigned roles to my user on the current subscription is the following:",{"type":415,"tag":523,"props":34975,"children":34977},{"className":4059,"code":34976,"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",[34978],{"type":415,"tag":468,"props":34979,"children":34980},{"__ignoreMap":401},[34981],{"type":415,"tag":532,"props":34982,"children":34983},{"class":534,"line":535},[34984,34989,34993,34997,35002,35006,35010,35014,35018,35022,35026,35030,35034,35038,35042,35046,35050,35054,35058,35063,35067,35071,35076,35080],{"type":415,"tag":532,"props":34985,"children":34986},{"style":545},[34987],{"type":420,"value":34988},"az role assignment list ",{"type":415,"tag":532,"props":34990,"children":34991},{"style":551},[34992],{"type":420,"value":4115},{"type":415,"tag":532,"props":34994,"children":34995},{"style":545},[34996],{"type":420,"value":26878},{"type":415,"tag":532,"props":34998,"children":34999},{"style":551},[35000],{"type":420,"value":35001},"$(",{"type":415,"tag":532,"props":35003,"children":35004},{"style":545},[35005],{"type":420,"value":26757},{"type":415,"tag":532,"props":35007,"children":35008},{"style":551},[35009],{"type":420,"value":4216},{"type":415,"tag":532,"props":35011,"children":35012},{"style":545},[35013],{"type":420,"value":26766},{"type":415,"tag":532,"props":35015,"children":35016},{"style":551},[35017],{"type":420,"value":4216},{"type":415,"tag":532,"props":35019,"children":35020},{"style":545},[35021],{"type":420,"value":26775},{"type":415,"tag":532,"props":35023,"children":35024},{"style":551},[35025],{"type":420,"value":4115},{"type":415,"tag":532,"props":35027,"children":35028},{"style":545},[35029],{"type":420,"value":4317},{"type":415,"tag":532,"props":35031,"children":35032},{"style":551},[35033],{"type":420,"value":801},{"type":415,"tag":532,"props":35035,"children":35036},{"style":804},[35037],{"type":420,"value":12332},{"type":415,"tag":532,"props":35039,"children":35040},{"style":551},[35041],{"type":420,"value":801},{"type":415,"tag":532,"props":35043,"children":35044},{"style":551},[35045],{"type":420,"value":1349},{"type":415,"tag":532,"props":35047,"children":35048},{"style":551},[35049],{"type":420,"value":4139},{"type":415,"tag":532,"props":35051,"children":35052},{"style":545},[35053],{"type":420,"value":4317},{"type":415,"tag":532,"props":35055,"children":35056},{"style":551},[35057],{"type":420,"value":801},{"type":415,"tag":532,"props":35059,"children":35060},{"style":804},[35061],{"type":420,"value":35062},"[*].{role:roleDefinitionName,scope:scope}",{"type":415,"tag":532,"props":35064,"children":35065},{"style":551},[35066],{"type":420,"value":801},{"type":415,"tag":532,"props":35068,"children":35069},{"style":551},[35070],{"type":420,"value":4139},{"type":415,"tag":532,"props":35072,"children":35073},{"style":545},[35074],{"type":420,"value":35075},"include",{"type":415,"tag":532,"props":35077,"children":35078},{"style":551},[35079],{"type":420,"value":4216},{"type":415,"tag":532,"props":35081,"children":35082},{"style":545},[35083],{"type":420,"value":35084},"inherited\n",{"type":415,"tag":482,"props":35086,"children":35088},{"id":35087},"azure-storage-explorer-just-got-better",[35089],{"type":420,"value":35090},"Azure Storage Explorer just got better!",{"type":415,"tag":416,"props":35092,"children":35093},{},[35094,35101],{"type":415,"tag":423,"props":35095,"children":35098},{"href":35096,"rel":35097},"https://azure.microsoft.com/en-us/features/storage-explorer/",[427],[35099],{"type":420,"value":35100},"Azure Storage Explorer",{"type":420,"value":35102}," 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":415,"tag":416,"props":35104,"children":35105},{},[35106],{"type":420,"value":35107},"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":415,"tag":416,"props":35109,"children":35110},{},[35111],{"type":415,"tag":3882,"props":35112,"children":35116},{"alt":35113,"className":35114,"src":35115},"Azure Storage Explorer account management section.",[3886,3887],"/posts/images/w222021tips_storageexplorer_1.png",[],{"type":415,"tag":416,"props":35118,"children":35119},{},[35120],{"type":420,"value":35121},"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":415,"tag":416,"props":35123,"children":35124},{},[35125],{"type":420,"value":28461},{"type":415,"tag":3470,"props":35127,"children":35128},{},[35129],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":35131},[35132,35133,35134],{"id":34797,"depth":566,"text":34800},{"id":34848,"depth":566,"text":34851},{"id":35087,"depth":566,"text":35090},"content:1.posts:19.w22-2021-tips-learned-this-week.md","1.posts/19.w22-2021-tips-learned-this-week.md",{"_path":52,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":51,"description":35138,"lead":35139,"date":35140,"image":35141,"badge":35142,"tags":35143,"body":35144,"_type":3483,"_id":35314,"_source":3485,"_file":35315,"_extension":3487},"This week I learned a few things related to vscode and especially about the Azure IoT Hub vscode extension.","Azure tenant in vs code and Azure IoT Hub vs code extension.","2021-04-10T00:00:00.000Z",{"src":28110},{"label":28112},[272,208,284,228],{"type":412,"children":35145,"toc":35310},[35146,35159,35165,35179,35199,35208,35223,35229,35234,35246,35255,35260,35269,35274,35283,35297,35306],{"type":415,"tag":416,"props":35147,"children":35148},{},[35149,35151,35157],{"type":420,"value":35150},"This week I learned a few things related to vscode and especially about the ",{"type":415,"tag":468,"props":35152,"children":35154},{"className":35153},[],[35155],{"type":420,"value":35156},"Azure IoT Hub",{"type":420,"value":35158}," vscode extension.",{"type":415,"tag":482,"props":35160,"children":35162},{"id":35161},"accessing-azure-resources-in-vscode-from-a-specific-tenant",[35163],{"type":420,"value":35164},"Accessing Azure resources in vscode from a specific tenant.",{"type":415,"tag":416,"props":35166,"children":35167},{},[35168,35170,35177],{"type":420,"value":35169},"There are a lot of vscode extensions (like the ones in ",{"type":415,"tag":423,"props":35171,"children":35174},{"href":35172,"rel":35173},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack",[427],[35175],{"type":420,"value":35176},"this extension pack",{"type":420,"value":35178},") that allow you to access and manipulate your Azure resources from Visual Studio Code.",{"type":415,"tag":416,"props":35180,"children":35181},{},[35182,35184,35197],{"type":420,"value":35183},"This ",{"type":415,"tag":423,"props":35185,"children":35188},{"href":35186,"rel":35187},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account",[427],[35189,35191],{"type":420,"value":35190},"specific extension ",{"type":415,"tag":468,"props":35192,"children":35194},{"className":35193},[],[35195],{"type":420,"value":35196},"Azure Account",{"type":420,"value":35198}," makes it easy for you to sign in to your Azure account and select the subscription you want to use. But what if you are working in a consulting company that works for different companies? How do you indicate the tenant of the customer to sign in to? Well, the answer is quite simple, the extension exposes a setting in vscode to specify a specific tenant to use.",{"type":415,"tag":416,"props":35200,"children":35201},{},[35202],{"type":415,"tag":3882,"props":35203,"children":35207},{"alt":35204,"className":35205,"src":35206},"Azure tenant settings in vscode.",[3886,3887],"/posts/images/w142021tips_vscode_1.png",[],{"type":415,"tag":434,"props":35209,"children":35211},{"icon":35210},"i-fluent-emoji-flat-pushpin",[35212],{"type":415,"tag":416,"props":35213,"children":35214},{},[35215,35217],{"type":420,"value":35216},"If you like to update the settings in JSON mode the key to use is ",{"type":415,"tag":468,"props":35218,"children":35220},{"className":35219},[],[35221],{"type":420,"value":35222},"azure.tenant",{"type":415,"tag":482,"props":35224,"children":35226},{"id":35225},"azure-iot-hub-vs-code-extension-is-awesome",[35227],{"type":420,"value":35228},"Azure IoT Hub vs code extension is awesome.",{"type":415,"tag":416,"props":35230,"children":35231},{},[35232],{"type":420,"value":35233},"I think everything is in the title. I knew about this extension before this week but I did not take the time to really use it. However this week it helped me a lot for my sprint demo where I needed to show new functionalities I implemented on an IoT backend: modify device twin tags in the IoT Hub and send some messages to an IoT device under certain conditions.",{"type":415,"tag":416,"props":35235,"children":35236},{},[35237,35239,35244],{"type":420,"value":35238},"The Azure IoT Hub extension adds an ",{"type":415,"tag":468,"props":35240,"children":35242},{"className":35241},[],[35243],{"type":420,"value":35156},{"type":420,"value":35245}," view in the Explorer where you can see the devices of the IoT Hub you selected and can do some actions on them.",{"type":415,"tag":416,"props":35247,"children":35248},{},[35249],{"type":415,"tag":3882,"props":35250,"children":35254},{"alt":35251,"className":35252,"src":35253},"Azure IoT Hub view in vscode.",[3886,3887],"/posts/images/w142021tips_vscode_2.png",[],{"type":415,"tag":416,"props":35256,"children":35257},{},[35258],{"type":420,"value":35259},"There are also a lot of commands you can use to interact with an IoT Hub and its devices.",{"type":415,"tag":416,"props":35261,"children":35262},{},[35263],{"type":415,"tag":3882,"props":35264,"children":35268},{"alt":35265,"className":35266,"src":35267},"Azure IoT Hub commands in vscode command palette.",[3886,3887],"/posts/images/w142021tips_vscode_3.png",[],{"type":415,"tag":416,"props":35270,"children":35271},{},[35272],{"type":420,"value":35273},"You can do pretty much anything you want from sending C2D / D2C messages to monitoring C2D / D2C messages. I found it quite nice to be able to directly visualize and edit a device twin as a JSON  document in vs code.",{"type":415,"tag":416,"props":35275,"children":35276},{},[35277],{"type":415,"tag":3882,"props":35278,"children":35282},{"alt":35279,"className":35280,"src":35281},"Device twin json in vscode.",[3886,3887],"/posts/images/w142021tips_vscode_4.png",[],{"type":415,"tag":416,"props":35284,"children":35285},{},[35286,35288,35295],{"type":420,"value":35287},"To quickly test something related to IoT Hub, the Azure IoT Hub extension is a very useful tool. An interesting alternative to this tool is the ",{"type":415,"tag":423,"props":35289,"children":35292},{"href":35290,"rel":35291},"https://github.com/Azure/azure-iot-explorer/releases",[427],[35293],{"type":420,"value":35294},"Azure IoT Explorer",{"type":420,"value":35296}," which is more user-friendly thanks to its simple UI but does not have all the features.",{"type":415,"tag":416,"props":35298,"children":35299},{},[35300],{"type":415,"tag":3882,"props":35301,"children":35305},{"alt":35302,"className":35303,"src":35304},"Device twin json in Azure Iot Explorer.",[3886,3887],"/posts/images/w142021tips_iotexplorer_1.png",[],{"type":415,"tag":416,"props":35307,"children":35308},{},[35309],{"type":420,"value":28461},{"title":401,"searchDepth":566,"depth":566,"links":35311},[35312,35313],{"id":35161,"depth":566,"text":35164},{"id":35225,"depth":566,"text":35228},"content:1.posts:15.w14-2021-tips-learned-this-week.md","1.posts/15.w14-2021-tips-learned-this-week.md",{"_path":37,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":36,"description":35317,"lead":35318,"date":35319,"image":35320,"badge":35322,"tags":35323,"body":35324,"_type":3483,"_id":35702,"_source":3485,"_file":35703,"_extension":3487},"The possibility to add configuration sources in Azure Functions has just been released with the latest version of Microsoft.Azure.Functions.Extensions NuGet package. I have been waiting for this feature for a long time (like many people I think) because it brings to Azure Functions all the things we are used to with configuration in ASP.NET Core 😻. But that is not the only reason, it is also because with this feature you almost don't need to use key vault references!","Talking about how to manage configuration secrets in Azure Functions.","2020-09-21T00:00:00.000Z",{"src":35321},"/images/lightning_1.jpg",{"label":408},[257,260,228,263],{"type":412,"children":35325,"toc":35694},[35326,35347,35352,35358,35385,35394,35407,35416,35421,35427,35439,35444,35453,35458,35509,35520,35529,35534,35547,35558,35600,35609,35614,35623,35628,35634,35668,35676,35681,35685,35690],{"type":415,"tag":416,"props":35327,"children":35328},{},[35329,35331,35337,35338,35345],{"type":420,"value":35330},"The possibility to add configuration sources in Azure Functions has just been released with the latest version of ",{"type":415,"tag":468,"props":35332,"children":35334},{"className":35333},[],[35335],{"type":420,"value":35336},"Microsoft.Azure.Functions.Extensions",{"type":420,"value":16037},{"type":415,"tag":423,"props":35339,"children":35342},{"href":35340,"rel":35341},"https://www.nuget.org/packages/Microsoft.Azure.Functions.Extensions/1.1.0",[427],[35343],{"type":420,"value":35344},"NuGet package",{"type":420,"value":35346},". I have been waiting for this feature for a long time (like many people I think) because it brings to Azure Functions all the things we are used to with configuration in ASP.NET Core 😻. But that is not the only reason, it is also because with this feature you almost don't need to use key vault references!",{"type":415,"tag":416,"props":35348,"children":35349},{},[35350],{"type":420,"value":35351},"But before deep dive into this topic, let's give a bit of context about configuration and secrets in Azure Functions (just skip the next section if you already are familiar with all that).",{"type":415,"tag":482,"props":35353,"children":35355},{"id":35354},"a-quick-reminder-about-configuration-and-secrets-in-azure-functions",[35356],{"type":420,"value":35357},"A quick reminder about configuration and secrets in Azure Functions",{"type":415,"tag":416,"props":35359,"children":35360},{},[35361,35363,35368,35370,35376,35378,35383],{"type":420,"value":35362},"Configuration used by functions in a Function App is stored in settings that can be set in the ",{"type":415,"tag":468,"props":35364,"children":35366},{"className":35365},[],[35367],{"type":420,"value":263},{"type":420,"value":35369}," section of a Function App in Azure Portal. When developing locally you have to use a ",{"type":415,"tag":468,"props":35371,"children":35373},{"className":35372},[],[35374],{"type":420,"value":35375},"local.settings.json",{"type":420,"value":35377}," file that will contain copies of the settings stored in Azure portal. The settings from ",{"type":415,"tag":468,"props":35379,"children":35381},{"className":35380},[],[35382],{"type":420,"value":35375},{"type":420,"value":35384}," will be loaded as environment variables when debugging locally. But as its name suggests, the purpose of this file is to be used for local development only: its settings are not used when the function runs on Azure. Furthermore, this file should never be committed to avoid putting settings corresponding to secrets in source control.",{"type":415,"tag":416,"props":35386,"children":35387},{},[35388],{"type":415,"tag":3882,"props":35389,"children":35393},{"alt":35390,"className":35391,"src":35392},"Azure Function local settings file.",[3886,3887],"/posts/images/functionssecrets_localsettings_1.png",[],{"type":415,"tag":416,"props":35395,"children":35396},{},[35397,35399,35405],{"type":420,"value":35398},"Speaking of secrets, they should never be directly stored in the application settings of a Function App (the same goes for App Services by the way). Why not? Because secrets would be available to  anyone who has access to the Function App in the Azure Portal. The right way is to use an Azure Key Vault which is the Azure component for securely storing and accessing secrets 🔒. Once your secrets are in the key vault, you have to grant the Key Vault access to the identity of your Function App and you can then reference the secrets you need directly in your application settings. These are called ",{"type":415,"tag":423,"props":35400,"children":35402},{"href":30580,"rel":35401},[427],[35403],{"type":420,"value":35404},"Key Vault references",{"type":420,"value":35406}," because an application setting does not contain directly the value of a secret but a reference to the secret which is stored in Key Vault. When running, your function will automatically have access to the secret and its value as an environment variable, as if it was a normal application setting.",{"type":415,"tag":416,"props":35408,"children":35409},{},[35410],{"type":415,"tag":3882,"props":35411,"children":35415},{"alt":35412,"className":35413,"src":35414},"Function App application settings in Azure portal.",[3886,3887],"/posts/images/functionssecrets_portal_1.png",[],{"type":415,"tag":416,"props":35417,"children":35418},{},[35419],{"type":420,"value":35420},"Key Vault references work for both App Services and Function Apps and are particularly useful for existing applications that have their secrets stored in settings because securing the secrets with Azure Key Vault references does not require any code change.",{"type":415,"tag":482,"props":35422,"children":35424},{"id":35423},"the-downside-of-key-vault-references-the-local-debugging-experience",[35425],{"type":420,"value":35426},"The downside of Key Vault references: the local debugging experience",{"type":415,"tag":416,"props":35428,"children":35429},{},[35430,35432,35437],{"type":420,"value":35431},"Do you remember when I told you that the local settings file should not be committed to your git repository? Well, what you might not have realized is that it means when someone from your team clones the git repository containing your function he won't have this ",{"type":415,"tag":468,"props":35433,"children":35435},{"className":35434},[],[35436],{"type":420,"value":35375},{"type":420,"value":35438}," file which is mandatory to run your function app locally. And even if he creates manually the file, he will not necessarily know which settings to put in it. But we want to avoid him manually copying all the settings from the Azure portal or asking a colleague to send his local settings file by email (which is a really bad practice if it contains secrets). Hopefully, there are some ways to fill or generate this file.",{"type":415,"tag":416,"props":35440,"children":35441},{},[35442],{"type":420,"value":35443},"If you use Visual Studio there is a GUI that will help you compare/modify local settings and Azure settings.",{"type":415,"tag":416,"props":35445,"children":35446},{},[35447],{"type":415,"tag":3882,"props":35448,"children":35452},{"alt":35449,"className":35450,"src":35451},"Function App application settings in Visual Studio.",[3886,3887],"/posts/images/functionssecrets_vs_1.png",[],{"type":415,"tag":416,"props":35454,"children":35455},{},[35456],{"type":420,"value":35457},"And whether or not you are using Visual Studio, you can generate the local settings file filled with Azure settings with a few Azure Functions CLI commands:",{"type":415,"tag":523,"props":35459,"children":35461},{"className":3984,"code":35460,"language":3986,"meta":401,"style":401},"func azure functionapp fetch-app-settings $FUNCTION_APP_NAME\nfunc settings decrypt\n",[35462],{"type":415,"tag":468,"props":35463,"children":35464},{"__ignoreMap":401},[35465,35493],{"type":415,"tag":532,"props":35466,"children":35467},{"class":534,"line":535},[35468,35473,35478,35483,35488],{"type":415,"tag":532,"props":35469,"children":35470},{"style":631},[35471],{"type":420,"value":35472},"func",{"type":415,"tag":532,"props":35474,"children":35475},{"style":804},[35476],{"type":420,"value":35477}," azure",{"type":415,"tag":532,"props":35479,"children":35480},{"style":804},[35481],{"type":420,"value":35482}," functionapp",{"type":415,"tag":532,"props":35484,"children":35485},{"style":804},[35486],{"type":420,"value":35487}," fetch-app-settings",{"type":415,"tag":532,"props":35489,"children":35490},{"style":545},[35491],{"type":420,"value":35492}," $FUNCTION_APP_NAME\n",{"type":415,"tag":532,"props":35494,"children":35495},{"class":534,"line":566},[35496,35500,35504],{"type":415,"tag":532,"props":35497,"children":35498},{"style":631},[35499],{"type":420,"value":35472},{"type":415,"tag":532,"props":35501,"children":35502},{"style":804},[35503],{"type":420,"value":30005},{"type":415,"tag":532,"props":35505,"children":35506},{"style":804},[35507],{"type":420,"value":35508}," decrypt\n",{"type":415,"tag":416,"props":35510,"children":35511},{},[35512,35514,35519],{"type":420,"value":35513},"This is an example of a generated ",{"type":415,"tag":468,"props":35515,"children":35517},{"className":35516},[],[35518],{"type":420,"value":35375},{"type":420,"value":11550},{"type":415,"tag":416,"props":35521,"children":35522},{},[35523],{"type":415,"tag":3882,"props":35524,"children":35528},{"alt":35525,"className":35526,"src":35527},"Generated local settings file.",[3886,3887],"/posts/images/functionssecrets_localsettings_2.png",[],{"type":415,"tag":416,"props":35530,"children":35531},{},[35532],{"type":420,"value":35533},"However, as you can see, the settings corresponding to secrets contain the Key Vault reference values that are used by Azure to link the settings to the secrets. But this is an Azure mechanism, locally the true secrets value won't be loaded into configuration. So you will have to manually retrieve the value of the secrets in your key vault and set them manually in your local settings file. That may be okay for one secret but that gets quickly annoying when you have many secrets. You don't want your team members to constantly lose time copying secret values from the key vault on their local environment. I don't even talk about the loss of time understanding what is wrong when a secret value has changed and you did not realize it or the bad habits it could lead to like sending secrets by email or chat messages.",{"type":415,"tag":416,"props":35535,"children":35536},{},[35537,35539,35546],{"type":420,"value":35538},"This is a terrible local debugging experience and honestly, you don't want that. What you want is that your function code just works when you or one of your colleagues clones or pulls a new version of the function app code. When debugging locally the code of an ASP.NET Core application deployed in an App Service you don't have this kind of problem because usually your code directly loads the secrets from the Key Vault thanks to ",{"type":415,"tag":423,"props":35540,"children":35543},{"href":35541,"rel":35542},"https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-3.1",[427],[35544],{"type":420,"value":35545},"Key Vault configuration provider",{"type":420,"value":432},{"type":415,"tag":482,"props":35548,"children":35550},{"id":35549},"here-comes-ifunctionsconfigurationbuilder",[35551,35552],{"type":420,"value":32949},{"type":415,"tag":468,"props":35553,"children":35555},{"className":35554},[],[35556],{"type":420,"value":35557},"IFunctionsConfigurationBuilder",{"type":415,"tag":416,"props":35559,"children":35560},{},[35561,35563,35568,35570,35576,35578,35584,35586,35591,35593,35598],{"type":420,"value":35562},"If you are already familiar with dependency injection in Azure Functions, you already know the ",{"type":415,"tag":468,"props":35564,"children":35566},{"className":35565},[],[35567],{"type":420,"value":35336},{"type":420,"value":35569}," NuGet package that allows you to inherit from the ",{"type":415,"tag":468,"props":35571,"children":35573},{"className":35572},[],[35574],{"type":420,"value":35575},"FunctionStartup",{"type":420,"value":35577}," abstract class and register the different services you want to inject into your functions (you can find more about that in the ",{"type":415,"tag":423,"props":35579,"children":35582},{"href":35580,"rel":35581},"https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection",[427],[35583],{"type":420,"value":499},{"type":420,"value":35585},"). In the latest version of this NuGet package, a new virtual method has been added to ",{"type":415,"tag":468,"props":35587,"children":35589},{"className":35588},[],[35590],{"type":420,"value":35575},{"type":420,"value":35592},": ",{"type":415,"tag":468,"props":35594,"children":35596},{"className":35595},[],[35597],{"type":420,"value":28581},{"type":420,"value":35599},". It allows you to specify additional configuration sources you would need in your functions.",{"type":415,"tag":416,"props":35601,"children":35602},{},[35603],{"type":415,"tag":3882,"props":35604,"children":35608},{"alt":35605,"className":35606,"src":35607},"FunctionsStartup abstract class.",[3886,3887],"/posts/images/functionssecrets_vs_2.png",[],{"type":415,"tag":416,"props":35610,"children":35611},{},[35612],{"type":420,"value":35613},"What is awesome is that you can use all the configuration providers you are used to in ASP.NET Core and that includes the Key Vault Configuration provider. I think you understand what I am getting at 😉: instead of using key vault references in your function app settings, you can simply retrieve the secrets from your key vault thanks to the configuration provider.",{"type":415,"tag":416,"props":35615,"children":35616},{},[35617],{"type":415,"tag":3882,"props":35618,"children":35622},{"alt":35619,"className":35620,"src":35621},"Debugging configuration in Startup file in Visual Studio.",[3886,3887],"/posts/images/functionssecrets_vs_3.png",[],{"type":415,"tag":416,"props":35624,"children":35625},{},[35626],{"type":420,"value":35627},"This way, no more copying secret, no more storing secrets values locally, no more wondering if you have the latest version of a secret. Say goodbye to key vault references, pull the latest version of your code, press F5 and it will work!",{"type":415,"tag":482,"props":35629,"children":35631},{"id":35630},"the-triggers-case",[35632],{"type":420,"value":35633},"The triggers case",{"type":415,"tag":416,"props":35635,"children":35636},{},[35637,35639,35651,35653,35657,35659,35666],{"type":420,"value":35638},"Well in my title I said ",{"type":415,"tag":7033,"props":35640,"children":35641},{},[35642,35644,35649],{"type":420,"value":35643},"\"you ",{"type":415,"tag":6864,"props":35645,"children":35646},{},[35647],{"type":420,"value":35648},"almost",{"type":420,"value":35650}," no longer need key vault references\"",{"type":420,"value":35652}," and the ",{"type":415,"tag":6864,"props":35654,"children":35655},{},[35656],{"type":420,"value":35648},{"type":420,"value":35658}," is important. As the ",{"type":415,"tag":423,"props":35660,"children":35663},{"href":35661,"rel":35662},"https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources",[427],[35664],{"type":420,"value":35665},"Azure Functions documentation",{"type":420,"value":35667}," about customizing configuration sources mentions:",{"type":415,"tag":434,"props":35669,"children":35670},{"icon":436},[35671],{"type":415,"tag":416,"props":35672,"children":35673},{},[35674],{"type":420,"value":35675},"For function apps running in the Consumption or Premium plans, modifications to configuration values used in triggers can cause scaling errors. Any changes to these properties by the FunctionsStartup class result in a function app startup error.",{"type":415,"tag":416,"props":35677,"children":35678},{},[35679],{"type":420,"value":35680},"Therefore, if you use a trigger that needs a secret (the connection string of an EventHub trigger for instance), you have no other choice than to use a key vault reference. But for everything else you are good to go with Azure Key Vault configuration provider.",{"type":415,"tag":482,"props":35682,"children":35683},{"id":10889},[35684],{"type":420,"value":10892},{"type":415,"tag":416,"props":35686,"children":35687},{},[35688],{"type":420,"value":35689},"To summarize, after a quick recall of how Azure Functions configuration works we have seen how Key Vault references can help to avoid having secret values in settings. We talked about the downside of this approach for the local development experience and how using the Azure Key Vault configuration provider solved that except when a secret is needed in a trigger.",{"type":415,"tag":3470,"props":35691,"children":35692},{},[35693],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":35695},[35696,35697,35698,35700,35701],{"id":35354,"depth":566,"text":35357},{"id":35423,"depth":566,"text":35426},{"id":35549,"depth":566,"text":35699},"Here comes IFunctionsConfigurationBuilder",{"id":35630,"depth":566,"text":35633},{"id":10889,"depth":566,"text":10892},"content:1.posts:10.azure-functions-custom-configuration.md","1.posts/10.azure-functions-custom-configuration.md",{"_path":16,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":15,"description":35705,"lead":35706,"date":35707,"image":35708,"badge":35710,"tags":35712,"body":35713,"_type":3483,"_id":38185,"_source":3485,"_file":38186,"_extension":3487},"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":35709},"/images/green-characters.jpg",{"label":35711},"Tooling",[225,228,230],{"type":412,"children":35714,"toc":38168},[35715,35720,35768,35781,35787,35817,35826,35831,35836,35842,35855,35860,35896,35929,35940,35983,36008,36028,36037,36049,36055,36061,36070,36097,36106,36123,36129,36134,36142,36414,36420,36433,36445,36458,37438,37443,37457,37466,37480,37489,37503,37512,37528,37534,37539,37544,37828,37833,37839,37844,37850,37855,37860,37883,37889,37894,37903,37915,37924,37929,37938,37944,37957,37962,37970,37983,37992,37997,38009,38015,38020,38033,38042,38075,38084,38103,38112,38117,38133,38150,38154,38159,38164],{"type":415,"tag":416,"props":35716,"children":35717},{},[35718],{"type":420,"value":35719},"In this article about Azure CLI, we will talk about:",{"type":415,"tag":508,"props":35721,"children":35722},{},[35723,35732,35741,35750,35759],{"type":415,"tag":512,"props":35724,"children":35725},{},[35726],{"type":415,"tag":423,"props":35727,"children":35729},{"href":35728},"#_1-managing-azure-resources",[35730],{"type":420,"value":35731},"Managing Azure resources",{"type":415,"tag":512,"props":35733,"children":35734},{},[35735],{"type":415,"tag":423,"props":35736,"children":35738},{"href":35737},"#_2-azure-cli-syntax",[35739],{"type":420,"value":35740},"Azure CLI Syntax",{"type":415,"tag":512,"props":35742,"children":35743},{},[35744],{"type":415,"tag":423,"props":35745,"children":35747},{"href":35746},"#_3-deep-dive-in-azure-cli",[35748],{"type":420,"value":35749},"Deep dive in Azure CLI",{"type":415,"tag":512,"props":35751,"children":35752},{},[35753],{"type":415,"tag":423,"props":35754,"children":35756},{"href":35755},"#_4-where-to-use-azure-cli",[35757],{"type":420,"value":35758},"Where to use Azure CLI",{"type":415,"tag":512,"props":35760,"children":35761},{},[35762],{"type":415,"tag":423,"props":35763,"children":35765},{"href":35764},"#_5-azure-cli-interactive-mode",[35766],{"type":420,"value":35767},"Azure CLI Interactive mode",{"type":415,"tag":416,"props":35769,"children":35770},{},[35771,35773,35780],{"type":420,"value":35772},"Azure CLI can be installed by following the instructions on ",{"type":415,"tag":423,"props":35774,"children":35777},{"href":35775,"rel":35776},"https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest",[427],[35778],{"type":420,"value":35779},"this page",{"type":420,"value":432},{"type":415,"tag":482,"props":35782,"children":35784},{"id":35783},"_1-managing-azure-resources",[35785],{"type":420,"value":35786},"1 - Managing Azure resources",{"type":415,"tag":416,"props":35788,"children":35789},{},[35790,35792,35799,35800,35807,35809,35815],{"type":420,"value":35791},"Azure resources can be managed in different ways but the main ones are the ",{"type":415,"tag":423,"props":35793,"children":35796},{"href":35794,"rel":35795},"https://portal.azure.com",[427],[35797],{"type":420,"value":35798},"Azure Portal",{"type":420,"value":8073},{"type":415,"tag":423,"props":35801,"children":35804},{"href":35802,"rel":35803},"https://docs.microsoft.com/en-us/powershell/azure/",[427],[35805],{"type":420,"value":35806},"Azure PowerShell",{"type":420,"value":35808},", and ",{"type":415,"tag":423,"props":35810,"children":35813},{"href":35811,"rel":35812},"https://docs.microsoft.com/en-us/cli/azure",[427],[35814],{"type":420,"value":225},{"type":420,"value":35816},". 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":415,"tag":416,"props":35818,"children":35819},{},[35820],{"type":415,"tag":3882,"props":35821,"children":35825},{"alt":35822,"className":35823,"src":35824},"Azure portal home",[3886,3887],"/posts/images/azurecli_portal_1.png",[],{"type":415,"tag":416,"props":35827,"children":35828},{},[35829],{"type":420,"value":35830},"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":415,"tag":416,"props":35832,"children":35833},{},[35834],{"type":420,"value":35835},"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":415,"tag":482,"props":35837,"children":35839},{"id":35838},"_2-azure-cli-syntax",[35840],{"type":420,"value":35841},"2 - Azure CLI Syntax",{"type":415,"tag":416,"props":35843,"children":35844},{},[35845,35847,35853],{"type":420,"value":35846},"The Azure CLI Syntax is simple to understand. For instance, the command ",{"type":415,"tag":468,"props":35848,"children":35850},{"className":35849},[],[35851],{"type":420,"value":35852},"az webapp list",{"type":420,"value":35854}," will list the WebApps in the subscription you are currently logged in.",{"type":415,"tag":416,"props":35856,"children":35857},{},[35858],{"type":420,"value":35859},"An Azure CLI command has the following structure:",{"type":415,"tag":508,"props":35861,"children":35862},{},[35863,35875,35886],{"type":415,"tag":512,"props":35864,"children":35865},{},[35866,35868,35873],{"type":420,"value":35867},"a ",{"type":415,"tag":6864,"props":35869,"children":35870},{},[35871],{"type":420,"value":35872},"command group",{"type":420,"value":35874}," that represents an Azure service and which can be the composition of subgroups",{"type":415,"tag":512,"props":35876,"children":35877},{},[35878,35879,35884],{"type":420,"value":35867},{"type":415,"tag":6864,"props":35880,"children":35881},{},[35882],{"type":420,"value":35883},"command",{"type":420,"value":35885}," which is the action you want to do on the group / Azure service",{"type":415,"tag":512,"props":35887,"children":35888},{},[35889,35894],{"type":415,"tag":6864,"props":35890,"children":35891},{},[35892],{"type":420,"value":35893},"arguments",{"type":420,"value":35895}," optionally which are a list of parameter names and values",{"type":415,"tag":416,"props":35897,"children":35898},{},[35899,35901,35907,35908,35913,35915,35920,35922,35927],{"type":420,"value":35900},"To sign in to your Azure account in your terminal, you have to execute the Azure CLI command ",{"type":415,"tag":468,"props":35902,"children":35904},{"className":35903},[],[35905],{"type":420,"value":35906},"az login",{"type":420,"value":25744},{"type":415,"tag":468,"props":35909,"children":35911},{"className":35910},[],[35912],{"type":420,"value":25983},{"type":420,"value":35914}," is the command group and ",{"type":415,"tag":468,"props":35916,"children":35918},{"className":35917},[],[35919],{"type":420,"value":33312},{"type":420,"value":35921}," is the command relative to the group/service ",{"type":415,"tag":468,"props":35923,"children":35925},{"className":35924},[],[35926],{"type":420,"value":25983},{"type":420,"value":35928}," (meaning Azure).",{"type":415,"tag":416,"props":35930,"children":35931},{},[35932,35934,35939],{"type":420,"value":35933},"In our previous example, ",{"type":415,"tag":468,"props":35935,"children":35937},{"className":35936},[],[35938],{"type":420,"value":35852},{"type":420,"value":972},{"type":415,"tag":508,"props":35941,"children":35942},{},[35943,35967,35978],{"type":415,"tag":512,"props":35944,"children":35945},{},[35946,35952,35954,35959,35961],{"type":415,"tag":468,"props":35947,"children":35949},{"className":35948},[],[35950],{"type":420,"value":35951},"az webapp",{"type":420,"value":35953}," was the command group composed of ",{"type":415,"tag":468,"props":35955,"children":35957},{"className":35956},[],[35958],{"type":420,"value":25983},{"type":420,"value":35960}," and its subgroup ",{"type":415,"tag":468,"props":35962,"children":35964},{"className":35963},[],[35965],{"type":420,"value":35966},"webapp",{"type":415,"tag":512,"props":35968,"children":35969},{},[35970,35976],{"type":415,"tag":468,"props":35971,"children":35973},{"className":35972},[],[35974],{"type":420,"value":35975},"list",{"type":420,"value":35977}," was the command",{"type":415,"tag":512,"props":35979,"children":35980},{},[35981],{"type":420,"value":35982},"no arguments here",{"type":415,"tag":416,"props":35984,"children":35985},{},[35986,35988,35993,35995,36000,36002],{"type":420,"value":35987},"We could have added some arguments to this command, like the ",{"type":415,"tag":468,"props":35989,"children":35991},{"className":35990},[],[35992],{"type":420,"value":33678},{"type":420,"value":35994}," argument (or ",{"type":415,"tag":468,"props":35996,"children":35998},{"className":35997},[],[35999],{"type":420,"value":11484},{"type":420,"value":36001},") to list only the WebApps in a specific resource group and that would have become ",{"type":415,"tag":468,"props":36003,"children":36005},{"className":36004},[],[36006],{"type":420,"value":36007},"az webapp list --resource-group 'myResourceGroupName'",{"type":415,"tag":416,"props":36009,"children":36010},{},[36011,36013,36019,36021,36026],{"type":420,"value":36012},"A few arguments are globally available arguments which means that can be used for every command. This is the case of the ",{"type":415,"tag":468,"props":36014,"children":36016},{"className":36015},[],[36017],{"type":420,"value":36018},"--help",{"type":420,"value":36020}," argument which displays help information about a command. The following example showing the use of the ",{"type":415,"tag":468,"props":36022,"children":36024},{"className":36023},[],[36025],{"type":420,"value":36018},{"type":420,"value":36027}," argument allows us to better understand the structure of an Azure CLI command.",{"type":415,"tag":416,"props":36029,"children":36030},{},[36031],{"type":415,"tag":3882,"props":36032,"children":36036},{"alt":36033,"className":36034,"src":36035},"Azure CLI Help output.",[3886,3887],"/posts/images/azurecli_console_1.png",[],{"type":415,"tag":416,"props":36038,"children":36039},{},[36040,36042,36047],{"type":420,"value":36041},"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":415,"tag":468,"props":36043,"children":36045},{"className":36044},[],[36046],{"type":420,"value":36018},{"type":420,"value":36048},") and you will quickly get the job done.",{"type":415,"tag":482,"props":36050,"children":36052},{"id":36051},"_3-deep-dive-in-azure-cli",[36053],{"type":420,"value":36054},"3 - Deep dive in Azure CLI",{"type":415,"tag":3914,"props":36056,"children":36058},{"id":36057},"command-output",[36059],{"type":420,"value":36060},"Command output",{"type":415,"tag":416,"props":36062,"children":36063},{},[36064],{"type":415,"tag":3882,"props":36065,"children":36069},{"alt":36066,"className":36067,"src":36068},"Azure CLI command outputs.",[3886,3887],"/posts/images/azurecli_console_2.png",[],{"type":415,"tag":416,"props":36071,"children":36072},{},[36073,36075,36081,36083,36088,36090,36096],{"type":420,"value":36074},"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":415,"tag":468,"props":36076,"children":36078},{"className":36077},[],[36079],{"type":420,"value":36080},"--output",{"type":420,"value":36082}," or ",{"type":415,"tag":468,"props":36084,"children":36086},{"className":36085},[],[36087],{"type":420,"value":26129},{"type":420,"value":36089},") like this: ",{"type":415,"tag":468,"props":36091,"children":36093},{"className":36092},[],[36094],{"type":420,"value":36095},"az group list -o table",{"type":420,"value":432},{"type":415,"tag":416,"props":36098,"children":36099},{},[36100],{"type":415,"tag":3882,"props":36101,"children":36105},{"alt":36102,"className":36103,"src":36104},"Azure CLI json and table outputs.",[3886,3887],"/posts/images/azurecli_console_3.png",[],{"type":415,"tag":434,"props":36107,"children":36109},{"icon":36108},"i-fluent-emoji-flat-gem-stone",[36110],{"type":415,"tag":416,"props":36111,"children":36112},{},[36113,36115,36121],{"type":420,"value":36114},"The default output format can be configured using the ",{"type":415,"tag":468,"props":36116,"children":36118},{"className":36117},[],[36119],{"type":420,"value":36120},"az configure",{"type":420,"value":36122}," command. This command also allows you to configure other settings like a default resource group for your commands for instance.",{"type":415,"tag":3914,"props":36124,"children":36126},{"id":36125},"using-variables",[36127],{"type":420,"value":36128},"Using variables",{"type":415,"tag":416,"props":36130,"children":36131},{},[36132],{"type":420,"value":36133},"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":415,"tag":434,"props":36135,"children":36136},{"icon":1382},[36137],{"type":415,"tag":416,"props":36138,"children":36139},{},[36140],{"type":420,"value":36141},"The samples in this article use the PowerShell syntax.",{"type":415,"tag":523,"props":36143,"children":36145},{"className":4059,"code":36144,"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",[36146],{"type":415,"tag":468,"props":36147,"children":36148},{"__ignoreMap":401},[36149,36177,36184,36192,36224,36231,36239,36289,36296,36304,36345,36352,36360],{"type":415,"tag":532,"props":36150,"children":36151},{"class":534,"line":535},[36152,36156,36160,36164,36168,36173],{"type":415,"tag":532,"props":36153,"children":36154},{"style":551},[36155],{"type":420,"value":4072},{"type":415,"tag":532,"props":36157,"children":36158},{"style":545},[36159],{"type":420,"value":26221},{"type":415,"tag":532,"props":36161,"children":36162},{"style":551},[36163],{"type":420,"value":1134},{"type":415,"tag":532,"props":36165,"children":36166},{"style":551},[36167],{"type":420,"value":3697},{"type":415,"tag":532,"props":36169,"children":36170},{"style":804},[36171],{"type":420,"value":36172},"TestingAzureCLI",{"type":415,"tag":532,"props":36174,"children":36175},{"style":551},[36176],{"type":420,"value":3707},{"type":415,"tag":532,"props":36178,"children":36179},{"class":534,"line":566},[36180],{"type":415,"tag":532,"props":36181,"children":36182},{"emptyLinePlaceholder":621},[36183],{"type":420,"value":624},{"type":415,"tag":532,"props":36185,"children":36186},{"class":534,"line":583},[36187],{"type":415,"tag":532,"props":36188,"children":36189},{"style":5425},[36190],{"type":420,"value":36191},"# Create a new resource group\n",{"type":415,"tag":532,"props":36193,"children":36194},{"class":534,"line":617},[36195,36199,36203,36207,36211,36215,36219],{"type":415,"tag":532,"props":36196,"children":36197},{"style":545},[36198],{"type":420,"value":27350},{"type":415,"tag":532,"props":36200,"children":36201},{"style":551},[36202],{"type":420,"value":4216},{"type":415,"tag":532,"props":36204,"children":36205},{"style":545},[36206],{"type":420,"value":26194},{"type":415,"tag":532,"props":36208,"children":36209},{"style":551},[36210],{"type":420,"value":4072},{"type":415,"tag":532,"props":36212,"children":36213},{"style":545},[36214],{"type":420,"value":26221},{"type":415,"tag":532,"props":36216,"children":36217},{"style":551},[36218],{"type":420,"value":4216},{"type":415,"tag":532,"props":36220,"children":36221},{"style":545},[36222],{"type":420,"value":36223},"l westeurope\n",{"type":415,"tag":532,"props":36225,"children":36226},{"class":534,"line":627},[36227],{"type":415,"tag":532,"props":36228,"children":36229},{"emptyLinePlaceholder":621},[36230],{"type":420,"value":624},{"type":415,"tag":532,"props":36232,"children":36233},{"class":534,"line":677},[36234],{"type":415,"tag":532,"props":36235,"children":36236},{"style":5425},[36237],{"type":420,"value":36238},"# Create an App Service plan with the Free tier\n",{"type":415,"tag":532,"props":36240,"children":36241},{"class":534,"line":719},[36242,36247,36251,36255,36259,36264,36268,36272,36276,36280,36284],{"type":415,"tag":532,"props":36243,"children":36244},{"style":545},[36245],{"type":420,"value":36246},"az appservice plan create ",{"type":415,"tag":532,"props":36248,"children":36249},{"style":551},[36250],{"type":420,"value":4216},{"type":415,"tag":532,"props":36252,"children":36253},{"style":545},[36254],{"type":420,"value":26194},{"type":415,"tag":532,"props":36256,"children":36257},{"style":551},[36258],{"type":420,"value":4072},{"type":415,"tag":532,"props":36260,"children":36261},{"style":545},[36262],{"type":420,"value":36263},"webAppName ",{"type":415,"tag":532,"props":36265,"children":36266},{"style":551},[36267],{"type":420,"value":4216},{"type":415,"tag":532,"props":36269,"children":36270},{"style":545},[36271],{"type":420,"value":26212},{"type":415,"tag":532,"props":36273,"children":36274},{"style":551},[36275],{"type":420,"value":4072},{"type":415,"tag":532,"props":36277,"children":36278},{"style":545},[36279],{"type":420,"value":26221},{"type":415,"tag":532,"props":36281,"children":36282},{"style":551},[36283],{"type":420,"value":4115},{"type":415,"tag":532,"props":36285,"children":36286},{"style":545},[36287],{"type":420,"value":36288},"sku FREE\n",{"type":415,"tag":532,"props":36290,"children":36291},{"class":534,"line":758},[36292],{"type":415,"tag":532,"props":36293,"children":36294},{"emptyLinePlaceholder":621},[36295],{"type":420,"value":624},{"type":415,"tag":532,"props":36297,"children":36298},{"class":534,"line":767},[36299],{"type":415,"tag":532,"props":36300,"children":36301},{"style":5425},[36302],{"type":420,"value":36303},"# Show the App Service plan just created \n",{"type":415,"tag":532,"props":36305,"children":36306},{"class":534,"line":819},[36307,36312,36316,36320,36324,36328,36332,36336,36340],{"type":415,"tag":532,"props":36308,"children":36309},{"style":545},[36310],{"type":420,"value":36311},"az appservice plan show ",{"type":415,"tag":532,"props":36313,"children":36314},{"style":551},[36315],{"type":420,"value":4216},{"type":415,"tag":532,"props":36317,"children":36318},{"style":545},[36319],{"type":420,"value":26194},{"type":415,"tag":532,"props":36321,"children":36322},{"style":551},[36323],{"type":420,"value":4072},{"type":415,"tag":532,"props":36325,"children":36326},{"style":545},[36327],{"type":420,"value":36263},{"type":415,"tag":532,"props":36329,"children":36330},{"style":551},[36331],{"type":420,"value":4216},{"type":415,"tag":532,"props":36333,"children":36334},{"style":545},[36335],{"type":420,"value":26212},{"type":415,"tag":532,"props":36337,"children":36338},{"style":551},[36339],{"type":420,"value":4072},{"type":415,"tag":532,"props":36341,"children":36342},{"style":545},[36343],{"type":420,"value":36344},"rgName \n",{"type":415,"tag":532,"props":36346,"children":36347},{"class":534,"line":850},[36348],{"type":415,"tag":532,"props":36349,"children":36350},{"emptyLinePlaceholder":621},[36351],{"type":420,"value":624},{"type":415,"tag":532,"props":36353,"children":36354},{"class":534,"line":859},[36355],{"type":415,"tag":532,"props":36356,"children":36357},{"style":5425},[36358],{"type":420,"value":36359},"# Store the result of the show query in a PowerShell variable\n",{"type":415,"tag":532,"props":36361,"children":36362},{"class":534,"line":867},[36363,36367,36372,36376,36381,36385,36389,36393,36397,36401,36405,36409],{"type":415,"tag":532,"props":36364,"children":36365},{"style":551},[36366],{"type":420,"value":4072},{"type":415,"tag":532,"props":36368,"children":36369},{"style":545},[36370],{"type":420,"value":36371},"servicePlan ",{"type":415,"tag":532,"props":36373,"children":36374},{"style":551},[36375],{"type":420,"value":1134},{"type":415,"tag":532,"props":36377,"children":36378},{"style":545},[36379],{"type":420,"value":36380}," az appservice plan show ",{"type":415,"tag":532,"props":36382,"children":36383},{"style":551},[36384],{"type":420,"value":4216},{"type":415,"tag":532,"props":36386,"children":36387},{"style":545},[36388],{"type":420,"value":26194},{"type":415,"tag":532,"props":36390,"children":36391},{"style":551},[36392],{"type":420,"value":4072},{"type":415,"tag":532,"props":36394,"children":36395},{"style":545},[36396],{"type":420,"value":36263},{"type":415,"tag":532,"props":36398,"children":36399},{"style":551},[36400],{"type":420,"value":4216},{"type":415,"tag":532,"props":36402,"children":36403},{"style":545},[36404],{"type":420,"value":26212},{"type":415,"tag":532,"props":36406,"children":36407},{"style":551},[36408],{"type":420,"value":4072},{"type":415,"tag":532,"props":36410,"children":36411},{"style":545},[36412],{"type":420,"value":36413},"rgName\n",{"type":415,"tag":3914,"props":36415,"children":36417},{"id":36416},"jmespath",[36418],{"type":420,"value":36419},"JMESPath",{"type":415,"tag":416,"props":36421,"children":36422},{},[36423,36425,36431],{"type":420,"value":36424},"If you don't know ",{"type":415,"tag":423,"props":36426,"children":36429},{"href":36427,"rel":36428},"http://jmespath.org/",[427],[36430],{"type":420,"value":36419},{"type":420,"value":36432},", 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":415,"tag":416,"props":36434,"children":36435},{},[36436,36438,36443],{"type":420,"value":36437},"To use JMESPath you have to add in your CLI command the argument ",{"type":415,"tag":468,"props":36439,"children":36441},{"className":36440},[],[36442],{"type":420,"value":4410},{"type":420,"value":36444}," followed by your JMESPath query.\nLet's see that with some examples.",{"type":415,"tag":416,"props":36446,"children":36447},{},[36448,36450,36456],{"type":420,"value":36449},"The query ",{"type":415,"tag":468,"props":36451,"children":36453},{"className":36452},[],[36454],{"type":420,"value":36455},"az group list",{"type":420,"value":36457}," executed on my subscription returns the following JSON:",{"type":415,"tag":523,"props":36459,"children":36463},{"className":36460,"code":36461,"language":36462,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[\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","json",[36464],{"type":415,"tag":468,"props":36465,"children":36466},{"__ignoreMap":401},[36467,36475,36483,36520,36556,36581,36617,36641,36675,36682,36706,36738,36745,36770,36778,36785,36821,36857,36880,36916,36939,36970,36977,37000,37037,37069,37076,37099,37106,37113,37149,37184,37207,37242,37265,37296,37303,37326,37361,37392,37399,37422,37430],{"type":415,"tag":532,"props":36468,"children":36469},{"class":534,"line":535},[36470],{"type":415,"tag":532,"props":36471,"children":36472},{"style":551},[36473],{"type":420,"value":36474},"[\n",{"type":415,"tag":532,"props":36476,"children":36477},{"class":534,"line":566},[36478],{"type":415,"tag":532,"props":36479,"children":36480},{"style":551},[36481],{"type":420,"value":36482},"  {\n",{"type":415,"tag":532,"props":36484,"children":36485},{"class":534,"line":583},[36486,36491,36495,36499,36503,36507,36512,36516],{"type":415,"tag":532,"props":36487,"children":36488},{"style":551},[36489],{"type":420,"value":36490},"    \"",{"type":415,"tag":532,"props":36492,"children":36493},{"style":954},[36494],{"type":420,"value":4326},{"type":415,"tag":532,"props":36496,"children":36497},{"style":551},[36498],{"type":420,"value":801},{"type":415,"tag":532,"props":36500,"children":36501},{"style":551},[36502],{"type":420,"value":1290},{"type":415,"tag":532,"props":36504,"children":36505},{"style":551},[36506],{"type":420,"value":4041},{"type":415,"tag":532,"props":36508,"children":36509},{"style":804},[36510],{"type":420,"value":36511},"/subscriptions/********-****-****-****-************/resourceGroups/CloudShellRG",{"type":415,"tag":532,"props":36513,"children":36514},{"style":551},[36515],{"type":420,"value":801},{"type":415,"tag":532,"props":36517,"children":36518},{"style":551},[36519],{"type":420,"value":7400},{"type":415,"tag":532,"props":36521,"children":36522},{"class":534,"line":617},[36523,36527,36531,36535,36539,36543,36548,36552],{"type":415,"tag":532,"props":36524,"children":36525},{"style":551},[36526],{"type":420,"value":36490},{"type":415,"tag":532,"props":36528,"children":36529},{"style":954},[36530],{"type":420,"value":25872},{"type":415,"tag":532,"props":36532,"children":36533},{"style":551},[36534],{"type":420,"value":801},{"type":415,"tag":532,"props":36536,"children":36537},{"style":551},[36538],{"type":420,"value":1290},{"type":415,"tag":532,"props":36540,"children":36541},{"style":551},[36542],{"type":420,"value":4041},{"type":415,"tag":532,"props":36544,"children":36545},{"style":804},[36546],{"type":420,"value":36547},"westeurope",{"type":415,"tag":532,"props":36549,"children":36550},{"style":551},[36551],{"type":420,"value":801},{"type":415,"tag":532,"props":36553,"children":36554},{"style":551},[36555],{"type":420,"value":7400},{"type":415,"tag":532,"props":36557,"children":36558},{"class":534,"line":627},[36559,36563,36568,36572,36576],{"type":415,"tag":532,"props":36560,"children":36561},{"style":551},[36562],{"type":420,"value":36490},{"type":415,"tag":532,"props":36564,"children":36565},{"style":954},[36566],{"type":420,"value":36567},"managedBy",{"type":415,"tag":532,"props":36569,"children":36570},{"style":551},[36571],{"type":420,"value":801},{"type":415,"tag":532,"props":36573,"children":36574},{"style":551},[36575],{"type":420,"value":1290},{"type":415,"tag":532,"props":36577,"children":36578},{"style":551},[36579],{"type":420,"value":36580}," null,\n",{"type":415,"tag":532,"props":36582,"children":36583},{"class":534,"line":677},[36584,36588,36592,36596,36600,36604,36609,36613],{"type":415,"tag":532,"props":36585,"children":36586},{"style":551},[36587],{"type":420,"value":36490},{"type":415,"tag":532,"props":36589,"children":36590},{"style":954},[36591],{"type":420,"value":3535},{"type":415,"tag":532,"props":36593,"children":36594},{"style":551},[36595],{"type":420,"value":801},{"type":415,"tag":532,"props":36597,"children":36598},{"style":551},[36599],{"type":420,"value":1290},{"type":415,"tag":532,"props":36601,"children":36602},{"style":551},[36603],{"type":420,"value":4041},{"type":415,"tag":532,"props":36605,"children":36606},{"style":804},[36607],{"type":420,"value":36608},"CloudShellRG",{"type":415,"tag":532,"props":36610,"children":36611},{"style":551},[36612],{"type":420,"value":801},{"type":415,"tag":532,"props":36614,"children":36615},{"style":551},[36616],{"type":420,"value":7400},{"type":415,"tag":532,"props":36618,"children":36619},{"class":534,"line":719},[36620,36624,36629,36633,36637],{"type":415,"tag":532,"props":36621,"children":36622},{"style":551},[36623],{"type":420,"value":36490},{"type":415,"tag":532,"props":36625,"children":36626},{"style":954},[36627],{"type":420,"value":36628},"properties",{"type":415,"tag":532,"props":36630,"children":36631},{"style":551},[36632],{"type":420,"value":801},{"type":415,"tag":532,"props":36634,"children":36635},{"style":551},[36636],{"type":420,"value":1290},{"type":415,"tag":532,"props":36638,"children":36639},{"style":551},[36640],{"type":420,"value":11759},{"type":415,"tag":532,"props":36642,"children":36643},{"class":534,"line":758},[36644,36649,36654,36658,36662,36666,36671],{"type":415,"tag":532,"props":36645,"children":36646},{"style":551},[36647],{"type":420,"value":36648},"      \"",{"type":415,"tag":532,"props":36650,"children":36651},{"style":631},[36652],{"type":420,"value":36653},"provisioningState",{"type":415,"tag":532,"props":36655,"children":36656},{"style":551},[36657],{"type":420,"value":801},{"type":415,"tag":532,"props":36659,"children":36660},{"style":551},[36661],{"type":420,"value":1290},{"type":415,"tag":532,"props":36663,"children":36664},{"style":551},[36665],{"type":420,"value":4041},{"type":415,"tag":532,"props":36667,"children":36668},{"style":804},[36669],{"type":420,"value":36670},"Succeeded",{"type":415,"tag":532,"props":36672,"children":36673},{"style":551},[36674],{"type":420,"value":4051},{"type":415,"tag":532,"props":36676,"children":36677},{"class":534,"line":767},[36678],{"type":415,"tag":532,"props":36679,"children":36680},{"style":551},[36681],{"type":420,"value":7650},{"type":415,"tag":532,"props":36683,"children":36684},{"class":534,"line":819},[36685,36689,36694,36698,36702],{"type":415,"tag":532,"props":36686,"children":36687},{"style":551},[36688],{"type":420,"value":36490},{"type":415,"tag":532,"props":36690,"children":36691},{"style":954},[36692],{"type":420,"value":36693},"tags",{"type":415,"tag":532,"props":36695,"children":36696},{"style":551},[36697],{"type":420,"value":801},{"type":415,"tag":532,"props":36699,"children":36700},{"style":551},[36701],{"type":420,"value":1290},{"type":415,"tag":532,"props":36703,"children":36704},{"style":551},[36705],{"type":420,"value":11759},{"type":415,"tag":532,"props":36707,"children":36708},{"class":534,"line":850},[36709,36713,36717,36721,36725,36729,36734],{"type":415,"tag":532,"props":36710,"children":36711},{"style":551},[36712],{"type":420,"value":36648},{"type":415,"tag":532,"props":36714,"children":36715},{"style":631},[36716],{"type":420,"value":29695},{"type":415,"tag":532,"props":36718,"children":36719},{"style":551},[36720],{"type":420,"value":801},{"type":415,"tag":532,"props":36722,"children":36723},{"style":551},[36724],{"type":420,"value":1290},{"type":415,"tag":532,"props":36726,"children":36727},{"style":551},[36728],{"type":420,"value":4041},{"type":415,"tag":532,"props":36730,"children":36731},{"style":804},[36732],{"type":420,"value":36733},"Production",{"type":415,"tag":532,"props":36735,"children":36736},{"style":551},[36737],{"type":420,"value":4051},{"type":415,"tag":532,"props":36739,"children":36740},{"class":534,"line":859},[36741],{"type":415,"tag":532,"props":36742,"children":36743},{"style":551},[36744],{"type":420,"value":7650},{"type":415,"tag":532,"props":36746,"children":36747},{"class":534,"line":867},[36748,36752,36757,36761,36765],{"type":415,"tag":532,"props":36749,"children":36750},{"style":551},[36751],{"type":420,"value":36490},{"type":415,"tag":532,"props":36753,"children":36754},{"style":954},[36755],{"type":420,"value":36756},"type",{"type":415,"tag":532,"props":36758,"children":36759},{"style":551},[36760],{"type":420,"value":801},{"type":415,"tag":532,"props":36762,"children":36763},{"style":551},[36764],{"type":420,"value":1290},{"type":415,"tag":532,"props":36766,"children":36767},{"style":551},[36768],{"type":420,"value":36769}," null\n",{"type":415,"tag":532,"props":36771,"children":36772},{"class":534,"line":902},[36773],{"type":415,"tag":532,"props":36774,"children":36775},{"style":551},[36776],{"type":420,"value":36777},"  },\n",{"type":415,"tag":532,"props":36779,"children":36780},{"class":534,"line":1302},[36781],{"type":415,"tag":532,"props":36782,"children":36783},{"style":551},[36784],{"type":420,"value":36482},{"type":415,"tag":532,"props":36786,"children":36787},{"class":534,"line":1311},[36788,36792,36796,36800,36804,36808,36813,36817],{"type":415,"tag":532,"props":36789,"children":36790},{"style":551},[36791],{"type":420,"value":36490},{"type":415,"tag":532,"props":36793,"children":36794},{"style":954},[36795],{"type":420,"value":4326},{"type":415,"tag":532,"props":36797,"children":36798},{"style":551},[36799],{"type":420,"value":801},{"type":415,"tag":532,"props":36801,"children":36802},{"style":551},[36803],{"type":420,"value":1290},{"type":415,"tag":532,"props":36805,"children":36806},{"style":551},[36807],{"type":420,"value":4041},{"type":415,"tag":532,"props":36809,"children":36810},{"style":804},[36811],{"type":420,"value":36812},"/subscriptions/********-****-****-****-************/resourceGroups/MyApp1ResourceGroup",{"type":415,"tag":532,"props":36814,"children":36815},{"style":551},[36816],{"type":420,"value":801},{"type":415,"tag":532,"props":36818,"children":36819},{"style":551},[36820],{"type":420,"value":7400},{"type":415,"tag":532,"props":36822,"children":36823},{"class":534,"line":1356},[36824,36828,36832,36836,36840,36844,36849,36853],{"type":415,"tag":532,"props":36825,"children":36826},{"style":551},[36827],{"type":420,"value":36490},{"type":415,"tag":532,"props":36829,"children":36830},{"style":954},[36831],{"type":420,"value":25872},{"type":415,"tag":532,"props":36833,"children":36834},{"style":551},[36835],{"type":420,"value":801},{"type":415,"tag":532,"props":36837,"children":36838},{"style":551},[36839],{"type":420,"value":1290},{"type":415,"tag":532,"props":36841,"children":36842},{"style":551},[36843],{"type":420,"value":4041},{"type":415,"tag":532,"props":36845,"children":36846},{"style":804},[36847],{"type":420,"value":36848},"canadacentral",{"type":415,"tag":532,"props":36850,"children":36851},{"style":551},[36852],{"type":420,"value":801},{"type":415,"tag":532,"props":36854,"children":36855},{"style":551},[36856],{"type":420,"value":7400},{"type":415,"tag":532,"props":36858,"children":36859},{"class":534,"line":1365},[36860,36864,36868,36872,36876],{"type":415,"tag":532,"props":36861,"children":36862},{"style":551},[36863],{"type":420,"value":36490},{"type":415,"tag":532,"props":36865,"children":36866},{"style":954},[36867],{"type":420,"value":36567},{"type":415,"tag":532,"props":36869,"children":36870},{"style":551},[36871],{"type":420,"value":801},{"type":415,"tag":532,"props":36873,"children":36874},{"style":551},[36875],{"type":420,"value":1290},{"type":415,"tag":532,"props":36877,"children":36878},{"style":551},[36879],{"type":420,"value":36580},{"type":415,"tag":532,"props":36881,"children":36882},{"class":534,"line":1373},[36883,36887,36891,36895,36899,36903,36908,36912],{"type":415,"tag":532,"props":36884,"children":36885},{"style":551},[36886],{"type":420,"value":36490},{"type":415,"tag":532,"props":36888,"children":36889},{"style":954},[36890],{"type":420,"value":3535},{"type":415,"tag":532,"props":36892,"children":36893},{"style":551},[36894],{"type":420,"value":801},{"type":415,"tag":532,"props":36896,"children":36897},{"style":551},[36898],{"type":420,"value":1290},{"type":415,"tag":532,"props":36900,"children":36901},{"style":551},[36902],{"type":420,"value":4041},{"type":415,"tag":532,"props":36904,"children":36905},{"style":804},[36906],{"type":420,"value":36907},"MyApp1ResourceGroup",{"type":415,"tag":532,"props":36909,"children":36910},{"style":551},[36911],{"type":420,"value":801},{"type":415,"tag":532,"props":36913,"children":36914},{"style":551},[36915],{"type":420,"value":7400},{"type":415,"tag":532,"props":36917,"children":36918},{"class":534,"line":3825},[36919,36923,36927,36931,36935],{"type":415,"tag":532,"props":36920,"children":36921},{"style":551},[36922],{"type":420,"value":36490},{"type":415,"tag":532,"props":36924,"children":36925},{"style":954},[36926],{"type":420,"value":36628},{"type":415,"tag":532,"props":36928,"children":36929},{"style":551},[36930],{"type":420,"value":801},{"type":415,"tag":532,"props":36932,"children":36933},{"style":551},[36934],{"type":420,"value":1290},{"type":415,"tag":532,"props":36936,"children":36937},{"style":551},[36938],{"type":420,"value":11759},{"type":415,"tag":532,"props":36940,"children":36941},{"class":534,"line":3843},[36942,36946,36950,36954,36958,36962,36966],{"type":415,"tag":532,"props":36943,"children":36944},{"style":551},[36945],{"type":420,"value":36648},{"type":415,"tag":532,"props":36947,"children":36948},{"style":631},[36949],{"type":420,"value":36653},{"type":415,"tag":532,"props":36951,"children":36952},{"style":551},[36953],{"type":420,"value":801},{"type":415,"tag":532,"props":36955,"children":36956},{"style":551},[36957],{"type":420,"value":1290},{"type":415,"tag":532,"props":36959,"children":36960},{"style":551},[36961],{"type":420,"value":4041},{"type":415,"tag":532,"props":36963,"children":36964},{"style":804},[36965],{"type":420,"value":36670},{"type":415,"tag":532,"props":36967,"children":36968},{"style":551},[36969],{"type":420,"value":4051},{"type":415,"tag":532,"props":36971,"children":36972},{"class":534,"line":3852},[36973],{"type":415,"tag":532,"props":36974,"children":36975},{"style":551},[36976],{"type":420,"value":7650},{"type":415,"tag":532,"props":36978,"children":36979},{"class":534,"line":5941},[36980,36984,36988,36992,36996],{"type":415,"tag":532,"props":36981,"children":36982},{"style":551},[36983],{"type":420,"value":36490},{"type":415,"tag":532,"props":36985,"children":36986},{"style":954},[36987],{"type":420,"value":36693},{"type":415,"tag":532,"props":36989,"children":36990},{"style":551},[36991],{"type":420,"value":801},{"type":415,"tag":532,"props":36993,"children":36994},{"style":551},[36995],{"type":420,"value":1290},{"type":415,"tag":532,"props":36997,"children":36998},{"style":551},[36999],{"type":420,"value":11759},{"type":415,"tag":532,"props":37001,"children":37002},{"class":534,"line":6053},[37003,37007,37012,37016,37020,37024,37029,37033],{"type":415,"tag":532,"props":37004,"children":37005},{"style":551},[37006],{"type":420,"value":36648},{"type":415,"tag":532,"props":37008,"children":37009},{"style":631},[37010],{"type":420,"value":37011},"Department",{"type":415,"tag":532,"props":37013,"children":37014},{"style":551},[37015],{"type":420,"value":801},{"type":415,"tag":532,"props":37017,"children":37018},{"style":551},[37019],{"type":420,"value":1290},{"type":415,"tag":532,"props":37021,"children":37022},{"style":551},[37023],{"type":420,"value":4041},{"type":415,"tag":532,"props":37025,"children":37026},{"style":804},[37027],{"type":420,"value":37028},"RH",{"type":415,"tag":532,"props":37030,"children":37031},{"style":551},[37032],{"type":420,"value":801},{"type":415,"tag":532,"props":37034,"children":37035},{"style":551},[37036],{"type":420,"value":7400},{"type":415,"tag":532,"props":37038,"children":37039},{"class":534,"line":6061},[37040,37044,37048,37052,37056,37060,37065],{"type":415,"tag":532,"props":37041,"children":37042},{"style":551},[37043],{"type":420,"value":36648},{"type":415,"tag":532,"props":37045,"children":37046},{"style":631},[37047],{"type":420,"value":29695},{"type":415,"tag":532,"props":37049,"children":37050},{"style":551},[37051],{"type":420,"value":801},{"type":415,"tag":532,"props":37053,"children":37054},{"style":551},[37055],{"type":420,"value":1290},{"type":415,"tag":532,"props":37057,"children":37058},{"style":551},[37059],{"type":420,"value":4041},{"type":415,"tag":532,"props":37061,"children":37062},{"style":804},[37063],{"type":420,"value":37064},"Dev",{"type":415,"tag":532,"props":37066,"children":37067},{"style":551},[37068],{"type":420,"value":4051},{"type":415,"tag":532,"props":37070,"children":37071},{"class":534,"line":6070},[37072],{"type":415,"tag":532,"props":37073,"children":37074},{"style":551},[37075],{"type":420,"value":7650},{"type":415,"tag":532,"props":37077,"children":37078},{"class":534,"line":6094},[37079,37083,37087,37091,37095],{"type":415,"tag":532,"props":37080,"children":37081},{"style":551},[37082],{"type":420,"value":36490},{"type":415,"tag":532,"props":37084,"children":37085},{"style":954},[37086],{"type":420,"value":36756},{"type":415,"tag":532,"props":37088,"children":37089},{"style":551},[37090],{"type":420,"value":801},{"type":415,"tag":532,"props":37092,"children":37093},{"style":551},[37094],{"type":420,"value":1290},{"type":415,"tag":532,"props":37096,"children":37097},{"style":551},[37098],{"type":420,"value":36769},{"type":415,"tag":532,"props":37100,"children":37101},{"class":534,"line":6118},[37102],{"type":415,"tag":532,"props":37103,"children":37104},{"style":551},[37105],{"type":420,"value":36777},{"type":415,"tag":532,"props":37107,"children":37108},{"class":534,"line":6142},[37109],{"type":415,"tag":532,"props":37110,"children":37111},{"style":551},[37112],{"type":420,"value":36482},{"type":415,"tag":532,"props":37114,"children":37115},{"class":534,"line":6182},[37116,37120,37124,37128,37132,37136,37141,37145],{"type":415,"tag":532,"props":37117,"children":37118},{"style":551},[37119],{"type":420,"value":36490},{"type":415,"tag":532,"props":37121,"children":37122},{"style":954},[37123],{"type":420,"value":4326},{"type":415,"tag":532,"props":37125,"children":37126},{"style":551},[37127],{"type":420,"value":801},{"type":415,"tag":532,"props":37129,"children":37130},{"style":551},[37131],{"type":420,"value":1290},{"type":415,"tag":532,"props":37133,"children":37134},{"style":551},[37135],{"type":420,"value":4041},{"type":415,"tag":532,"props":37137,"children":37138},{"style":804},[37139],{"type":420,"value":37140},"/subscriptions/********-****-****-****-************/resourceGroups/TestingAzureCLI",{"type":415,"tag":532,"props":37142,"children":37143},{"style":551},[37144],{"type":420,"value":801},{"type":415,"tag":532,"props":37146,"children":37147},{"style":551},[37148],{"type":420,"value":7400},{"type":415,"tag":532,"props":37150,"children":37151},{"class":534,"line":6214},[37152,37156,37160,37164,37168,37172,37176,37180],{"type":415,"tag":532,"props":37153,"children":37154},{"style":551},[37155],{"type":420,"value":36490},{"type":415,"tag":532,"props":37157,"children":37158},{"style":954},[37159],{"type":420,"value":25872},{"type":415,"tag":532,"props":37161,"children":37162},{"style":551},[37163],{"type":420,"value":801},{"type":415,"tag":532,"props":37165,"children":37166},{"style":551},[37167],{"type":420,"value":1290},{"type":415,"tag":532,"props":37169,"children":37170},{"style":551},[37171],{"type":420,"value":4041},{"type":415,"tag":532,"props":37173,"children":37174},{"style":804},[37175],{"type":420,"value":36547},{"type":415,"tag":532,"props":37177,"children":37178},{"style":551},[37179],{"type":420,"value":801},{"type":415,"tag":532,"props":37181,"children":37182},{"style":551},[37183],{"type":420,"value":7400},{"type":415,"tag":532,"props":37185,"children":37186},{"class":534,"line":6234},[37187,37191,37195,37199,37203],{"type":415,"tag":532,"props":37188,"children":37189},{"style":551},[37190],{"type":420,"value":36490},{"type":415,"tag":532,"props":37192,"children":37193},{"style":954},[37194],{"type":420,"value":36567},{"type":415,"tag":532,"props":37196,"children":37197},{"style":551},[37198],{"type":420,"value":801},{"type":415,"tag":532,"props":37200,"children":37201},{"style":551},[37202],{"type":420,"value":1290},{"type":415,"tag":532,"props":37204,"children":37205},{"style":551},[37206],{"type":420,"value":36580},{"type":415,"tag":532,"props":37208,"children":37209},{"class":534,"line":6250},[37210,37214,37218,37222,37226,37230,37234,37238],{"type":415,"tag":532,"props":37211,"children":37212},{"style":551},[37213],{"type":420,"value":36490},{"type":415,"tag":532,"props":37215,"children":37216},{"style":954},[37217],{"type":420,"value":3535},{"type":415,"tag":532,"props":37219,"children":37220},{"style":551},[37221],{"type":420,"value":801},{"type":415,"tag":532,"props":37223,"children":37224},{"style":551},[37225],{"type":420,"value":1290},{"type":415,"tag":532,"props":37227,"children":37228},{"style":551},[37229],{"type":420,"value":4041},{"type":415,"tag":532,"props":37231,"children":37232},{"style":804},[37233],{"type":420,"value":36172},{"type":415,"tag":532,"props":37235,"children":37236},{"style":551},[37237],{"type":420,"value":801},{"type":415,"tag":532,"props":37239,"children":37240},{"style":551},[37241],{"type":420,"value":7400},{"type":415,"tag":532,"props":37243,"children":37244},{"class":534,"line":6258},[37245,37249,37253,37257,37261],{"type":415,"tag":532,"props":37246,"children":37247},{"style":551},[37248],{"type":420,"value":36490},{"type":415,"tag":532,"props":37250,"children":37251},{"style":954},[37252],{"type":420,"value":36628},{"type":415,"tag":532,"props":37254,"children":37255},{"style":551},[37256],{"type":420,"value":801},{"type":415,"tag":532,"props":37258,"children":37259},{"style":551},[37260],{"type":420,"value":1290},{"type":415,"tag":532,"props":37262,"children":37263},{"style":551},[37264],{"type":420,"value":11759},{"type":415,"tag":532,"props":37266,"children":37267},{"class":534,"line":6266},[37268,37272,37276,37280,37284,37288,37292],{"type":415,"tag":532,"props":37269,"children":37270},{"style":551},[37271],{"type":420,"value":36648},{"type":415,"tag":532,"props":37273,"children":37274},{"style":631},[37275],{"type":420,"value":36653},{"type":415,"tag":532,"props":37277,"children":37278},{"style":551},[37279],{"type":420,"value":801},{"type":415,"tag":532,"props":37281,"children":37282},{"style":551},[37283],{"type":420,"value":1290},{"type":415,"tag":532,"props":37285,"children":37286},{"style":551},[37287],{"type":420,"value":4041},{"type":415,"tag":532,"props":37289,"children":37290},{"style":804},[37291],{"type":420,"value":36670},{"type":415,"tag":532,"props":37293,"children":37294},{"style":551},[37295],{"type":420,"value":4051},{"type":415,"tag":532,"props":37297,"children":37298},{"class":534,"line":6274},[37299],{"type":415,"tag":532,"props":37300,"children":37301},{"style":551},[37302],{"type":420,"value":7650},{"type":415,"tag":532,"props":37304,"children":37305},{"class":534,"line":6283},[37306,37310,37314,37318,37322],{"type":415,"tag":532,"props":37307,"children":37308},{"style":551},[37309],{"type":420,"value":36490},{"type":415,"tag":532,"props":37311,"children":37312},{"style":954},[37313],{"type":420,"value":36693},{"type":415,"tag":532,"props":37315,"children":37316},{"style":551},[37317],{"type":420,"value":801},{"type":415,"tag":532,"props":37319,"children":37320},{"style":551},[37321],{"type":420,"value":1290},{"type":415,"tag":532,"props":37323,"children":37324},{"style":551},[37325],{"type":420,"value":11759},{"type":415,"tag":532,"props":37327,"children":37328},{"class":534,"line":6292},[37329,37333,37337,37341,37345,37349,37353,37357],{"type":415,"tag":532,"props":37330,"children":37331},{"style":551},[37332],{"type":420,"value":36648},{"type":415,"tag":532,"props":37334,"children":37335},{"style":631},[37336],{"type":420,"value":37011},{"type":415,"tag":532,"props":37338,"children":37339},{"style":551},[37340],{"type":420,"value":801},{"type":415,"tag":532,"props":37342,"children":37343},{"style":551},[37344],{"type":420,"value":1290},{"type":415,"tag":532,"props":37346,"children":37347},{"style":551},[37348],{"type":420,"value":4041},{"type":415,"tag":532,"props":37350,"children":37351},{"style":804},[37352],{"type":420,"value":269},{"type":415,"tag":532,"props":37354,"children":37355},{"style":551},[37356],{"type":420,"value":801},{"type":415,"tag":532,"props":37358,"children":37359},{"style":551},[37360],{"type":420,"value":7400},{"type":415,"tag":532,"props":37362,"children":37363},{"class":534,"line":6392},[37364,37368,37372,37376,37380,37384,37388],{"type":415,"tag":532,"props":37365,"children":37366},{"style":551},[37367],{"type":420,"value":36648},{"type":415,"tag":532,"props":37369,"children":37370},{"style":631},[37371],{"type":420,"value":29695},{"type":415,"tag":532,"props":37373,"children":37374},{"style":551},[37375],{"type":420,"value":801},{"type":415,"tag":532,"props":37377,"children":37378},{"style":551},[37379],{"type":420,"value":1290},{"type":415,"tag":532,"props":37381,"children":37382},{"style":551},[37383],{"type":420,"value":4041},{"type":415,"tag":532,"props":37385,"children":37386},{"style":804},[37387],{"type":420,"value":36733},{"type":415,"tag":532,"props":37389,"children":37390},{"style":551},[37391],{"type":420,"value":4051},{"type":415,"tag":532,"props":37393,"children":37394},{"class":534,"line":6400},[37395],{"type":415,"tag":532,"props":37396,"children":37397},{"style":551},[37398],{"type":420,"value":7650},{"type":415,"tag":532,"props":37400,"children":37401},{"class":534,"line":6409},[37402,37406,37410,37414,37418],{"type":415,"tag":532,"props":37403,"children":37404},{"style":551},[37405],{"type":420,"value":36490},{"type":415,"tag":532,"props":37407,"children":37408},{"style":954},[37409],{"type":420,"value":36756},{"type":415,"tag":532,"props":37411,"children":37412},{"style":551},[37413],{"type":420,"value":801},{"type":415,"tag":532,"props":37415,"children":37416},{"style":551},[37417],{"type":420,"value":1290},{"type":415,"tag":532,"props":37419,"children":37420},{"style":551},[37421],{"type":420,"value":36769},{"type":415,"tag":532,"props":37423,"children":37424},{"class":534,"line":6457},[37425],{"type":415,"tag":532,"props":37426,"children":37427},{"style":551},[37428],{"type":420,"value":37429},"  }\n",{"type":415,"tag":532,"props":37431,"children":37432},{"class":534,"line":6465},[37433],{"type":415,"tag":532,"props":37434,"children":37435},{"style":551},[37436],{"type":420,"value":37437},"]\n",{"type":415,"tag":416,"props":37439,"children":37440},{},[37441],{"type":420,"value":37442},"Here are some CLI commands that query more precisely the resource groups:",{"type":415,"tag":508,"props":37444,"children":37445},{},[37446],{"type":415,"tag":512,"props":37447,"children":37448},{},[37449,37451],{"type":420,"value":37450},"Select only the resource groups names with ",{"type":415,"tag":468,"props":37452,"children":37454},{"className":37453},[],[37455],{"type":420,"value":37456},"az group list --query '[].name'",{"type":415,"tag":416,"props":37458,"children":37459},{},[37460],{"type":415,"tag":3882,"props":37461,"children":37465},{"alt":37462,"className":37463,"src":37464,"width":6932},"az group command output using JMESPath property selection.",[3886,3887],"/posts/images/azurecli_jmespath_2.png",[],{"type":415,"tag":508,"props":37467,"children":37468},{},[37469],{"type":415,"tag":512,"props":37470,"children":37471},{},[37472,37474],{"type":420,"value":37473},"Filter on resource groups in West Europe with ",{"type":415,"tag":468,"props":37475,"children":37477},{"className":37476},[],[37478],{"type":420,"value":37479},"az group list --query \"[?location=='westeurope']\"",{"type":415,"tag":416,"props":37481,"children":37482},{},[37483],{"type":415,"tag":3882,"props":37484,"children":37488},{"alt":37485,"className":37486,"src":37487,"width":6932},"az group command output using JMESPath property filter.",[3886,3887],"/posts/images/azurecli_jmespath_1.png",[],{"type":415,"tag":508,"props":37490,"children":37491},{},[37492],{"type":415,"tag":512,"props":37493,"children":37494},{},[37495,37497],{"type":420,"value":37496},"Filter on resource groups with an Environment tag with the value Production, select and rename name and tags properties with ",{"type":415,"tag":468,"props":37498,"children":37500},{"className":37499},[],[37501],{"type":420,"value":37502},"az group list --query \"[?tags.Environment=='Production'].{RGName:name, RGTags:tags}\"",{"type":415,"tag":416,"props":37504,"children":37505},{},[37506],{"type":415,"tag":3882,"props":37507,"children":37511},{"alt":37508,"className":37509,"src":37510,"width":6932},"az group command output using JMESPath property filter and selection.",[3886,3887],"/posts/images/azurecli_jmespath_3.png",[],{"type":415,"tag":434,"props":37513,"children":37514},{"icon":36108},[37515],{"type":415,"tag":416,"props":37516,"children":37517},{},[37518,37520,37527],{"type":420,"value":37519},"JMESPath is not an Azure CLI only thing, it is used in different other projects or tools like the ",{"type":415,"tag":423,"props":37521,"children":37524},{"href":37522,"rel":37523},"https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-output.html#controlling-output-filter",[427],[37525],{"type":420,"value":37526},"AWS CLI",{"type":420,"value":432},{"type":415,"tag":3914,"props":37529,"children":37531},{"id":37530},"mixing-output-variables-and-jmespath",[37532],{"type":420,"value":37533},"Mixing output, variables, and JMESPath",{"type":415,"tag":416,"props":37535,"children":37536},{},[37537],{"type":420,"value":37538},"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":415,"tag":416,"props":37540,"children":37541},{},[37542],{"type":420,"value":37543},"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":415,"tag":523,"props":37545,"children":37547},{"className":4059,"code":37546,"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",[37548],{"type":415,"tag":468,"props":37549,"children":37550},{"__ignoreMap":401},[37551,37559,37609,37616,37624,37690,37697,37705,37768,37775,37783],{"type":415,"tag":532,"props":37552,"children":37553},{"class":534,"line":535},[37554],{"type":415,"tag":532,"props":37555,"children":37556},{"style":5425},[37557],{"type":420,"value":37558},"# Retrieve resource group name of IT Department in West Europe\n",{"type":415,"tag":532,"props":37560,"children":37561},{"class":534,"line":566},[37562,37566,37571,37575,37580,37584,37588,37592,37597,37601,37605],{"type":415,"tag":532,"props":37563,"children":37564},{"style":551},[37565],{"type":420,"value":4072},{"type":415,"tag":532,"props":37567,"children":37568},{"style":545},[37569],{"type":420,"value":37570},"itRgName ",{"type":415,"tag":532,"props":37572,"children":37573},{"style":551},[37574],{"type":420,"value":1134},{"type":415,"tag":532,"props":37576,"children":37577},{"style":545},[37578],{"type":420,"value":37579}," az group list ",{"type":415,"tag":532,"props":37581,"children":37582},{"style":551},[37583],{"type":420,"value":4115},{"type":415,"tag":532,"props":37585,"children":37586},{"style":545},[37587],{"type":420,"value":4317},{"type":415,"tag":532,"props":37589,"children":37590},{"style":551},[37591],{"type":420,"value":801},{"type":415,"tag":532,"props":37593,"children":37594},{"style":804},[37595],{"type":420,"value":37596},"[?tags.Department=='IT' && location=='westeurope'].name",{"type":415,"tag":532,"props":37598,"children":37599},{"style":551},[37600],{"type":420,"value":801},{"type":415,"tag":532,"props":37602,"children":37603},{"style":551},[37604],{"type":420,"value":4335},{"type":415,"tag":532,"props":37606,"children":37607},{"style":545},[37608],{"type":420,"value":26804},{"type":415,"tag":532,"props":37610,"children":37611},{"class":534,"line":583},[37612],{"type":415,"tag":532,"props":37613,"children":37614},{"emptyLinePlaceholder":621},[37615],{"type":420,"value":624},{"type":415,"tag":532,"props":37617,"children":37618},{"class":534,"line":617},[37619],{"type":415,"tag":532,"props":37620,"children":37621},{"style":5425},[37622],{"type":420,"value":37623},"# Retrieve app service plan name in this resource group\n",{"type":415,"tag":532,"props":37625,"children":37626},{"class":534,"line":627},[37627,37631,37636,37640,37645,37649,37653,37657,37661,37665,37669,37673,37678,37682,37686],{"type":415,"tag":532,"props":37628,"children":37629},{"style":551},[37630],{"type":420,"value":4072},{"type":415,"tag":532,"props":37632,"children":37633},{"style":545},[37634],{"type":420,"value":37635},"appServicePlan ",{"type":415,"tag":532,"props":37637,"children":37638},{"style":551},[37639],{"type":420,"value":1134},{"type":415,"tag":532,"props":37641,"children":37642},{"style":545},[37643],{"type":420,"value":37644}," az appservice plan list ",{"type":415,"tag":532,"props":37646,"children":37647},{"style":551},[37648],{"type":420,"value":4216},{"type":415,"tag":532,"props":37650,"children":37651},{"style":545},[37652],{"type":420,"value":26212},{"type":415,"tag":532,"props":37654,"children":37655},{"style":551},[37656],{"type":420,"value":4072},{"type":415,"tag":532,"props":37658,"children":37659},{"style":545},[37660],{"type":420,"value":37570},{"type":415,"tag":532,"props":37662,"children":37663},{"style":551},[37664],{"type":420,"value":4115},{"type":415,"tag":532,"props":37666,"children":37667},{"style":545},[37668],{"type":420,"value":4317},{"type":415,"tag":532,"props":37670,"children":37671},{"style":551},[37672],{"type":420,"value":801},{"type":415,"tag":532,"props":37674,"children":37675},{"style":804},[37676],{"type":420,"value":37677},"[0].name",{"type":415,"tag":532,"props":37679,"children":37680},{"style":551},[37681],{"type":420,"value":801},{"type":415,"tag":532,"props":37683,"children":37684},{"style":551},[37685],{"type":420,"value":4335},{"type":415,"tag":532,"props":37687,"children":37688},{"style":545},[37689],{"type":420,"value":26804},{"type":415,"tag":532,"props":37691,"children":37692},{"class":534,"line":677},[37693],{"type":415,"tag":532,"props":37694,"children":37695},{"emptyLinePlaceholder":621},[37696],{"type":420,"value":624},{"type":415,"tag":532,"props":37698,"children":37699},{"class":534,"line":719},[37700],{"type":415,"tag":532,"props":37701,"children":37702},{"style":5425},[37703],{"type":420,"value":37704},"# Create a new Web App on this app service plan\n",{"type":415,"tag":532,"props":37706,"children":37707},{"class":534,"line":758},[37708,37713,37717,37721,37725,37730,37734,37738,37742,37746,37750,37754,37759,37763],{"type":415,"tag":532,"props":37709,"children":37710},{"style":545},[37711],{"type":420,"value":37712},"az webapp create ",{"type":415,"tag":532,"props":37714,"children":37715},{"style":551},[37716],{"type":420,"value":4216},{"type":415,"tag":532,"props":37718,"children":37719},{"style":545},[37720],{"type":420,"value":26194},{"type":415,"tag":532,"props":37722,"children":37723},{"style":551},[37724],{"type":420,"value":801},{"type":415,"tag":532,"props":37726,"children":37727},{"style":804},[37728],{"type":420,"value":37729},"MyNewWebAp",{"type":415,"tag":532,"props":37731,"children":37732},{"style":551},[37733],{"type":420,"value":801},{"type":415,"tag":532,"props":37735,"children":37736},{"style":551},[37737],{"type":420,"value":4335},{"type":415,"tag":532,"props":37739,"children":37740},{"style":545},[37741],{"type":420,"value":26212},{"type":415,"tag":532,"props":37743,"children":37744},{"style":551},[37745],{"type":420,"value":4072},{"type":415,"tag":532,"props":37747,"children":37748},{"style":545},[37749],{"type":420,"value":37570},{"type":415,"tag":532,"props":37751,"children":37752},{"style":551},[37753],{"type":420,"value":4115},{"type":415,"tag":532,"props":37755,"children":37756},{"style":545},[37757],{"type":420,"value":37758},"plan ",{"type":415,"tag":532,"props":37760,"children":37761},{"style":551},[37762],{"type":420,"value":4072},{"type":415,"tag":532,"props":37764,"children":37765},{"style":545},[37766],{"type":420,"value":37767},"appServicePlan\n",{"type":415,"tag":532,"props":37769,"children":37770},{"class":534,"line":767},[37771],{"type":415,"tag":532,"props":37772,"children":37773},{"emptyLinePlaceholder":621},[37774],{"type":420,"value":624},{"type":415,"tag":532,"props":37776,"children":37777},{"class":534,"line":819},[37778],{"type":415,"tag":532,"props":37779,"children":37780},{"style":5425},[37781],{"type":420,"value":37782},"# List all Web App in this resource group\n",{"type":415,"tag":532,"props":37784,"children":37785},{"class":534,"line":850},[37786,37791,37795,37799,37803,37807,37811,37815,37819,37824],{"type":415,"tag":532,"props":37787,"children":37788},{"style":545},[37789],{"type":420,"value":37790},"az webapp list ",{"type":415,"tag":532,"props":37792,"children":37793},{"style":551},[37794],{"type":420,"value":4216},{"type":415,"tag":532,"props":37796,"children":37797},{"style":545},[37798],{"type":420,"value":26212},{"type":415,"tag":532,"props":37800,"children":37801},{"style":551},[37802],{"type":420,"value":4072},{"type":415,"tag":532,"props":37804,"children":37805},{"style":545},[37806],{"type":420,"value":37570},{"type":415,"tag":532,"props":37808,"children":37809},{"style":551},[37810],{"type":420,"value":4115},{"type":415,"tag":532,"props":37812,"children":37813},{"style":545},[37814],{"type":420,"value":4317},{"type":415,"tag":532,"props":37816,"children":37817},{"style":551},[37818],{"type":420,"value":801},{"type":415,"tag":532,"props":37820,"children":37821},{"style":804},[37822],{"type":420,"value":37823},"[].name",{"type":415,"tag":532,"props":37825,"children":37826},{"style":551},[37827],{"type":420,"value":4051},{"type":415,"tag":416,"props":37829,"children":37830},{},[37831],{"type":420,"value":37832},"This is just a quick example but you can easily imagine all the possibilities that Azure CLI offers you.",{"type":415,"tag":482,"props":37834,"children":37836},{"id":37835},"_4-where-to-use-azure-cli",[37837],{"type":420,"value":37838},"4 - Where to use Azure CLI",{"type":415,"tag":416,"props":37840,"children":37841},{},[37842],{"type":420,"value":37843},"All that is great but we haven't talked about where we can use Azure CLI, let's do that now!",{"type":415,"tag":3914,"props":37845,"children":37847},{"id":37846},"bash-vs-powershell",[37848],{"type":420,"value":37849},"Bash vs PowerShell",{"type":415,"tag":416,"props":37851,"children":37852},{},[37853],{"type":420,"value":37854},"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":415,"tag":416,"props":37856,"children":37857},{},[37858],{"type":420,"value":37859},"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":415,"tag":416,"props":37861,"children":37862},{},[37863,37865,37872,37874,37881],{"type":420,"value":37864},"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":415,"tag":423,"props":37866,"children":37869},{"href":37867,"rel":37868},"https://github.com/Azure/azure-cli/issues/2324",[427],[37870],{"type":420,"value":37871},"GitHub issue",{"type":420,"value":37873}," on this matter. If you are not using bash and that tab completion is important for you, ",{"type":415,"tag":423,"props":37875,"children":37878},{"href":37876,"rel":37877},"https://docs.microsoft.com/en-us/cli/azure/interactive-azure-cli?view=azure-cli-latest",[427],[37879],{"type":420,"value":37880},"Azure CLI interactive mode",{"type":420,"value":37882}," is what you are looking for (we will talk about it later in the article)!",{"type":415,"tag":3914,"props":37884,"children":37886},{"id":37885},"azure-cli-in-visual-studio-code",[37887],{"type":420,"value":37888},"Azure CLI in Visual Studio Code",{"type":415,"tag":416,"props":37890,"children":37891},{},[37892],{"type":420,"value":37893},"As for most of Azure components, there is an extension in vs code for Azure CLI: Azure CLI Tools.",{"type":415,"tag":416,"props":37895,"children":37896},{},[37897],{"type":415,"tag":3882,"props":37898,"children":37902},{"alt":37899,"className":37900,"src":37901},"Azure CLI Tools vscode extension.",[3886,3887],"/posts/images/azurecli_vscode_1.png",[],{"type":415,"tag":416,"props":37904,"children":37905},{},[37906,37908,37913],{"type":420,"value":37907},"With this extension you can create Azure CLI Scrapbooks which are files with an ",{"type":415,"tag":468,"props":37909,"children":37911},{"className":37910},[],[37912],{"type":420,"value":25788},{"type":420,"value":37914}," extension where you have IntelliSense on CLI commands you write.",{"type":415,"tag":416,"props":37916,"children":37917},{},[37918],{"type":415,"tag":3882,"props":37919,"children":37923},{"alt":37920,"className":37921,"src":37922,"width":6932},"Intellisense with Azure CLI vscode extension.",[3886,3887],"/posts/images/azurecli_vscode_3.png",[],{"type":415,"tag":416,"props":37925,"children":37926},{},[37927],{"type":420,"value":37928},"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":415,"tag":416,"props":37930,"children":37931},{},[37932],{"type":415,"tag":3882,"props":37933,"children":37937},{"alt":37934,"className":37935,"src":37936,"width":6932},"Azcli file with integrated integrated terminal.",[3886,3887],"/posts/images/azurecli_vscode_2.png",[],{"type":415,"tag":3914,"props":37939,"children":37941},{"id":37940},"azure-cloud-shell",[37942],{"type":420,"value":37943},"Azure Cloud Shell",{"type":415,"tag":416,"props":37945,"children":37946},{},[37947,37949,37955],{"type":420,"value":37948},"I did not talk about Azure CLI installation but you can find everything you need in ",{"type":415,"tag":423,"props":37950,"children":37952},{"href":35775,"rel":37951},[427],[37953],{"type":420,"value":37954},"Microsoft documentation",{"type":420,"value":37956},". Actually, Azure Cloud Shell provides you with a way to use Azure CLI without installing anything.",{"type":415,"tag":416,"props":37958,"children":37959},{},[37960],{"type":420,"value":37961},"If we quote the documentation:",{"type":415,"tag":18632,"props":37963,"children":37964},{},[37965],{"type":415,"tag":416,"props":37966,"children":37967},{},[37968],{"type":420,"value":37969},"Azure Cloud Shell is an interactive, browser-accessible shell for managing Azure resources",{"type":415,"tag":416,"props":37971,"children":37972},{},[37973,37975,37981],{"type":420,"value":37974},"In concrete terms, you open a browser, go to ",{"type":415,"tag":423,"props":37976,"children":37979},{"href":37977,"rel":37978},"https://shell.azure.com",[427],[37980],{"type":420,"value":37977},{"type":420,"value":37982},", 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":415,"tag":416,"props":37984,"children":37985},{},[37986],{"type":415,"tag":3882,"props":37987,"children":37991},{"alt":37988,"className":37989,"src":37990,"width":6932},"Azure cloud shell in browser.",[3886,3887],"/posts/images/azurecli_cloudshell_1.png",[],{"type":415,"tag":416,"props":37993,"children":37994},{},[37995],{"type":420,"value":37996},"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":415,"tag":416,"props":37998,"children":37999},{},[38000,38002,38008],{"type":420,"value":38001},"Azure Cloud Shell is also available in the Azure Portal or directly in your vs code integrated terminal through the ",{"type":415,"tag":423,"props":38003,"children":38005},{"href":35186,"rel":38004},[427],[38006],{"type":420,"value":38007},"Azure Account extension",{"type":420,"value":432},{"type":415,"tag":482,"props":38010,"children":38012},{"id":38011},"_5-azure-cli-interactive-mode",[38013],{"type":420,"value":38014},"5 - Azure CLI Interactive mode",{"type":415,"tag":416,"props":38016,"children":38017},{},[38018],{"type":420,"value":38019},"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":415,"tag":416,"props":38021,"children":38022},{},[38023,38025,38031],{"type":420,"value":38024},"To enter in interactive mode, you have to type ",{"type":415,"tag":468,"props":38026,"children":38028},{"className":38027},[],[38029],{"type":420,"value":38030},"az interactive",{"type":420,"value":38032}," 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":415,"tag":416,"props":38034,"children":38035},{},[38036],{"type":415,"tag":3882,"props":38037,"children":38041},{"alt":38038,"className":38039,"src":38040,"width":6932},"Azure CLI interactive mode display.",[3886,3887],"/posts/images/azurecli_interactive_1.png",[],{"type":415,"tag":416,"props":38043,"children":38044},{},[38045,38047,38052,38054,38059,38061,38067,38068,38073],{"type":420,"value":38046},"One thing to notice is that commands you type are scoped to a command group. By default, it's scoped to ",{"type":415,"tag":468,"props":38048,"children":38050},{"className":38049},[],[38051],{"type":420,"value":25983},{"type":420,"value":38053}," group so you don't have to type the ",{"type":415,"tag":468,"props":38055,"children":38057},{"className":38056},[],[38058],{"type":420,"value":25983},{"type":420,"value":38060}," keyword before your commands. So by default, it only saves you two characters as you will write ",{"type":415,"tag":468,"props":38062,"children":38064},{"className":38063},[],[38065],{"type":420,"value":38066},"group list",{"type":420,"value":11493},{"type":415,"tag":468,"props":38069,"children":38071},{"className":38070},[],[38072],{"type":420,"value":36455},{"type":420,"value":38074},". But you can set the scope to any subgroup as you can see in the following example.",{"type":415,"tag":416,"props":38076,"children":38077},{},[38078],{"type":415,"tag":3882,"props":38079,"children":38083},{"alt":38080,"className":38081,"src":38082},"Scoped commands in Azure CLI interactive mode.",[3886,3887],"/posts/images/azurecli_interactive_2.png",[],{"type":415,"tag":416,"props":38085,"children":38086},{},[38087,38089,38094,38096,38102],{"type":420,"value":38088},"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":415,"tag":468,"props":38090,"children":38092},{"className":38091},[],[38093],{"type":420,"value":38066},{"type":420,"value":38095}," in interactive mode. If I want to select only the names in the results of this command, I can just type ",{"type":415,"tag":468,"props":38097,"children":38099},{"className":38098},[],[38100],{"type":420,"value":38101},"\"?? [*].name\"",{"type":420,"value":432},{"type":415,"tag":416,"props":38104,"children":38105},{},[38106],{"type":415,"tag":3882,"props":38107,"children":38111},{"alt":38108,"className":38109,"src":38110},"JMESPath examples to filter Azure CLI interactive output.",[3886,3887],"/posts/images/azurecli_interactive_3.png",[],{"type":415,"tag":416,"props":38113,"children":38114},{},[38115],{"type":420,"value":38116},"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":415,"tag":434,"props":38118,"children":38119},{"icon":36108},[38120],{"type":415,"tag":416,"props":38121,"children":38122},{},[38123,38125,38131],{"type":420,"value":38124},"It can sometimes be a little slow to use Azure interactive mode on ",{"type":415,"tag":423,"props":38126,"children":38129},{"href":38127,"rel":38128},"https://shell.azure.com/",[427],[38130],{"type":420,"value":38127},{"type":420,"value":38132},", 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":415,"tag":434,"props":38134,"children":38135},{"icon":36108},[38136],{"type":415,"tag":416,"props":38137,"children":38138},{},[38139,38141,38148],{"type":420,"value":38140},"If you like interactive CLI, you can also have a look at ",{"type":415,"tag":423,"props":38142,"children":38145},{"href":38143,"rel":38144},"https://github.com/lawrencegripper/azbrowse",[427],[38146],{"type":420,"value":38147},"AzBrowse",{"type":420,"value":38149}," which is a nice community project.",{"type":415,"tag":482,"props":38151,"children":38152},{"id":10889},[38153],{"type":420,"value":10892},{"type":415,"tag":416,"props":38155,"children":38156},{},[38157],{"type":420,"value":38158},"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":415,"tag":416,"props":38160,"children":38161},{},[38162],{"type":420,"value":38163},"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":415,"tag":3470,"props":38165,"children":38166},{},[38167],{"type":420,"value":3474},{"title":401,"searchDepth":566,"depth":566,"links":38169},[38170,38171,38172,38178,38183,38184],{"id":35783,"depth":566,"text":35786},{"id":35838,"depth":566,"text":35841},{"id":36051,"depth":566,"text":36054,"children":38173},[38174,38175,38176,38177],{"id":36057,"depth":583,"text":36060},{"id":36125,"depth":583,"text":36128},{"id":36416,"depth":583,"text":36419},{"id":37530,"depth":583,"text":37533},{"id":37835,"depth":566,"text":37838,"children":38179},[38180,38181,38182],{"id":37846,"depth":583,"text":37849},{"id":37885,"depth":583,"text":37888},{"id":37940,"depth":583,"text":37943},{"id":38011,"depth":566,"text":38014},{"id":10889,"depth":566,"text":10892},"content:1.posts:3.welcome-azure-cli.md","1.posts/3.welcome-azure-cli.md",1716749600578]