<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Awilsons on Black Marble</title><link>https://blogs.blackmarble.co.uk/awilson/</link><description>Recent content in Awilsons on Black Marble</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Copyright © Black Marble; all rights reserved.</copyright><lastBuildDate>Mon, 09 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blogs.blackmarble.co.uk/awilson/feed.xml" rel="self" type="application/rss+xml"/><item><title>MSTest | Controlling Parallelism of Test Runs</title><link>https://blogs.blackmarble.co.uk/awilson/mstest-controlling-parallelism/</link><pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/mstest-controlling-parallelism/</guid><description>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>I have been writing integration tests using MSTest recently and have encountered the need to control the level of parallelism required. MSTest, by default, runs your tests in parallel to maximise performance and reduce overall test execution time. This is great for independent unit tests, but it can quickly become a problem when you&amp;rsquo;re writing integration tests that access shared resources like databases, APIs, or cloud services. I recently encountered this issue when my integration test suite started failing randomly due to parallel tests competing for the same data or creating conflicting test data. The solution? Learning to control MSTest&amp;rsquo;s parallelism settings.&lt;/p></description></item><item><title>Azure Logic Apps Standard | Send Custom Events to Application Insights</title><link>https://blogs.blackmarble.co.uk/awilson/logic-app-standard-send-custom-events-application-insights/</link><pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/logic-app-standard-send-custom-events-application-insights/</guid><description>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>When building integration workflows with Azure Logic Apps Standard, there&amp;rsquo;s often a need to track custom business events that sit between pure technical telemetry and business process monitoring. Recently, while authoring a Logic App Standard workflow, I needed to track the total number of items processed along with a breakdown of successful versus failed processing attempts.&lt;/p>
&lt;p>While Logic Apps provides excellent run history and built-in diagnostics, custom events allow you to capture specific business actions and metrics that align with your reporting requirements. In this post, I&amp;rsquo;ll show you how to send custom events directly to Azure Application Insights using the ingestion endpoint from the Application Insights connection string.&lt;/p></description></item><item><title>Azure Function Apps | OkObjectResult Returns Empty JSON After Moving to .NET 9 Isolated Worker Runtime</title><link>https://blogs.blackmarble.co.uk/awilson/azure-function-apps-okobjectresult-returning-empty-json-object/</link><pubDate>Wed, 03 Dec 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/azure-function-apps-okobjectresult-returning-empty-json-object/</guid><description>
&lt;h2 id="the-problem">The Problem&lt;/h2>
&lt;p>I recently upgraded an Azure Function from .NET 8 to .NET 9, and at the same time migrated from the in-process worker to the isolated worker model. After the upgrade, my function that returned &lt;code>OkObjectResult&lt;/code> started returning an empty JSON object &lt;code>{}&lt;/code> instead of the expected data.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#50fa7b">[Function(&amp;#34;MyFunction&amp;#34;)]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">public&lt;/span> IActionResult Run([HttpTrigger(AuthorizationLevel.Function, &lt;span style="color:#f1fa8c">&amp;#34;post&amp;#34;&lt;/span>)] HttpRequest req)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd">var&lt;/span> data = &lt;span style="color:#ff79c6">new&lt;/span> MyResponse { Name = &lt;span style="color:#f1fa8c">&amp;#34;Test&amp;#34;&lt;/span>, Value = &lt;span style="color:#bd93f9">123&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">return&lt;/span> &lt;span style="color:#ff79c6">new&lt;/span> OkObjectResult(data); &lt;span style="color:#6272a4">// Returns {} instead of expected JSON&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="why-this-happens">Why This Happens&lt;/h2>
&lt;p>There are two key changes that caused this issue:&lt;/p></description></item><item><title>Bicep Tips and Tricks | #9 | Prevent a Nasty Refactor with Function Namespaces</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-function-namespaces/</link><pubDate>Wed, 17 Sep 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-function-namespaces/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>There have been few times where I have landed into this particular predicament whereby either by my own doing or through the use of another&amp;rsquo;s code base, a deep nested or thoroughly utilised (parameter/variable/or other defined item) has been created with the same name as a Bicep function. As by Murphy&amp;rsquo;s law, its only once you have reached this point of no return that you realise that your items name conflicts.&lt;/p></description></item><item><title>Bicep Tips and Tricks | #8 | Agnostic Templates Through Config Files</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-agnostic-templates-through-config-files/</link><pubDate>Wed, 03 Sep 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-agnostic-templates-through-config-files/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Building on our previous exploration of &lt;a href="https://andrewilson.co.uk/post/2025/08/bicep-tips-and-tricks-typed-variables/">Typed Variables&lt;/a>, today we&amp;rsquo;re diving into one of my favorite patterns for creating maintainable and reusable Bicep templates: the &lt;strong>Shared Variable File Pattern&lt;/strong>. This approach transforms your templates from being tightly coupled to specific configurations into truly agnostic, environment-ready solutions.&lt;/p>
&lt;p>The beauty of this pattern lies in its simplicity - by extracting configuration data into external JSON or YAML files, you can create templates that adapt without modification. When combined with typed variables, this approach becomes even more powerful, providing compile-time validation and enhanced developer experience.&lt;/p></description></item><item><title>Bicep Tips and Tricks | #7 | From Static to Dynamic Config</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-static-to-dynamic-config/</link><pubDate>Wed, 27 Aug 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-static-to-dynamic-config/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>One of my core goals when writing IaC templates is ensuring reusability of common components, resources, and in this case, configuration. More often than not, I see configuration that is broadly common between resources (except for one or two properties) being duplicated throughout templates. This duplication means that changing a single property value requires updates across the entire codebase—a change that&amp;rsquo;s not trivial to manage unless you&amp;rsquo;re well-versed with the codebase and understand all areas where the configuration is implemented.&lt;/p></description></item><item><title>Bicep Tips and Tricks | #6 | Typed Variables</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-typed-variables/</link><pubDate>Wed, 20 Aug 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-typed-variables/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>In late &lt;a href="https://github.com/Azure/bicep/releases/tag/v0.36.1">May this year&lt;/a>, an exciting but semi overlooked feature was released, and I absolutely love it - &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/variables#typed-variables">Typed Variables&lt;/a>!&lt;/p>
&lt;p>Prior to this release, variable types were inferred through the value, which is fine for most statically defined content within a template, but there are cases that I will go through in this post where typing your variables really does make a big difference.&lt;/p>
&lt;h2 id="why-use-typed-variables">Why Use Typed Variables&lt;/h2>
&lt;p>Before I get going, let me walk through why you should consider using typed variables:&lt;/p></description></item><item><title>Bicep Tips and Tricks | #5 | From Documentation to Deployment-Time Validation: Conditional Parameter Requirements</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-conditional-mandatory-parameters/</link><pubDate>Wed, 13 Aug 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-conditional-mandatory-parameters/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>In Bicep templates, we sometimes encounter scenarios where certain parameters should be mandatory based on the value of another parameter. For example, when deploying to production environments, you might require additional configuration parameters that are optional for development environments.&lt;/p>
&lt;p>One of the common ways in which I have seen this handled is through documentation, which can lead to deployment failures and inconsistent configurations across environments. This post explores how to implement fail-fast validation using Bicep&amp;rsquo;s built-in capabilities to enforce these conditional requirements at deployment time.&lt;/p></description></item><item><title>Bicep Tips and Tricks | #4 | Shared Variables</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-shared-variables/</link><pubDate>Wed, 06 Aug 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-shared-variables/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>This week is a simple one, but works wonders in maintainability and consistency.&lt;/p>
&lt;p>There are often cases where you will need to define static values that don&amp;rsquo;t change frequently, if at all, and more importantly, you seem to be setting these up frequently for multiple templates. Here are some examples that I have seen:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Multi-Environment Deployments&lt;/p>
&lt;p>Different environments (dev, staging, prod) that share common configuration but need environment-specific values:&lt;/p></description></item><item><title>Bicep Tips and Tricks | #3 | Naming Convention and Functions</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-naming-convention-functions/</link><pubDate>Wed, 30 Jul 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-naming-convention-functions/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>One of my bugbears is seeing either a complete lack of naming conventions or manual naming mechanisms that introduce human error through mistakes and misunderstandings. Naming conventions are incredibly important, but equally critical is how they&amp;rsquo;re implemented and maintained. Let&amp;rsquo;s explore a better approach.&lt;/p>
&lt;p>&lt;strong>What is a Naming Convention and Why Do We Need One?&lt;/strong>&lt;/p>
&lt;p>A naming convention is a set of rules for naming Resource Groups and Resources (among other Azure components). These rules define the structure and composition of names, ensuring clarity, consistency, and compliance with Azure naming requirements such as length limits, valid characters, and scope uniqueness.&lt;/p></description></item><item><title>Bicep Tips and Tricks | #2 | Centralize Core Parameters with Types, Constructors, and Imports</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-core-parameters-and-constructors/</link><pubDate>Wed, 23 Jul 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-tips-and-tricks-core-parameters-and-constructors/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>When building IaC templates we strive to enable them to be environment agnostic, configurable even. One of the mechanisms that we do this is through lots of &amp;ldquo;&lt;em>Core Parameters&lt;/em>&amp;rdquo; that disseminate the fundamental details of our deployment and resources. The number of core parameters is often variable but the verdict is always true, three or more usually does the trick. These Core Parameters are passed into the main deployment template and any other sub deployment template (Module) too. These may include but are not limited to:&lt;/p></description></item><item><title>Bicep Tips and Tricks | #1 | Template Versioning and Applying to Azure Resource Tags</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-template-versioning-resource-tags-tips-tricks-azure-devops/</link><pubDate>Wed, 16 Jul 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-template-versioning-resource-tags-tips-tricks-azure-devops/</guid><description>
&lt;h2 id="the-first-of-many">The first of many&lt;/h2>
&lt;p>For those who know me well, starting a bicep tips and tricks series would not be a surprise to them. The moment the Bicep language was introduced, I knew I would be completely obsessed. I love writing bicep templates and even more the clever refinement to make them reusable, configurable, manageable, readable&amp;hellip; I really enjoy sharing my experiences with Bicep, so here it begins on the wider front. From one Bicep nerd to another, I hope you find these tips useful, happy templating!&lt;/p></description></item><item><title>Automating web.config Environment Transforms in Azure DevOps Pipelines for App Services</title><link>https://blogs.blackmarble.co.uk/awilson/webconfig-environment-transform-azure-devops-app-service/</link><pubDate>Wed, 02 Jul 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/webconfig-environment-transform-azure-devops-app-service/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>Modernising legacy applications is always a journey, and recently I tackled moving an existing WCF web service into Azure App Service. If you’ve worked with WCF, you’ll know the &lt;code>web.config&lt;/code> file is the nerve centre, handling everything from parameters to connection strings.&lt;/p>
&lt;p>But here’s the catch, this service needs to run in multiple environments (Development, Test, and Production) each with its own unique settings. That means multiple config files:&lt;/p></description></item><item><title>How to Set Up Manual Approval for Azure App Service Slot Swaps in Azure DevOps Pipelines</title><link>https://blogs.blackmarble.co.uk/awilson/manual-approval-azure-app-service-slot-swap-azure-devops/</link><pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/manual-approval-azure-app-service-slot-swap-azure-devops/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Deploying updates to production environments demands both speed and control. Azure App Service deployment slots, combined with Azure DevOps pipelines, offer a powerful way to manage releases, enabling teams to validate changes in a live-like environment before they go public. However, ensuring that only reviewed and approved changes reach your users is critical for maintaining reliability and compliance.&lt;/p>
&lt;p>Azure App Service Slots unlock powerful advantages:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Site Review&lt;/strong>. Preview and test your site before it goes live, ensuring everything works as expected.&lt;/li>
&lt;li>&lt;strong>Warmed-up Instances&lt;/strong>. Swap with confidence. Your instances are pre-warmed, so there’s no downtime, seamless traffic redirection, and zero dropped requests.&lt;/li>
&lt;li>&lt;strong>Instant Rollback&lt;/strong>. If something goes wrong after a swap, simply swap back to restore your last known good version in seconds.&lt;/li>
&lt;/ul>
&lt;p>Best of all, deployment slots come at no extra cost. Check the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-app-service-limits">Azure App Service limits&lt;/a> to see how many slots your App Service Tier supports.&lt;/p></description></item><item><title>Agent Loop | Azure Logic Apps Just Got Smarter</title><link>https://blogs.blackmarble.co.uk/awilson/agent-loop-announcement-microsoft-logic-apps/</link><pubDate>Wed, 21 May 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/agent-loop-announcement-microsoft-logic-apps/</guid><description>
&lt;h2 id="microsoft-announcement">Microsoft Announcement&lt;/h2>
&lt;p>Microsoft has just introduced something quite revolutionary into the world of integration: &lt;strong>Agent Loop&lt;/strong>, a new capability in Azure Logic Apps that lets you build AI-powered agents directly into your workflows. On the surface, it might seem like another incremental feature. But dig a little deeper, and the implications are huge!&lt;/p>
&lt;p>Let’s break it down.&lt;/p>
&lt;h2 id="what-is-agent-loop">What Is Agent Loop?&lt;/h2>
&lt;p>Agent Loop is Microsoft’s way of embedding &lt;strong>advanced AI decision-making&lt;/strong> into Logic Apps workflows. Think of it like adding a smart co-pilot into your integration flows, an agent that can &lt;strong>retain context, reason over time, and take meaningful actions&lt;/strong>. It uses an LLM like Azure OpenAI under the hood, paired with a memory store that persists throughout the workflow, allowing the agent to understand, adapt, and make decisions across multiple steps.&lt;/p></description></item><item><title>The Requirements Ambiguity Paradox</title><link>https://blogs.blackmarble.co.uk/awilson/requirements-ambiguity-paradox/</link><pubDate>Fri, 16 May 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/requirements-ambiguity-paradox/</guid><description>
&lt;h2 id="the-requirements-ambiguity-paradox">The Requirements Ambiguity Paradox&lt;/h2>
&lt;p>With the context of software requirements, I regularly encounter an understood but often ignored scenario: the less detailed the initial requirements, the more expansive the client&amp;rsquo;s expectations become as the project progresses. It&amp;rsquo;s a phenomenon I refer to as the &lt;strong>Requirements Ambiguity Paradox&lt;/strong>.&lt;/p>
&lt;p>Imagine initiating a project with a brief requirements document, aiming for agility and speed. At first glance, this seems efficient.&lt;/p>
&lt;p>However, this brevity often leads to divergent interpretations:&lt;/p></description></item><item><title>Automating Semantic Versioning in Azure DevOps CI/CD Pipelines with GitVersion</title><link>https://blogs.blackmarble.co.uk/awilson/cicd-and-automatic-semantic-versioning/</link><pubDate>Wed, 07 May 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/cicd-and-automatic-semantic-versioning/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Versioning is the unsung hero of software development—often overlooked but absolutely essential. Imagine trying to manage a project without a clear way to track changes, communicate updates, or ensure compatibility. Chaos, right? That’s where versioning steps in, providing structure and clarity.&lt;/p>
&lt;p>In this post, I’ll share how I streamline versioning in my projects by combining the power of &lt;strong>Semantic Versioning (SemVer)&lt;/strong> with &lt;strong>GitVersion&lt;/strong>, an automation tool that eliminates the manual effort of version management. Whether you&amp;rsquo;re just beginning your journey or tackling the complexities of feature-rich projects, this post will show you how to automate semantic versioning in &lt;strong>Azure DevOps&lt;/strong> for consistency, traceability, and peace of mind.&lt;/p></description></item><item><title>Bicep | Existing Resource Dependencies</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-existing-resource-dependencies/</link><pubDate>Wed, 26 Mar 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-existing-resource-dependencies/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>The Bicep &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/existing-resource">existing&lt;/a> keyword is a powerful capability that allows us to reference a resource that wasn&amp;rsquo;t deployed as part of the current Bicep file.&lt;/p>
&lt;p>One of the typical use cases that I often see is where a resource is deployed as part of a module called by the parent template, the resource that was deployed as part of the module is then required later in the parent template and therefore an existing resource definition is used. As part of the template configuration there would be an explicit dependency between the existing resource definition and the module reference.&lt;/p></description></item><item><title>Logic App | Access Key Revocation and Regeneration</title><link>https://blogs.blackmarble.co.uk/awilson/logic-app-standard-sas-revocation-and-regeneration/</link><pubDate>Fri, 28 Feb 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/logic-app-standard-sas-revocation-and-regeneration/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>In previous articles I have subtly referenced risks and best practices regarding HTTP triggered workflows and their use of Access Keys for security, such as:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Some Potential Risks:&lt;/p>
&lt;ul>
&lt;li>If a &lt;strong>Key is leaked&lt;/strong>, it can be used by anyone who obtains it to call your Logic App Workflow.&lt;/li>
&lt;li>If a &lt;strong>Key has expired or been invalidated&lt;/strong> then services, applications, and or users who have not been provided a new key will cease to be able to invoke your workflow.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Some Access Key Best Practices to mitigate risks:&lt;/p></description></item><item><title>Logic App | Try-Catch Pattern, Nested Scopes, And Compensating Transaction Pattern</title><link>https://blogs.blackmarble.co.uk/awilson/logic-app-nested-scopes-and-compensating-transaction-pattern/</link><pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/logic-app-nested-scopes-and-compensating-transaction-pattern/</guid><description>
&lt;h2 id="the-try-catch-pattern">The Try-Catch Pattern&lt;/h2>
&lt;p>Following the idea of defensive programming or as I like to call it for Logic Apps (&lt;em>being low code&lt;/em>): &lt;em>defensive processing&lt;/em>, it is considered good practice to wrap your workflows in a try-catch pattern to handle the unexpected. The pattern makes use of a mixture of Run After conditions and the Scope block.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Run After Conditions&lt;/strong> | &lt;em>used to define the execution order based on the state of the previous action or scope&lt;/em>&lt;/li>
&lt;li>&lt;strong>Scope Block&lt;/strong> | &lt;em>provides the ability to group a series of actions. If any action within the scope fails, the whole scope will fail (unless handled via other means)&lt;/em>&lt;/li>
&lt;/ul>
&lt;p>By placing your actions within a &amp;ldquo;try&amp;rdquo; scope with the assumption that each action will run after the success of the previous, if there is an action failure, the scope will fail also.&lt;/p></description></item><item><title>Key Vault Reference | Logic and Function Apps using User-Assigned Managed Identity</title><link>https://blogs.blackmarble.co.uk/awilson/logic-and-function-app-keyvault-access-with-user-assigned-identity/</link><pubDate>Mon, 06 Jan 2025 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/logic-and-function-app-keyvault-access-with-user-assigned-identity/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Prior to the Christmas break I was involved in writing some integrations that used a mixture of Logic Apps Standard and Function Apps. It was agreed as part of the architecture that user-assigned identities would be the best fit. As part of the implementation, I observed that the differences in configuration setup between system-assigned and user-assigned wasn&amp;rsquo;t widely understood. This article aims to show a brief run through of both.&lt;/p></description></item><item><title>Easy Auth | Standard Logic App with Azure API Management</title><link>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-easy-auth-apim/</link><pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-easy-auth-apim/</guid><description>
&lt;p>&lt;a href="https://github.com/Andrew-D-Wilson/Standard-Logic-App-APIM-Backend">
&lt;img src="https://img.shields.io/badge/Repo-Easy%20Auth%20With%20Standard%20Logic%20App%20And%20APIM-blue?logo=github&amp;amp;style=for-the-badge" alt="GitHub Repository">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>The recent work that I have been doing with Standard Logic Apps and linking them as backends to Azure API Management has relied on the use of the Logic App Workflow SAS key for security. This is a valid authentication approach, but there are risks that you need to be aware of as well as &lt;a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview#best-practices-when-using-sas">best practices&lt;/a> that you need to be abiding by. Such as:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Some Potential Risks:&lt;/p></description></item><item><title>Easy Auth | Function App with Azure API Management</title><link>https://blogs.blackmarble.co.uk/awilson/function-app-easy-auth-apim/</link><pubDate>Thu, 14 Nov 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/function-app-easy-auth-apim/</guid><description>
&lt;p>&lt;a href="https://github.com/Andrew-D-Wilson/Function-App-APIM-Backend/">
&lt;img src="https://img.shields.io/badge/Repo-Easy%20Auth%20With%20Function%20Apps%20And%20APIM-blue?logo=github&amp;amp;style=for-the-badge" alt="GitHub Repository">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>The &lt;a href="https://andrewilson.co.uk/post/2024/10/function-app-apim-backend/">recent work&lt;/a> that I have been doing with Function Apps and linking them as backends to Azure API Management has relied on the use of the Function Apps Function SAS key for security. This is a valid authentication approach, but there are risks that you need to be aware of as well as &lt;a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview#best-practices-when-using-sas">best practices&lt;/a> that you need to be abiding by. Such as:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Some Potential Risks:&lt;/p></description></item><item><title>Azure API Management | Function App Backend</title><link>https://blogs.blackmarble.co.uk/awilson/function-app-apim-backend/</link><pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/function-app-apim-backend/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>&lt;a href="https://github.com/Andrew-D-Wilson/Function-App-APIM-Backend">
&lt;img src="https://img.shields.io/badge/Repo-Function--App--APIM--Backend-blue?logo=github&amp;amp;style=for-the-badge" alt="GitHub Repository">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;p>Following on from a previous set of posts from earlier this year where I detailed how to securely implement Logic App Standard backends in Azure API Management, there has been questions on how this would be achieved in a similar manner with Azure Function Apps.&lt;/p>
&lt;p>&lt;em>To read-up on how this was achieved with Standard Logic Apps have a look at the following:&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://andrewilson.co.uk/post/2024/01/standard-logic-app-apim-backend/">Azure API Management | Logic App (Standard) Backend&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://andrewilson.co.uk/post/2024/02/standard-logic-app-apim-backend-swagger/">Azure API Management | Logic App (Standard) Backend Using a Swagger Definition&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://andrewilson.co.uk/post/2024/02/standard-logic-app-easy-auth-apim/">Easy Auth | Standard Logic App with Azure API Management&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>At a high level comparison with Azure Logic Apps, Azure Functions are a developer-centric serverless compute offering allowing authors to write code in languages such as C#, Java, Javascript, Python, and PowerShell. Azure Functions are best suited for stateless computation and application specific tasks.&lt;/p></description></item><item><title>Speaking | Azure Security Do's and Don'ts: A Developer's Checklist for Secure Azure Applications</title><link>https://blogs.blackmarble.co.uk/awilson/speaking-azure-security-dos-and-donts/</link><pubDate>Thu, 15 Aug 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/speaking-azure-security-dos-and-donts/</guid><description>
&lt;p>
&lt;img src="https://andrewilson.co.uk/images/posts/2024/08/AzureOnAir.png" alt="AzureOnAir">
&lt;/p>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=h5s7UIfnlUo&amp;amp;list=PLfIG-b2nAHLdP4fk7ck53BqXzyArGg8ss&amp;amp;index=6">
&lt;img src="https://img.shields.io/badge/WATCH_NOW:_Azure_Security_Do%27s_and_Don%27ts-darkred?logo=youtube&amp;amp;style=for-the-badge" alt="Static Badge">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;p>I recently had the privilege to be hosted on the &lt;a href="https://turbo360.com/podcast">Azure on Air&lt;/a> podcast by the &lt;a href="https://turbo360.com/">Turbo360&lt;/a> team. I had a great conversation with Lex discussing the importance of a &amp;ldquo;security first&amp;rdquo; mindset in the world of Azure solutions, and how this mindset should be carried out as a priority in every stage from Requirements Gathering, Design, Development, and Release.&lt;/p>
&lt;p>During our time together we discussed topics such as:&lt;/p></description></item><item><title>webpack | Build Time Environment Variables With Azure DevOps Yaml CI/CD</title><link>https://blogs.blackmarble.co.uk/awilson/webpack-build-time-environment-variables/</link><pubDate>Thu, 25 Jul 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/webpack-build-time-environment-variables/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>One of my recent projects has involved the use of a static module bundler called &lt;a href="https://webpack.js.org/">webpack&lt;/a> to bundle a typescript site so I can serve static content from a &lt;a href="https://learn.microsoft.com/en-us/azure/static-web-apps/overview">Static Web App&lt;/a> in Azure.&lt;/p>
&lt;p>For a while now the site content has not deviated between environments [ dev / test / prod ] and therefore we have simply built and bundled the site for deployment.&lt;/p>
&lt;p>Recent changes however have required that there be some deviation between environments, at which point the question raised, at what point should this deviation be set or retrieved?&lt;/p></description></item><item><title>Azure Role Based Access Control (RBAC) | Removing Orphaned Role Assignments</title><link>https://blogs.blackmarble.co.uk/awilson/removing-orphaned-rbac-role-assignments/</link><pubDate>Thu, 04 Jul 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/removing-orphaned-rbac-role-assignments/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>Deploying solutions into Azure that rely on Role Based Access often involve us creating IaC automation for the assignment of roles, such as:&lt;/p>
&lt;ul>
&lt;li>A services access to Key Vault&lt;/li>
&lt;li>A services access to a Key Vault specific secret&lt;/li>
&lt;li>A services access to a storage account&lt;/li>
&lt;li>A services access to a Service Bus Queue or Topic&lt;/li>
&lt;/ul>
&lt;p>In many of these instances we may wish to leverage the source resource identity (&lt;em>System Assigned Managed Identity&lt;/em>) for the assigned access.&lt;/p></description></item><item><title>Azure API Management | Enable Tracing for an API</title><link>https://blogs.blackmarble.co.uk/awilson/apim-enable-tracing-for-an-api/</link><pubDate>Sun, 02 Jun 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-enable-tracing-for-an-api/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>For a while now I have made good use of the Trace functionality in the API Management (APIM) Test Client. If you haven&amp;rsquo;t, I would highly advise having a &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-api-inspector#trace-a-call-in-the-portal">look&lt;/a>. The Trace functionality allows us to unveil (debug) the complexity and inner workings of our reverse proxy APIs (their routing / hierarchical policies / alternate backends / caching / etc.). With the Portal this is fairly trivial to do, you simply:&lt;/p></description></item><item><title>Bicep | Prevent a Nasty Refactor with Function Namespaces</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-function-namespaces/</link><pubDate>Mon, 27 May 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-function-namespaces/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>There have been few times where I have landed into this particular predicament whereby either by my own doing or through the use of another&amp;rsquo;s code base, a deep nested or thoroughly utilised (parameter/variable/or other defined item) has been created with the same name as a Bicep function. As by Murphy&amp;rsquo;s law, its only once you have reached this point of no return that you realise that your items name conflicts.&lt;/p></description></item><item><title>Azure API Management | Unintentional Removal of Request Forwarding to Backend</title><link>https://blogs.blackmarble.co.uk/awilson/apim-policy-hierarchy-request-forwarding/</link><pubDate>Fri, 03 May 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-policy-hierarchy-request-forwarding/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I have recently been working on an API scoped policy within API Management, the policy ideally should not be impacted by any policies defined higher up in the hierarchy.&lt;/p>
&lt;p>For reference, this means that any policies defined at the Product, Workspace, or Global level will not be inherited at the API scope for the given API Definition. See diagram below:&lt;/p>
&lt;p>
&lt;img src="https://andrewilson.co.uk/images/posts/2024/05/APIMPolicyScopes.png" alt="Policy Scopes">
&lt;/p>
&lt;p>Ideally this means that my API traffic will start at my non-hierarchical policy definition, conduct any policy processing prior to being sent off to the backend, and then sent back to the calling outbound system.&lt;/p></description></item><item><title>Azure API Management | Governing Product Visibility and Access via Groups</title><link>https://blogs.blackmarble.co.uk/awilson/apim-users-and-groups/</link><pubDate>Tue, 30 Apr 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-users-and-groups/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>In API Management, users and groups are a core aspect of the Developer Portal and are used to manage the visibility and access to respective products and their APIs.&lt;/p>
&lt;p>One of the common questions that I often get asked is, &amp;ldquo;how do I appropriately govern the groups effectively so that I can ensure that the correct groups and users have access to the appropriate resources and those who don&amp;rsquo;t&amp;hellip; well don&amp;rsquo;t?&amp;rdquo;.&lt;/p></description></item><item><title>Microsoft.Web/Connections | Access Policies</title><link>https://blogs.blackmarble.co.uk/awilson/api-connection-access-policies/</link><pubDate>Wed, 10 Apr 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/api-connection-access-policies/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I have recently been adding email alerting to some Logic App Standard workflows as part of the error handling flow. In doing so I made use of an existing Office 365 Outlook Connector in the Azure Subscription; the connector is not built in for Standard Logic Apps but is rather part of the Managed Api Connections.&lt;/p>
&lt;p>Managed Api Connectors require more than just the connection details to be detailed in the Logic Apps connections.json configuration as shown below:&lt;/p></description></item><item><title>Bicep | User Defined Types</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-user-defined-types/</link><pubDate>Wed, 07 Feb 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-user-defined-types/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>Over the years of developing Infrastructure as Code (IaC) with either ARM templates or Bicep (since it was released in 2020), I have made it my best practice where possible to use well-defined base type parameters (&lt;code>Strings | Integers | Booleans&lt;/code>) so that the templates are usable and maintainable by collaborators apart from myself. This usually equated to where possible avoiding the use of &lt;code>Object and Array&lt;/code> parameters, although in many cases the use of these types was inevitable given the complexity of the infrastructure and resources being deployed.&lt;/p></description></item><item><title>Azure API Management | Logic App (Standard) Backend Using a Swagger Definition</title><link>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-apim-backend-swagger/</link><pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-apim-backend-swagger/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>&lt;a href="https://github.com/Andrew-D-Wilson/Standard-Logic-App-APIM-Backend">
&lt;img src="https://img.shields.io/badge/Repo-Standard--Logic--App--APIM--Backend-blue?logo=github&amp;amp;style=for-the-badge" alt="GitHub Repository">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;p>After setting up a &lt;a href="https://andrewilson.co.uk/post/2024/01/standard-logic-app-apim-backend/">Logic App (Standard) Backend in Azure API Management (APIM)&lt;/a> in my last post, I wanted to try and see if I could create a Swagger definition from a Standard Logic App which could then be used to simplify the API authoring process in APIM. This post shows my methods of doing so.&lt;/p>
&lt;blockquote>
&lt;p>If you haven&amp;rsquo;t already I would recommend reading my previous &lt;a href="https://andrewilson.co.uk/post/2024/01/standard-logic-app-apim-backend/">&lt;strong>post&lt;/strong>&lt;/a> as this one will be working off of the building blocks of the last.&lt;/p></description></item><item><title>Azure API Management | Logic App (Standard) Backend</title><link>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-apim-backend/</link><pubDate>Tue, 02 Jan 2024 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/standard-logic-app-apim-backend/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>&lt;a href="https://github.com/Andrew-D-Wilson/Standard-Logic-App-APIM-Backend">
&lt;img src="https://img.shields.io/badge/Repo-Standard--Logic--App--APIM--Backend-blue?logo=github&amp;amp;style=for-the-badge" alt="GitHub Repository">
&lt;p>&lt;/a>&lt;/p>&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>Updated [31/01/2024]: See&lt;/code> &lt;a href="https://andrewilson.co.uk/post/2024/02/standard-logic-app-apim-backend-swagger/">New Post&lt;/a> &lt;code>showing methods of linking a Logic App Standard as a Backend to APIM through a Swagger Definition.&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>I have recently been reviewing the method in which a Logic App (Standard) workflow would be setup as an API in API Management. My aim is to overcome and simplify the limitation whereby &lt;a href="https://techcommunity.microsoft.com/t5/azure-paas-blog/import-logic-apps-standard-into-azure-api-management/ba-p/3055490#:~:text=As%20an%20alternative%2C%20to%20import,into%20the%20backend%20and%20frontend.">directly importing a Logic App (Standard) workflow is not available, only in consumption.&lt;/a>&lt;/p></description></item><item><title>Windows Terminal | Azure Customisation for PowerShell</title><link>https://blogs.blackmarble.co.uk/awilson/windows-terminal-customisation-powershell/</link><pubDate>Thu, 30 Nov 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/windows-terminal-customisation-powershell/</guid><description>
&lt;p>If you haven&amp;rsquo;t already, placing a customisation on your command prompt for PowerShell is a great way to gain extra context in given activities. For example, if you would like to have a comprehensive overview of your Git status summary information, then &lt;a href="https://github.com/dahlbyk/posh-git">posh-git&lt;/a> is for you.&lt;/p>
&lt;p>
&lt;img src="https://andrewilson.co.uk/images/posts/2023/11/posh-git.png" alt="posh-git">
&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Be Careful:&lt;/strong> Adding customisations will bring latency to start-up&lt;/p>
&lt;/blockquote>
&lt;p>One customisation that I came across that I really like is the &lt;a href="https://ohmyposh.dev/docs/themes#cloud-native-azure">cloud-native-azure&lt;/a> theme using &lt;a href="https://ohmyposh.dev/">Oh My Posh&lt;/a>.
The theme gives context to the following:&lt;/p></description></item><item><title>Azure RBAC Key Vault | Role Assignment for Specific Secret</title><link>https://blogs.blackmarble.co.uk/awilson/rbac-key-vault-specific-secret/</link><pubDate>Wed, 22 Nov 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/rbac-key-vault-specific-secret/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>Azure role-based access control (Azure RBAC) provides fine grained control over access to Azure resources. Azure RBAC is founded on top of the Azure Resource Manager which allows us to provide access authorisation at differing scope levels ranging from the Management Group through to individual resources.&lt;/p>
&lt;p>With RBAC enabled key vaults we can manage access to the resource and data stored in the vault. We can also manage access for individual keys, secrets, and certificates.&lt;/p></description></item><item><title>Azure API Management | Unintentional Pass through of Subscription Key Header</title><link>https://blogs.blackmarble.co.uk/awilson/apim-subscription-key-header/</link><pubDate>Tue, 21 Nov 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-subscription-key-header/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>There is a potential unintentional side effect when you add a &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/api-management-subscriptions">APIM subscription key&lt;/a> as a header to an inbound request. The header is not stripped from the request prior to being sent to the configured backend service. Rather it is retained.&lt;/p>
&lt;p>If you manage the backing service and are not concerned with the disclosure of the subscription key, then no problem. &lt;strong>However&lt;/strong>, being overly permissive of this information may make your API more vulnerable to security threats and disallows a separation of concerns.&lt;/p></description></item><item><title>Desired State Configuration | Project DSC</title><link>https://blogs.blackmarble.co.uk/awilson/project-dsc/</link><pubDate>Mon, 23 Oct 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/project-dsc/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I have often found myself with a peeked interest into any method that will simplify both the on-boarding and return to a given project.&lt;/p>
&lt;p>Why the interest you may ask&amp;hellip;&lt;/p>
&lt;p>Well, in most cases when working on a given project (&lt;em>Greenfield or Brownfield&lt;/em>), one member of the team will scout ahead to make sure all the engineering tasks are complete. This often allows the development team to work in parallel without stepping on each others toes or be reclined to a halt due to engineering tasks that can only be conducted by a smaller subset of the team. These tasks often include:&lt;/p></description></item><item><title>BizTalk | Replacing Strong Name Keys</title><link>https://blogs.blackmarble.co.uk/awilson/biztalk-replacing-strong-name-keys/</link><pubDate>Wed, 28 Jun 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/biztalk-replacing-strong-name-keys/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>Strong Names provide .NET Framework assemblies with unique identities. When the .NET Framework loads a strong-named assembly for a referring assembly, it verifies the strong name signature. If the strong name signature of the assembly cannot be verified, the .NET Framework will not load the assembly.&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>!Do not rely on strong names for security. They provide a unique identity only!&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>Alternatively in our case, BizTalk assemblies are loaded into the Global Assembly Cache (GAC). In this case, instead of the .NET Framework verifying the assembly identity each time it requires loading, the assembly identity is verified once when installed into the GAC.&lt;/p></description></item><item><title>BizTalk | Deploying and Reading Secure SSO Settings</title><link>https://blogs.blackmarble.co.uk/awilson/biztalk-secure-sso-settings/</link><pubDate>Wed, 26 Apr 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/biztalk-secure-sso-settings/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>One of the fundamental parts to BizTalk for both configuration and integration applications is &lt;a href="https://learn.microsoft.com/en-us/biztalk/core/enterprise-single-sign-on-sso">&lt;code>Enterprise Single Sign On&lt;/code>&lt;/a>, or as we will continue to reference as &lt;code>SSO&lt;/code> from now on.&lt;/p>
&lt;p>SSO outside the bounds of BizTalk is an available service that is used to store and transmit encrypted user credentials. However, due to the nature of the service it is fairly generic, this has meant that many middleware applications and custom adapters have been designed to leverage SSO to securely store and transmit secure &lt;code>settings&lt;/code>.&lt;/p></description></item><item><title>Bicep | Deployment Scope Hopping</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-deployment-scope-hopping/</link><pubDate>Tue, 25 Apr 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-deployment-scope-hopping/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>An Azure Tenant is hierarchically structured with the following make up:&lt;/p>
&lt;ul>
&lt;li>Tenant&lt;/li>
&lt;li>One or more Management Groups&lt;/li>
&lt;li>One or more Subscriptions&lt;/li>
&lt;li>One or more Resource groups&lt;/li>
&lt;li>One or more Resources&lt;/li>
&lt;/ul>
&lt;p>
&lt;img src="https://andrewilson.co.uk/images/posts/2023/04/az-scopes.png" alt="AzureScopes">
&lt;/p>
&lt;p>Deployment Scopes &lt;code>{Tenant, Management Group, Subscription, Resource Group}&lt;/code> allow us to deploy respective types of resources at each level.&lt;/p>
&lt;p>A &lt;code>Scope&lt;/code> is dictated by two attributes, the selected scope level, and the identifier of the item at that scope level. For example, if I am to deploy at the Subscription Scope, I need to both Identify that I am doing a Subscription Deployment, and I need to provide the identifier of the Subscription. Resource Groups are the lowest in the list of Scope Levels.&lt;/p></description></item><item><title>Bicep | Conditional Iterative Deployment</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-conditional-iterative-deployment/</link><pubDate>Tue, 11 Apr 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-conditional-iterative-deployment/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>I have recently been looking at creating multiple of the same resource using Bicep. There is however a condition where I would wish for the set of resources not to be deployed. The following stages show my work through of this particular problem (&lt;em>using a storage account resource as an example&lt;/em>):&lt;/p>
&lt;h3 id="conditional-deployment">Conditional Deployment&lt;/h3>
&lt;p>&lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/conditional-resource-deployment">Conditional Deployment&lt;/a> is used where you may or may not wish to deploy a given resource depending on the outcome of a given condition (if statement).&lt;/p></description></item><item><title>Bicep Template | Shared Variable File Pattern</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-shared-variable-file-pattern/</link><pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-shared-variable-file-pattern/</guid><description>
&lt;h2 id="background">Background&lt;/h2>
&lt;p>I have recently been playing around with some of the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions">Bicep functions&lt;/a> when I came across a pattern by Microsoft called the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/patterns-shared-variable-file">&lt;strong>Shared Variable File Pattern&lt;/strong>&lt;/a>.&lt;/p>
&lt;p>This nifty pattern describes a method in which you can extract what would either be commonly used or complex configuration values away from your Bicep Template. Using the pattern will allow you to retain easy to read and manageable Bicep templates where you have modelled large variable configurations and or configuration values that are used repeatedly across your templates (prevents multiple copies of the value that would need to be maintained).&lt;/p></description></item><item><title>Automating Deployment of Azure Consumption Logic Apps | Bicep and ARM</title><link>https://blogs.blackmarble.co.uk/awilson/automate-deployment-of-azure-consumption-logic-apps/</link><pubDate>Fri, 24 Feb 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/automate-deployment-of-azure-consumption-logic-apps/</guid><description>
&lt;h2 id="azure-logic-apps">Azure Logic Apps&lt;/h2>
&lt;p>Azure Logic Apps is an Azure Integration Service (AIS) that provides you the ability to create and run automated workflows with little to no code. Consumption Logic Apps are developed using the visual designer within the Azure Portal.&lt;/p>
&lt;p>If you are new to developing Azure Logic Apps, there is great Microsoft Learning material to get you started:&lt;/p>
&lt;ul>
&lt;li>What are Azure Logic Apps | &lt;a href="https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-overview">https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-overview&lt;/a>&lt;/li>
&lt;li>Introduction to Azure Logic Apps | &lt;a href="https://learn.microsoft.com/en-us/training/modules/intro-to-logic-apps/">https://learn.microsoft.com/en-us/training/modules/intro-to-logic-apps/&lt;/a>&lt;/li>
&lt;li>Quickstart: Create an integration workflow | &lt;a href="https://learn.microsoft.com/en-us/azure/logic-apps/quickstart-create-first-logic-app-workflow">https://learn.microsoft.com/en-us/azure/logic-apps/quickstart-create-first-logic-app-workflow&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>Once you have created your workflow in the Logic App designer, your next question may be:&lt;/p></description></item><item><title>Fluent UI | React | Controlled multi-select Dropdown - Selected Keys</title><link>https://blogs.blackmarble.co.uk/awilson/fluent-ui-react-controlled-multi-select-dropdown-selected-keys/</link><pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/fluent-ui-react-controlled-multi-select-dropdown-selected-keys/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I ran into a problem the other day working with the Fluent UI React component &lt;code>Controlled Multi-select Dropdown&lt;/code>. As context, here is my redacted code and explanation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">import&lt;/span> { Dropdown, IDropdownOption } &lt;span style="color:#ff79c6">from&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;office-ui-fabric-react&amp;#39;&lt;/span>; &lt;span style="color:#6272a4">// office-ui-fabric-react@7.204.0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">export&lt;/span> &lt;span style="color:#ff79c6">interface&lt;/span> State {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> itemList: &lt;span style="color:#8be9fd">IDropdownOption&lt;/span>[];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> selectedItems: &lt;span style="color:#8be9fd">string&lt;/span>[];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">export&lt;/span> &lt;span style="color:#ff79c6">default&lt;/span> &lt;span style="color:#ff79c6">class&lt;/span> DropDownExample &lt;span style="color:#ff79c6">extends&lt;/span> React.Component&amp;lt;&lt;span style="color:#ff79c6">any&lt;/span>, &lt;span style="color:#50fa7b">State&lt;/span>&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">constructor&lt;/span>(context) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">super&lt;/span>(context);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">this&lt;/span>.state &lt;span style="color:#ff79c6">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> itemList&lt;span style="color:#ff79c6">:&lt;/span> [{ key&lt;span style="color:#ff79c6">:&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;None&amp;#39;&lt;/span>, text&lt;span style="color:#ff79c6">:&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;None&amp;#39;&lt;/span> }],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> selectedItems&lt;span style="color:#ff79c6">:&lt;/span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">this&lt;/span>.GetItems();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">this&lt;/span>.LoadPreselection();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">private&lt;/span> &lt;span style="color:#ff79c6">async&lt;/span> GetItems(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4">// ... load items into itemList
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">private&lt;/span> &lt;span style="color:#ff79c6">async&lt;/span> LoadPreselection(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4">// ... load pre-selected items into selectedItems
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">public&lt;/span> onItemChange &lt;span style="color:#ff79c6">=&lt;/span> (event: &lt;span style="color:#8be9fd">React.FormEvent&lt;/span>&amp;lt;&lt;span style="color:#ff79c6">HTMLDivElement&lt;/span>&amp;gt;, item: &lt;span style="color:#8be9fd">IDropdownOption&lt;/span>)&lt;span style="color:#ff79c6">:&lt;/span> &lt;span style="color:#ff79c6">void&lt;/span> &lt;span style="color:#ff79c6">=&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">if&lt;/span> (item) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">let&lt;/span> tempItemsArray &lt;span style="color:#ff79c6">=&lt;/span> selectedKeys;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">const&lt;/span> index &lt;span style="color:#ff79c6">=&lt;/span> tempItemsArray.indexOf(item.key, &lt;span style="color:#bd93f9">0&lt;/span>); &lt;span style="color:#6272a4">// Obtain item index if exists - returns -1 if it does not
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">if&lt;/span> (index &lt;span style="color:#ff79c6">&amp;gt;&lt;/span> &lt;span style="color:#ff79c6">-&lt;/span>&lt;span style="color:#bd93f9">1&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> tempItemsArray.splice(index, &lt;span style="color:#bd93f9">1&lt;/span>); &lt;span style="color:#6272a4">// If the item exists, remove the item from the existing array through the splice function
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span> } &lt;span style="color:#ff79c6">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> tempItemsArray.push(item.key); &lt;span style="color:#6272a4">// If the item does not exist, add the item to the existing array
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> setSelectedKeys(tempItemsArray); &lt;span style="color:#6272a4">// Update State
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> render() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">return&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;&lt;span style="color:#ff79c6">Dropdown&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">placeholder&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;[Select Item]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">disabled&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>{&lt;span style="color:#ff79c6">this&lt;/span>.state.itemList.length &lt;span style="color:#ff79c6">===&lt;/span> &lt;span style="color:#bd93f9">0&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">label&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;Items&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">id&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;items&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">responsiveMode&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>{&lt;span style="color:#bd93f9">1&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">multiSelect&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">options&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>{&lt;span style="color:#ff79c6">this&lt;/span>.state.itemList}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">selectedKeys&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>{&lt;span style="color:#ff79c6">this&lt;/span>.state.selectedItems}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#50fa7b">onChange&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>{&lt;span style="color:#ff79c6">this&lt;/span>.onItemChange.bind(&lt;span style="color:#ff79c6">this&lt;/span>)}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> );
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I had a list of items that I wanted to load into the Multi-select control from an API call. After obtaining the list of items, I wanted to preload any previously selected items.&lt;/p></description></item><item><title>Azure DevOps Pipeline | Git Shallow Fetch</title><link>https://blogs.blackmarble.co.uk/awilson/azure-devops-pipeline-shallow-fetch/</link><pubDate>Mon, 09 Jan 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/azure-devops-pipeline-shallow-fetch/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I have been recently working on building a new Yaml pipeline in Azure DevOps and wished to use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=gittools.gittools">GitVersion Task&lt;/a>, however, upon running the pipeline the task failed with the following error:&lt;/p>
&lt;pre tabindex="0">&lt;code>ERROR [../../.. ..:..:..:..] An unexpected error occurred:
System.NullReferenceException: Object reference not set to an instance of an object.
&lt;/code>&lt;/pre>&lt;p>After some digging and a conversation with one of my colleagues, it turns out there has been a change on Azure DevOps pipelines. By default now when a pipeline is created, the &amp;lsquo;&lt;em>Get Sources&lt;/em>&amp;rsquo; &lt;strong>Shallow fetch&lt;/strong> setting is enabled and set to a depth of 1.&lt;/p></description></item><item><title>Bicep | File Reference in a Git Repository Containing Spaces</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-git-repository-spaces/</link><pubDate>Fri, 06 Jan 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-git-repository-spaces/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>I recently started working on a Git Repository (&lt;em>not of my own creation&lt;/em>) that had a repository name containing spaces.&lt;/p>
&lt;p>As a helping hand when a repository is created with spaces in the name, the spaces are replaced with %20 when cloned &amp;hellip; Unless otherwise specified, however, this would then need to be specified whenever another user/pipeline clones the repo. See the git command below:&lt;/p>
&lt;pre tabindex="0">&lt;code>git clone https://.../.../my%20repo myrepo
&lt;/code>&lt;/pre>&lt;p>My best practice answer would be, &lt;strong>don&amp;rsquo;t create repositories with names containing spaces&lt;/strong>, but this one already did.&lt;/p></description></item><item><title>Azure Storage Account | Deletion and Reuse</title><link>https://blogs.blackmarble.co.uk/awilson/azure-storage-account-deletion/</link><pubDate>Thu, 05 Jan 2023 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/azure-storage-account-deletion/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>When it comes to creating Azure Storage Accounts, the &lt;a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview#storage-account-name">name&lt;/a> has some very important rules that need to be kept in mind. These rules will not only be important in the creation of the resource, but will be critical in deletion and reuse.&lt;/p>
&lt;p>The rules are as follows:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Storage account names &lt;strong>must&lt;/strong> be &lt;strong>between 3 and 24 characters in length&lt;/strong> and may &lt;strong>contain numbers and lowercase letters only&lt;/strong>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Your storage account &lt;strong>name must be unique within Azure&lt;/strong>. &lt;strong>No two storage accounts can have the same name&lt;/strong>.&lt;/p></description></item><item><title>Azure API Management | Product Required Subscription Behaviours</title><link>https://blogs.blackmarble.co.uk/awilson/apim-product-required-subscription-behaviours/</link><pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-product-required-subscription-behaviours/</guid><description>
&lt;h2 id="background--functional-workings-of-apim-subscriptions">Background | Functional Workings of APIM Subscriptions&lt;/h2>
&lt;p>Subscriptions are a nice and easy method of securing your APIs in APIM, however as I bumped into a small detail around their use the other day, I thought it wise to note it down.&lt;/p>
&lt;p>Azure API Management Subscriptions operate at &lt;strong>three&lt;/strong> scope levels:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>All APIs&lt;/strong>
&lt;ul>
&lt;li>Applies to any API that requires a Subscription.&lt;/li>
&lt;li>&lt;em>As this will allow access to &lt;strong>ANY&lt;/strong> api, use this with caution.&lt;/em>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Specific APIs&lt;/strong>
&lt;ul>
&lt;li>These subscriptions are linked to specific APIs, and their keys can only be used by those APIs.&lt;/li>
&lt;li>&lt;em>An API with a Specific subscription, as mentioned above, can be called with a generic All APIs Subscription Key.&lt;/em>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Products&lt;/strong>
&lt;ul>
&lt;li>Products are independent of APIs and therefore have their own &amp;lsquo;&lt;em>Subscription Required&lt;/em>&amp;rsquo; setting and behaviours. &lt;em>See Problem Space below.&lt;/em>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>As mentioned above, because Products are independent of APIs, their subscriptions operate slightly differently and &lt;strong>can cause some ill effects if unknown&lt;/strong>.&lt;/p></description></item><item><title>Azure API Management | Subscription Contract Names</title><link>https://blogs.blackmarble.co.uk/awilson/apim-subscription-contract-name/</link><pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-subscription-contract-name/</guid><description>
&lt;h2 id="problem-space">Problem Space&lt;/h2>
&lt;p>Subscriptions are a nice and easy method of securing your APIs in APIM, however as I bumped into a small detail around their use the other day, I thought it wise to note it down.&lt;/p>
&lt;p>When a Subscription Key is required on an API, as an invoker I will need to provide either a Header or a Parameter to my request which will contain the Subscription Key.&lt;/p>
&lt;p>By default:&lt;/p></description></item><item><title>Bicep File Template | VS Code Snippet</title><link>https://blogs.blackmarble.co.uk/awilson/bicep-template-snippet/</link><pubDate>Wed, 16 Nov 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/bicep-template-snippet/</guid><description>
&lt;h2 id="problem-space">Problem Space:&lt;/h2>
&lt;p>After developing native ARM templates for a year or two within a set structure, I have found myself applying the same structure to my Bicep templates using comments. This structure however is not setup by default, and in actuality, the sequencing of your bicep components doesn&amp;rsquo;t really matter as long as your dependencies are there.&lt;/p>
&lt;p>Of course we typically follow the standard pattern as shown below, but the larger the template the harder it is to see the breaks between.&lt;/p></description></item><item><title>Azure API Management | API Mocking</title><link>https://blogs.blackmarble.co.uk/awilson/apim-api-mocking/</link><pubDate>Sun, 18 Sep 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-api-mocking/</guid><description>
&lt;h3 id="problem-space">Problem Space:&lt;/h3>
&lt;p>I have been recently looking into setting up some APIs within API Management. I do not currently have any backing services to hook the API&amp;rsquo;s to and I would like to decouple development of the front end systems from the backend. Thankfully Azure API Management has provided the ability to create mocks for your API&amp;rsquo;s. In this post I will be walking through API mocking and how to achieve this within Bicep Templates for deployment.&lt;/p></description></item><item><title>Azure API Management | Purge Soft-Deleted Instance</title><link>https://blogs.blackmarble.co.uk/awilson/apim-purge-soft-deleted-instance/</link><pubDate>Wed, 07 Sep 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/apim-purge-soft-deleted-instance/</guid><description>
&lt;h3 id="problem-space">Problem Space:&lt;/h3>
&lt;p>Around June 2020 a change was made to Azure API Management whereby any deletion of the instance via the Azure portal, Azure PowerShell, Azure CLI, and REST API version &lt;code>2020-06-01-preview&lt;/code> or later will result in the instance being &lt;em>&lt;strong>soft-deleted&lt;/strong>&lt;/em>.&lt;/p>
&lt;p>This is to allow for recoverability of a recently deleted API Management instance, and therefore protecting against accidental deletion of the instance.&lt;/p>
&lt;p>The problem with this is that not all the Azure Resource Management tooling currently supports the management of soft deleted API Management Instances. Currently the only management tooling that supports this feature are the REST API and Azure CLI. You cannot at this point in time list, show, or purge a soft deleted instance in the Management Portal or Azure PowerShell.&lt;/p></description></item><item><title>Azure Logic App | Parallel Terminates &amp; Action State Checking</title><link>https://blogs.blackmarble.co.uk/awilson/azure-logic-app-parallel-terminate/</link><pubDate>Sun, 04 Sep 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/azure-logic-app-parallel-terminate/</guid><description>
&lt;h2 id="problem-space">Problem Space:&lt;/h2>
&lt;p>I have recently encountered an interesting problem space with Azure logic app action &lt;code>run after&lt;/code> logic. I ran into the problem whilst creating a logic app that will perform actions in parallel. The bulk of the actions are performed in scopes. If an action fails within the first set of scopes, the scope status is &lt;code>Failed&lt;/code>. If the first scope fails, then the second scope full of actions are executed (&lt;em>this based on run after logic&lt;/em>). The problem with this is that I still need the logic app to terminate as Failed so that an alert will be fired off.&lt;/p></description></item><item><title>Azure Role Assignment</title><link>https://blogs.blackmarble.co.uk/awilson/azure-assign-role/</link><pubDate>Fri, 02 Sep 2022 00:00:00 +0000</pubDate><author>Andrew Wilson</author><guid>https://blogs.blackmarble.co.uk/awilson/azure-assign-role/</guid><description>
&lt;h2 id="problem-space">Problem Space:&lt;/h2>
&lt;p>I recently came into some issues with assigning Azure roles through a Bicep template and pipeline deployment. I was looking to assign &amp;lsquo;&lt;em>Storage Blob Data Reader&lt;/em>&amp;rsquo; to a service principal, and refine their access to only the container of the storage account. The three main issues that I ran into were:&lt;/p>
&lt;ol>
&lt;li>What are &lt;a href="#role-assignment-conditions">Role Assignment Conditions&lt;/a> and how can I use them in my template?&lt;/li>
&lt;li>I am trying to assign a built in role, what is the &lt;a href="#identifying-the-role-definition-id">roleDefinitionId&lt;/a> that I should be using?&lt;/li>
&lt;li>I am trying to assign the role to a &lt;a href="#referencing-a-service-principal-id">service principal user&lt;/a>, what id should I be referencing in the template?&lt;/li>
&lt;/ol>
&lt;p>For reference, the Bicep template for role assignment&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> that I am using is shown below:&lt;/p></description></item></channel></rss>