Pipeline Service Connections - Best Practices
Service Connections Overview
It is common to connect to external and remote services to execute tasks in a job. (See the Pipelines Versioning P&P for more info about tasks, jobs, stages, and pipelines.) Examples of this include connecting to an Azure subscription, a different build or file server, to a continuous integration environment, or to services installed on remote computers. To do this you will need to use service connections in Azure Pipelines.
Creation of Service Connections
Service connections will be created and maintained by Organization Administrators and the Energizers team so that we can ensure security protocols are maintained and we are following least privilege access principles. This also aligns with IT policies which requires users to be trained and added to a security group to be able to create and maintain service principles in Azure DevOps.
Service Connection Guiding Principles
- Keep the number of service connections as small as possible.
- Always follow least privilege access principles.
- Azure DevOps names service connections with the project name followed by a GUID. The creator of the service connection should rename it so that it is clear what the intended use is.
Using Service Connections
By default a service connection exists in a specific project. However, we can and should enable sharing of service connections across the organization. This will be done in the case of many of the common service connections, but note that we can also keep a service connection within only a single project (for security reasons for example). In order to share a service connection from a different project to your project within same organization, you need to create a support ticket With Energizers Team.
When a team discovers a need to connect to an external service or to deploy Azure resources, they should reach out to the Energizers team and a representative from the security team to determine the risk associated with the request and to identify the access required to do the job.
When a service connection is used in a new way, it will have to be authorized by the Organization Administrators. A support ticket should be filed and placed in the Energizers backlog to track this work. In the support ticket you should specify what service you want to connect to and the pipeline and/or repo you want to connect from. After completing the authorization request, that service connection will be part of the pipeline's deployment process.
Creating a service connection
- Go to project settings for a project.
- Select Service connections.
- Press "New service connection" button.
- Select the type of service connection. (See next process)
- Press Next.
Note: Many service connection types exist but two of the most common are being discussed here for examples.
Azure Resource Manager service connections
At step 4 above in "creating a service connection" when selecting a type of service connection the "Azure Resource Manager" service connection can be selected. It is used to grant access from pipelines to resources within an Azure Subscription. This is used often to access an Azure Key Vault for secrets or access some other resource for deployment or storage by a pipeline.
After the above procedure, assuming you selected an "Azure Resource Manager" service connection type.
- Select "Service principal (automatic)" this creates a service account in Azure AD. To do this you need to be a member of the Azure Application Developer role or in a group that can create service accounts. Contact IT to get added to this group.
- Select Next.
- For nearly all of our connections we will select "Subscription" the other options are for higher level multiple Azure subscription based access which we do not need.
- Make sure the subscription says "Simplified DevOps Architecture" unless you are setting up access to a legacy or alternative subscription in Azure. The "Simplified DevOps Architecture" subscription is aligned with the MDTProductDevelopment Azure DevOps organization for billing and use.
- Resource group is optional, it restricts the service account to only resources in that one resource group.
- For service connection name we recommend the following for arm connections. mdtpd-to-arm-somename-prod For production subscriptions and -dev for non-production connections.
- Provide a description on what access this service connection provides.
- If this should be automatically available to all pipelines leave the "grant access permission to all pipelines" checked. This is normal unless we want to control use (for example a special production account).
- Press "Save".
Azure Repos/Team Foundation Server service connections
At step 4 above in "creating a service connection" when selecting a type of service connection the "Azure Repos/Team Foundation Server" service connection can be select to access another azure devops organization's repositories.
- Select "Token based authentication"
- For connection URL past the URL to the organization or project collection. This can be seen on the organization overview page https://dev.azure.com/MDTProductDevelopment/_settings/organizationOverview for an organization just under the organization's name. But generally it is in the format for Azure DevOps https://dev.azure.com/OrganizationName/
- In Personal Access Token paste in a PAT that has access to the resources in the other org you need to access. Remember when this PAT expires it will need to be updated in the service connection.
- For service connection name we recommend the following for arm connections. mdtpd-to-azdo-orgname-prod For production subscriptions and -dev for non-production connections.
- Provide a description on what access this service connection provides.
- If this should be automatically available to all pipelines leave the "grant access permission to all pipelines" checked. This is normal unless we want to control use (for example a special production account).
- Press "Verify and Save".
Service connection security
- Select from the project's service connection list the service connection name.
- Select the ... in the upper right corner on the service connection.
- Select security.
- Grant using the "Add" button under "User Permissions" access to the project's project administrators. These look like
[carelink]\Project Administrators
in their format. - The role granted to these project administrator groups should be "Administrator".
Sharing connections
To share a connection with multiple projects follow the procedures above to create the service connection in one and then....
- Select from the project's service connection list the service connection name.
- Select the ... in the upper right corner on the service connection.
- Select security.
- Select the
+
in the section titled project permissions. - Select each additional project which should have access to the service connection.
Note: When you share a connection with another project it gets a suffix of -projectname added. The original service connection does not have this suffix. See the following section for how to remove this.
Renaming shared service connections to remove suffix.
Sometimes you don't want each shared service connection to have a different name. To correct that from the screen where you shared the service connections do the following:
- Click on the hyperlinked name of the service connection in the list of project permissions.
- Press the
Edit
button. - Remove the suffix from the service connection name.
- Press Save.
- Repeat for any other shared connections.
Renaming the azure service principal
While this is optional it can make it easier to find the service principal while applying it to resources in Azure.
- Select from the project's service connection list the service connection name.
- Select the hyperlink in the details titled "Manage Service Principal". Azure portal will launch.
- Select the display name hyperlink.
- Change the name to match the service connection name you applied in Azure DevOps
- Press save.
This will change the name in Azure for some selection lists.
Granting a service principal access to key vault secrets in Azure
- Create an Azure Resource Manager service connection that has access to the resource group or subscription with the key vault.
- Navigate in the Azure portal to the Azure Key Vault resource (you can search for it by name in https://portal.azure.com)
- Select Access Policies
- Select Add Access Policy
- For secrets, the most common, Select secret permissions Get, List (and any others that are needed like Set, Delete)
- Under Select Principal press the none selected hyperlink.
- Enter the name of the service principal for the account (if you renamed it is is easier to find)
- Press Select.
- Press Add.
- Press Save.
If your service connection has access to the resource group or entire subscription of the Azure Key Vault it will now be able to do operations on the secrets stored in the vault inside of pipelines.
References
- https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml
- https://docs.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops
- http://techgenix.com/azure-devops-service-connections/
- https://docs.microsoft.com/en-us/azure/devops/pipelines/security/infrastructure?view=azure-devops