Skip to content

Commit

Permalink
Feature #43 - Export all serviceconnections (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
webtonize authored Oct 19, 2023
1 parent 16252a5 commit 8f1d717
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 36 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ in building the ruleset for this module.
- [Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md)
- [Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md)
- [Azure.DevOps.Repos.InheritedPermissions](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md)
- [Azure.DevOps.ServiceConnections.ClassicAzure](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md)
- [Azure.DevOps.ServiceConnections.Description](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md)
- [Azure.DevOps.ServiceConnections.GitHubPAT](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md)
- [Azure.DevOps.ServiceConnections.ProductionBranchLimit](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md)
- [Azure.DevOps.ServiceConnections.ProductionCheckProtection](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md)
- [Azure.DevOps.ServiceConnections.ProductionHumanApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md)
Expand Down
4 changes: 3 additions & 1 deletion docs/security-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ You can change the configuration of your organization or project if you have [Pr
> :o: [**Azure.DevOps.ServiceConnections.Scope**](../src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md)
- Don’t give users generic or broad contributor rights on the Azure subscription.
- Don’t use Azure Classic service connections, as there’s no way to scope the permissions.
- Don’t use Azure Classic service connections, as there’s no way to scope the permissions.
> :o: [**Azure.DevOps.ServiceConnections.ClassicAzure**](../src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md)
- Make sure the resource group only contains Virtual Machines (VMs) or resources that the build needs access to.
- Use a purpose-specific team service account to authenticate a service connection.
- For more information, see [Common service connection types](../../pipelines/library/service-endpoints.md).
Expand Down Expand Up @@ -324,6 +325,7 @@ If possible, we recommended to always use identity services for authentication i
## Secure GitHub Integrations

- Disable Personal Access Token (PAT)-based authentication, so the OAuth flow gets used with the GitHub service connection.
> :o: [**Azure.DevOps.ServiceConnections.GitHubPAT**](../src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md)
- Never authenticate GitHub service connections as an identity that's an administrator or owner of any repositories.
- Never use a full-scope GitHub PAT (Personal Access Token) to authenticate GitHub service connections.
- Don't use a personal GitHub account as a service connection with Azure DevOps.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
Project name for Azure DevOps
.EXAMPLE
Get-AzDevOpsArmServiceConnections -PAT $PAT -Organization $Organization -Project $Project
Get-AzDevOpsServiceConnections -PAT $PAT -Organization $Organization -Project $Project
#>
function Get-AzDevOpsArmServiceConnections {
function Get-AzDevOpsServiceConnections {
[CmdletBinding()]
param (
[Parameter()]
Expand All @@ -44,10 +44,10 @@ function Get-AzDevOpsArmServiceConnections {
}

$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header
return $response.value | Where-Object { $_.type -eq 'azurerm' }
return $response.value
}
Export-ModuleMember -Function Get-AzDevOpsArmServiceConnections
# End of Function Get-AzDevOpsArmServiceConnections
Export-ModuleMember -Function Get-AzDevOpsServiceConnections
# End of Function Get-AzDevOpsServiceConnections

<#
.SYNOPSIS
Expand All @@ -69,12 +69,12 @@ Export-ModuleMember -Function Get-AzDevOpsArmServiceConnections
Service connection id for Azure DevOps
.EXAMPLE
Get-AzDevOpsArmServiceConnectionChecks -PAT $PAT -Organization $Organization -Project $Project -ServiceConnectionId $ServiceConnectionId
Get-AzDevOpsServiceConnectionChecks -PAT $PAT -Organization $Organization -Project $Project -ServiceConnectionId $ServiceConnectionId
.LINK
https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/check-configurations/list?view=azure-devops-rest-7.2&tabs=HTTP
#>
function Get-AzDevOpsArmServiceConnectionChecks {
function Get-AzDevOpsServiceConnectionChecks {
[CmdletBinding()]
param (
[Parameter()]
Expand Down Expand Up @@ -104,8 +104,8 @@ function Get-AzDevOpsArmServiceConnectionChecks {
}
return $response.value
}
Export-ModuleMember -Function Get-AzDevOpsArmServiceConnectionChecks
# End of Function Get-AzDevOpsArmServiceConnectionChecks
Export-ModuleMember -Function Get-AzDevOpsServiceConnectionChecks
# End of Function Get-AzDevOpsServiceConnectionChecks

<#
.SYNOPSIS
Expand All @@ -127,12 +127,12 @@ Export-ModuleMember -Function Get-AzDevOpsArmServiceConnectionChecks
Output path for JSON files
.EXAMPLE
Export-AzDevOpsArmServiceConnections -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsServiceConnections -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
.LINK
https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/check-configurations/list?view=azure-devops-rest-7.2&tabs=HTTP
#>
function Export-AzDevOpsArmServiceConnections {
function Export-AzDevOpsServiceConnections {
[CmdletBinding()]
param (
[Parameter()]
Expand All @@ -149,17 +149,17 @@ function Export-AzDevOpsArmServiceConnections {
$OutputPath
)
# Get all service connections
$serviceConnections = Get-AzDevOpsArmServiceConnections -PAT $PAT -Organization $Organization -Project $Project
$serviceConnections = Get-AzDevOpsServiceConnections -PAT $PAT -Organization $Organization -Project $Project
$serviceConnections | ForEach-Object {
$serviceConnection = $_
# Set JSON ObjectType field to Azure.DevOps.ServiceConnection
$serviceConnection | Add-Member -MemberType NoteProperty -Name ObjectType -Value 'Azure.DevOps.ServiceConnection'
# Get checks for service connection
$serviceConnectionChecks = @(Get-AzDevOpsArmServiceConnectionChecks -PAT $PAT -Organization $Organization -Project $Project -ServiceConnectionId $serviceConnection.id)
$serviceConnectionChecks = @(Get-AzDevOpsServiceConnectionChecks -PAT $PAT -Organization $Organization -Project $Project -ServiceConnectionId $serviceConnection.id)
$serviceConnection | Add-Member -MemberType NoteProperty -Name Checks -Value $serviceConnectionChecks
Write-Verbose "Exporting service connection $($serviceConnection.name) as file $($serviceConnection.name).ado.sc.json"
$serviceConnection | ConvertTo-Json -Depth 100 | Out-File "$OutputPath/$($serviceConnection.name).ado.sc.json"
}
}
Export-ModuleMember -Function Export-AzDevOpsArmServiceConnections
# End of Function Export-AzDevOpsArmServiceConnections
Export-ModuleMember -Function Export-AzDevOpsServiceConnections
# End of Function Export-AzDevOpsServiceConnections
2 changes: 1 addition & 1 deletion src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Function Export-AzDevOpsRuleData {
)
Export-AzDevOpsReposAndBranchPolicies -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsEnvironmentChecks -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsArmServiceConnections -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsServiceConnections -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsPipelines -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsPipelinesSettings -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Export-AzDevOpsVariableGroups -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
category: Microsoft Azure DevOps Service Connections
severity: Severe
online version: https://github.com/cloudyspells/PSRule.Rules.AzureDevOps/blob/main/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md
---

# Azure.DevOps.ServiceConnections.ClassicAzure

## SYNOPSIS

A Service connection should not use the Classic Azure service connection type.

## DESCRIPTION

A service connection is a securely stored object that contains information about how to
connect to a service. Service connections are used during the build or release pipeline to
connect to external and remote resources. The Classic Azure service connection type can not
be scoped to a specific resource group or subscription. This means that any user with
access to the service connection can deploy to any resource group or subscription. Also
the Classic Azure service connection type does not support modern ways of authentication.

## RECOMMENDATION

Consider using a service connection type that can be scoped to a specific resource group
with modern authentication.

## LINKS

- [Azure DevOps security best practices](https://learn.microsoft.com/en-us/azure/devops/organizations/security/security-best-practices?view=azure-devops#scope-service-accounts)
- [Create a service connection](https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-using-workload-identity-federation)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
category: Microsoft Azure DevOps Service Connections
severity: Severe
online version: https://github.com/cloudyspells/PSRule.Rules.AzureDevOps/blob/main/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md
---

# Azure.DevOps.ServiceConnections.GitHubPAT

## SYNOPSIS

A service connection should not use a GitHub Personal Access Token (PAT).

## DESCRIPTION

A service connection is a secure stored object that contains information about how to
connect to a service. Service connections are used during the build or release pipeline
to connect to external and remote resources. The GitHub PAT service connection type is
linked to a personal account and cannot be traced back to the specific connection from
Azure DevOps. This means any user with access to the service connection can impersonate
the user who created the service connection.

## RECOMMENDATION

Consider using an oauth-based service connection.

## LINKS

- [Azure DevOps security best practices](https://learn.microsoft.com/en-us/azure/devops/organizations/security/security-best-practices?view=azure-devops#secure-github-integrations)
- [Create a service connection](https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
category: Microsoft Azure DevOps Service Connections
severity: Severe
online version: https://github.com/cloudyspells/PSRule.Rules.AzureDevOps/blob/main/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ClassicAzure.md
---

# Azure.DevOps.ServiceConnections.ClassicAzure

## SYNOPSIS

Een serviceverbinding mag niet het klassieke Azure-serviceverbindingstype gebruiken.

## DESCRIPTION

Een serviceverbinding is een veilig opgeslagen object dat informatie bevat over hoe u
verbinding kunt maken met een service. Serviceverbindingen worden tijdens de build- of
release-pijplijn gebruikt om verbinding te maken met externe en externe bronnen. Het
klassieke Azure-serviceverbindingstype kan niet worden geschaald naar een specifieke
resourcegroep of abonnement. Dit betekent dat elke gebruiker met toegang tot de
serviceverbinding kan implementeren naar elke resourcegroep of elk abonnement. Ook het
klassieke Azure-serviceverbindingstype ondersteunt geen moderne manieren van authenticatie.

## RECOMMENDATION

Overweeg om een serviceverbindingstype te gebruiken dat kan worden geschaald naar een
specifieke resourcegroep met moderne authenticatie.

## LINKS

- [Azure DevOps security best practices](https://learn.microsoft.com/nl-nl/azure/devops/organizations/security/security-best-practices?view=azure-devops#scope-service-accounts)
- [Create a service connection](https://learn.microsoft.com/nl-nl/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-using-workload-identity-federation)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
category: Microsoft Azure DevOps Service Connections
severity: Severe
online version: https://github.com/cloudyspells/PSRule.Rules.AzureDevOps/blob/main/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.GitHubPAT.md
---

# Azure.DevOps.ServiceConnections.GitHubPAT

## SYNOPSIS

Een serviceverbinding zou geen GitHub-persoonlijke toegangstoken (PAT) moeten gebruiken.

## DESCRIPTION

Een serviceverbinding is een veilig opgeslagen object dat informatie bevat over hoe u
verbinding kunt maken met een service. Serviceverbindingen worden tijdens de build- of
release-pijplijn gebruikt om verbinding te maken met externe en externe bronnen. Het GitHub
PAT-serviceverbindingstype is gekoppeld aan een persoonlijk account en kan niet worden
getraceerd naar de specifieke verbinding vanuit Azure DevOps. Dit betekent dat elke
gebruiker met toegang tot de serviceverbinding zich kan voordoen als de gebruiker die de
serviceverbinding heeft gemaakt.

## RECOMMENDATION

Overweeg een oauth-gebaseerde serviceverbinding te gebruiken.

## LINKS

- [Azure DevOps security best practices](https://learn.microsoft.com/nl-nl/azure/devops/organizations/security/security-best-practices?view=azure-devops#secure-github-integrations)
- [Create a service connection](https://learn.microsoft.com/nl-nl/azure/devops/pipelines/library/connect-to-azure?view=azure-devops)
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Rule 'Azure.DevOps.ServiceConnections.Scope' `
-Ref 'ADO-SC-004' `
-Type 'Azure.DevOps.ServiceConnection' `
-Tag @{ release = 'GA'} `
-If { $TargetObject.data.scopeLevel -eq 'Subscription' } `
-If { $TargetObject.data.scopeLevel -eq 'Subscription' -and $TargetObject.type -eq 'azurerm' } `
-Level Information {
# Description 'Service connection should have a scope that is not an entire subscription.'
Reason 'The service connection is scoped to a subscription.'
Expand All @@ -64,7 +64,7 @@ Rule 'Azure.DevOps.ServiceConnections.WorkloadIdentityFederation' `
-Ref 'ADO-SC-005' `
-Type 'Azure.DevOps.ServiceConnection' `
-Tag @{ release = 'GA'} `
-If { $TargetObject.data.scopeLevel -eq 'Subscription' } `
-If { $TargetObject.data.scopeLevel -eq 'Subscription' -and $TargetObject.type -eq 'azurerm' } `
-Level Warning {
# Description 'Service connection should should use Workload Idenity Federation.'
Reason 'The service connection does not use Workload Idenity Federation.'
Expand All @@ -89,3 +89,29 @@ Rule 'Azure.DevOps.ServiceConnections.ProductionBranchLimit' `
$Assert.HasField($TargetObject, "Checks[[email protected] == 'Branch control'].settings.inputs.allowedBranches", $true)
$Assert.HasFieldValue($TargetObject, "Checks[[email protected] == 'Branch control'].settings.inputs.allowedBranches")
}

# Synopsis: Service Connection should not be of the classic azure type
Rule 'Azure.DevOps.ServiceConnections.ClassicAzure' `
-Ref 'ADO-SC-007' `
-Type 'Azure.DevOps.ServiceConnection' `
-Tag @{ release = 'GA'} `
-If { $TargetObject.type -match 'azure' } `
-Level Warning {
# Description 'Service Connection should not be of the classic azure type.'
Reason 'The service connection is of the classic azure type.'
Recommend 'Use the Azure Resource Manager service connection type.'
$Assert.NotIn($TargetObject, "type", "azure")
}

# Synposis: Service Connections of the GitHub type should not use a PAT
Rule 'Azure.DevOps.ServiceConnections.GitHubPAT' `
-Ref 'ADO-SC-008' `
-Type 'Azure.DevOps.ServiceConnection' `
-If { $TargetObject.type -match 'github' } `
-Tag @{ release = 'GA'} `
-Level Warning {
# Description 'Service Connections of the GitHub type should not use a PAT.'
Reason 'The service connection uses a PAT.'
Recommend 'Use a GitHub App instead of a PAT.'
$Assert.NotIn($TargetObject, "authorization.scheme", "Token")
}
Loading

0 comments on commit 8f1d717

Please sign in to comment.