Power Platform Pipelines - Delegated Deployment Architectural Pattern for Connections with oAuth
Wow that's a long title! 😲 But it's accurate. And it's difficult to figure out. I spent a bit of time recently trying to figure out the best architectural patterns for Power Platform Pipelines and try to document which ones can be used and where. You have 3 options for Power Platform Pipeline deployments, User Deployment (or Standard Pipeline deployment), Delegated Deployment Stage Owner (User/Service Account) or Delegated Deployment Service Principal. Each one has their advantages and disadvantages but the interesting things here is how to work with connections.
But why connections? Why are connections the important part here? Well, most solution artefacts are fine to be imported by a user or Service Principal, the biggest issue are connections.
Basically, when you create a flow that connects to a data source, you create a connection and connection reference to data source. A connection reference is kinda like the metadata for how a flow connects to a data source. It include the data source and the connection, however the connection is separate from the connection reference. The connection is the actual authentication to the data source.
Some data sources like Dataverse, support a Service Principal natively connecting and can act as the connection, however other oAuth data sources, like SharePoint or Outlook do not support this. Again, why is any of this important?
Each of the types of deployment handle connections differently.
User Deployment - These will prompt the user to sign into the data source to create the connection or will check if there is an existing connection for this user in the target environment and allow you to use this.
Delegated Deployment Stage Owner - This will deploy artefacts as the User who owns the stage and not the user triggering the deployment. However, if a different user tries to deploy a flow with their connections, and they are not the stage owner, the deployment will fail. This is because the the Stage Owner, cannot have connections created for them by the triggering user. It says in the documentation this does not work.
Delegated Deployment Service Principal - This will deploy artefacts and it will prompt to share the connections with the Service Principal. This will work, but it will create/use the connections as the user running the deployment.
User Deployment or Service Principal deployments are easy to understand, but both have a downside, when the user leaves the organisation and their account is deactivated, the flows will stop working. The Service Principal also has another issue which is that the flow will be owned as the Service Principal and unless it is in the context of a Dynamics 365 Application, it will require a Power Automate Process License to cover those automations.
The Delegated Deployment Stage Owner seems like the most useful, if we think of the Stage Owner as a Service Account. A regular user account, except the account is never disabled and you can assign permissions to that account that it needs and no more. Some organisations allow Service Accounts for building solutions, some do not. But if you don't want to have to handle multiple connections in a production environment and have flows turn off when people leave, it's often the best approach. I reference how to approach flow and connection ownership in my best practices guide.
You can use a Delegated Deployment with Stage Owner as a Service Account and have the connection work, but it requires some preparation.
Firstly, create a solution containing connection references that you require for your solutions. I'd recommend creating all that you think you need. You can add to them later, but it would be easier to maintain if you know all of them up front. Next, deploy the solution with these connection references to you test, pre-prod, prod environments etc, with the Service Account. A manual deployment is easiest for this. As you deploy, you create the connections as the Service Account in the other environments.
A connection does not move between environments, they are unique to the environments they are created in. Thus this needs to be done before you can deploy your flows.
This is good but still doesn't solve the problem, as even with a delegated deployment, connection references and connections cannot be shared with other users. People have made workarounds for this like creating dummy flows with connection references, but I think this is a better solution.
If you use a Delegated Deployment, you need to use an approval and the approval has to come from a connection for the Stage Owner (Service Account) or Service Principal. You can read up on how to create these here and I will cover these parts in more details in a separate blog post, for now, we just want to discuss the pattern.
As such, you will need to setup a pre-deployment flow for the approval, but this also opens up another possibility, Deployment Settings JSON. If you are familiar with Azure DevOps Pipelines or the PAC CLI, you may be familiar with this concept, but this is the ability to configure settings such as Environment Variables and Connections for the deployment. You can read more about them here.
When you trigger the deployment, if the solution contains deployment settings that need to be deployed at the same time, they will create them in the Deployment JSON Settings column and they will look something like this:
{
"EnvironmentVariables":[],
"ConnectionReferences":[
{"LogicalName":"mcj_sharedoffice365_b3781",
"ConnectionId":"46f5fa142d87446e9b1f09054b5ca64d","
ConnectorId":"/providers/Microsoft.PowerApps/apis/shared_office365"},{"LogicalName":"mcj_sharedsharepointonline_7f828",
"ConnectionId":"shared-sharepointonl-c8092739-c9bf-4a25-838a-82508edd0f10",
"ConnectorId":"/providers/Microsoft.PowerApps/apis/shared_sharepointonline"}
]
}
This gives you an opportunity to update the settings, so you can update the connections to the connections you have in your UAT, Pre-prod, Production environments etc.
The important part here is you need to take the deploying connection reference and only update the connection (ConnectionId) to be the one in the target environment.
For clarity, the 3 parameters in the above code, this is how you want to update them:
LogicalName - Deploying solution (do not update)
ConnectionId - Target Environment (Service Accounts connection, update this to the one in the target environment)
ConnectorId - Deploying solution (this can also be used to determine the data source so you can update the right ConnectionId, do not update)
Once you update the connections through the Deployment Setting JSON and write that back to your Deployment Stage Run record and approve the deployment, the solution will deploy.
The above diagram is to illustrate the change in connections from Bob to Fred via the deployment JSON settings change, not that connections can be sent in solutions.
Now here is the great part, as you deploy, despite the triggering user not having access to the connections of the Service Account (Stage Owner), the Service Account that does the deploying, does, meaning it can find it's connection and use that for the connection reference and therefore the flows. Once your deployment completes, you flows switch on, no manual or additional flows to go switch on or needing to update connections before they switch on.
I'll have a future blog post detailing how to do the Deployment Setting update dynamically.
Ciao for now MCJ
Comments