Blogs

Logic App Standard – Local Development and Managed Identities in 2024

Anyone who has picked up and started using Azure’s Logic App Standard offering in the last couple of years will have seen the advancements made in the space to provide a developer first experience using Visual Studio Code to build out workflows. Admittedly in the early days I wasn’t sold as there were some really big pain points, but i am slowly coming around. Regardless Logic App Standard workflows are far more developer friendly unlike the traditional consumption logic apps that are purely browser-based.

This is the first in a series of blogs about some of the learninings I have had along the way in the last few months

The Challenge: Managed Identity

When connecting to other Azure Resources like Azure Service Bus to test workflows ideally in a perfect world, we want to avoid using connection strings to connect with these services where possible and use either System or User-assigned identities with appropriate least privilege Role-Based Access Controls. Unfortunately, the Azure and Logic App Standard extensions do not support managed identity connections from VS Code to Azure Resources. So connection strings must be used locally so the challenge was this….

How can I build Logic App Workflows on my local development machine but once we deploy (via Github Actions) only managed identities are used

What other blogs say?

The only solution that I found on the internet was to maintain two connections in the connections.json file (one for connection strings and one for managed identity) and pass the name of the connection to use as a parameter to the workflow. The connections.json file would look something like this

				
					{
  "serviceProviderConnections": {
    "serviceBusConnectionString": {
      "parameterValues": {
        "connectionString": "@appsetting('serviceBus_connectionString')"
      },
      "parameterSetName": "connectionString",
      "serviceProvider": {
        "id": "/serviceProviders/serviceBus"
      },
      "displayName": "ServiceBusConnection Connection String"
    },
    "serviceBusManagedIdentity": {
      "displayName": "Service Bus Connection Managed ManagedServiceIdentity",
      "parameterSetName": "ManagedServiceIdentity",
      "parameterValues": {
        "authProvider": {
          "Type": "ManagedServiceIdentity"
        },
        "fullyQualifiedNamespace": "@appsetting('serviceBus_fullyQualifiedNamespace')"
      },
      "serviceProvider": {
        "id": "/serviceProviders/serviceBus"
      }
    }
  },
  "managedApiConnections": {}
}
				
			

We then go into the workflow.json and update the triggers section to use the parameter to determine the connection type to use when executing the trigger

				
					 "triggers": {
            "When_messages_are_available_in_a_topic_subscription_(peek-lock)": {
                "type": "ServiceProvider",
                "inputs": {
                    "parameters": {
                        "topicName": "example-topic-name",
                        "subscriptionName": "example-topic-name-subscription",
                        "isSessionsEnabled": false
                    },
                    "serviceProviderConfiguration": {
                        "connectionName": "@{parameters('ServiceBusConnectionType')}",
                        "operationId": "peekLockTopicMessages",
                        "serviceProviderId": "/serviceProviders/serviceBus"
                    }
                },
                "splitOn": "@triggerOutputs()?['body']"
            }
        }
				
			

This solution absolutely works as you’d expect and perfectly acceptable as an implementation. But!

Is there another way?

The more I thought about it, what I didn’t like was that both connections were still available to be used once we had deployed the Logic App via GitHub in Azure.

The Alternative Approach

The approach I ended up taking was to have two connection.json files. One to use locally and then one that would be used when deployed to Azure.
 
What this achieves in my mind
  • We only want to use Managed Identities and RBAC Roles – No connections strings
  • Simplifies workflows where there’s no parameter passed in for the connection (when multiple connections are used this would get messy)
  • The developer had to make a conscious decision to think about the connection style that will be used
  • The one perceived downside is that there are now two connection files to maintain.

 

In the Logic App Project you will need to have two connections files

  •  connnections.json – This file is the one that’s created when you create a new project and this file maintains the connection string versions of the resources are going to be used locally
				
					{
  "serviceProviderConnections": {
    "serviceBus": {
      "parameterValues": {
        "connectionString": "@appsetting('serviceBus_connectionString')"
      },
      "parameterSetName": "connectionString",
      "serviceProvider": {
        "id": "/serviceProviders/serviceBus"
      },
      "displayName": "ServiceBusConnection"
    }
  },
  "managedApiConnections": {}
}

				
			
  • connnections.deploy.json – This file needs to be created manually, this is the file that will be used when the project is packaged and deployed to Azure via a GitHub Action.
				
					{
  "serviceProviderConnections": {
    "serviceBus": {
      "parameterSetName": "ManagedServiceIdentity",
      "parameterValues": {
        "authProvider": {
          "Type": "ManagedServiceIdentity"
        },
        "fullyQualifiedNamespace": "@appsetting('serviceBus_fullyQualifiedNamespace')"
      },
      "serviceProvider": {
        "id": "/serviceProviders/serviceBus"
      }
    },
    "displayName": "ServiceBusMsi"
  },
  "managedApiConnections": {},
}
				
			

NOTE: The key thing to note here is that the name of the connection (“serviceBus”) needs to match across both files in order for this to work.

Great! Now when the workflow is run from Visual Studio Code it’ll look up the application setting “serviceBus_connectionString” from local.settings.json and connect to it

Your project structure in Visual Studio Code should look something like this

VS Code Project Structure
VS Code Project Structure

But what about when we deploy?

As part of the GitHub build action we have defined the first step before we package the code there is an additional step added to action which will remove the existing connections.json file and rename the connections.deploy.json to connections.json

				
					        # Remove the local dev connections.json and replace it with the connections.deploy.json which azure should use
      - name: Logic App Remove and Rename Connections
        run: |
          rm src/yourLogicAppProjectName/connections.json
          mv src/yourLogicAppProjectName/connections.deploy.json src/yourLogicAppProjectName/connections.json
				
			
 Now our deployment package has no traces of anything to do with connection string to connect to Azure Resources!
 
When we go to the connections blade in the Azure Portal we see that our connection is deployed successfully with the correct connections
Deployed Managed Identity Connection
Deployed Managed Identity Connection

Closing Thought

This is simply an alternative approach to the parameter based solutions that I have seen implemented. One future improvement I would make would be to include a script in the GitHub action that executes at the time of Pull Request performing a check to ensure the connection files have the same number and named connections.

Hope you found this helpful! Leave a comment with your thoughts!

 

 

[mailpoet_form id="1"]

Other Recent Blogs

Microsoft Teams IP Phones and Intune Enrollment

Microsoft Teams provides a growing portfolio of devices that can be used as desk and conference room phones. These IP phones run on Android 8.x or 9.x and are required to be enrolled in Intune. By default, these devices are enrolled as personal devices, which is not ideal as users should not be able to enrol their own personal Android devices.

Read More »

Level 9, 360 Collins Street, 
Melbourne VIC 3000

Level 2, 24 Campbell St,
Sydney NSW 2000

200 Adelaide St,
Brisbane QLD 4000

191 St Georges Terrace
Perth WA 6000

Level 10, 41 Shortland Street
Auckland

Part of

Arinco trades as Arinco (VIC) Pty Ltd and Arinco (NSW) Pty Ltd. © 2023 All Rights Reserved Arinco™ | Privacy Policy | Sustainability and Our Community
Arinco acknowledges the Traditional Owners of the land on which our offices are situated, and pay our respects to their Elders past, present and emerging.

Get started on the right path to cloud success today. Our Crew are standing by to answer your questions and get you up and running.