Framework/Configurations/SVT/AzureDevOps/AzureDevOps.ServiceConnection.json

{
  "FeatureName": "ServiceConnection",
  "Reference": "aka.ms/azsktcp/ServiceConnection",
  "IsMaintenanceMode": false,
  "Controls": [
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthN_Use_Cert_Auth_for_SPN",
      "Description": "Azure Active Directory applications, which used in pipeline, must use certificate based authentication",
      "Id": "ServiceConnection110",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckSPNAuthenticationCertificate",
      "Rationale": "Password/shared secret credentials can be easily shared and hence can be easily compromised. Certificate credentials offer better security.",
      "Recommendation": "Remove any password credentials from Azure AD Applications and use certificate credentials instead. Configure certificate details against service connection. Run command Remove-AzureADApplicationPasswordCredential -InformationAction '{ActionPreference}' -InformationVariable '{InformationVariable}' -KeyId '{KeyId}' -ObjectId '{ObjectId}'. Refer: https://docs.microsoft.com/en-us/powershell/module/azuread/remove-azureadapplicationpasswordcredential?view=azureadps-2.0, https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthN",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Dont_Grant_Subscription_Access",
      "Description": "Service Connection should not be provided access at subscription level.",
      "Id": "ServiceConnection120",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckServiceConnectionAccess",
      "Rationale": "Just like AD-based service accounts, SPNs have a single credential and most scenarios that use them cannot support multi-factor authentication. As a result, adding SPNs to a subscription in 'Owners' or 'Contributors' roles is risky.",
      "Recommendation": "Make sure you add SPN at the specific permission scope and role required for your scenario. For example, sometimes 'Contributor' access at 'Resource Group' scope might work. Exact permission will vary based on your use case. If you want to remove the SPN, run command Remove-AzRoleAssignment -ObjectId '{objectId}' -Scope '{scope}' -RoleDefinitionName '{role definition name}'. Run 'Get-Help Remove-AzRoleAssignment -full' for more help.",
      "Tags": [
        "SDL",
        "Automated",
        "TCP",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Justify_Connection_Admin",
      "Description": "Justify all users/groups that have access to the service connection.",
      "Id": "ServiceConnection130",
      "ControlSeverity": "High",
      "Automated": "No",
      "MethodName": "CheckServiceConnectionAdmins",
      "Rationale": "Accounts with admin access can install/manage extensions for Organization. Members with this access without a legitimate business reason increase the risk for Organization. By carefully reviewing and removing accounts that shouldn't be there in the first place, you can avoid attacks if those accounts are compromised.",
      "Recommendation": "Go to Project Settings --> Pipelines --> Service Connections --> Select Service Connection --> Select three dots on top right --> Select Security --> Under user permissions verify connection admin and users",
      "Tags": [
        "SDL",
        "TCP",
        "Manual",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_Audit_Usage_History",
      "Description": "Periodically review usage history of service connection to validate use from legitimate pipelines.",
      "Id": "ServiceConnection140",
      "ControlSeverity": "High",
      "Automated": "No",
      "MethodName": "",
      "Rationale": "Periodic reviews of request history logs ensures that sevice connection been used from legitimate build definitions and avoid major compromise.",
      "Recommendation": "Go to Project Settings --> Pipelines --> Service Connections --> Select Service Connection --> Usage History --> Validate connection is been used from legitimate build/release definitions only",
      "Tags": [
        "SDL",
        "TCP",
        "Manual",
        "Audit"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Dont_Use_Classic_Connections",
      "Description": "Do not use Azure classic service connections to grant access on a subscription.",
      "Id": "ServiceConnection150",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckClassConnections",
      "Rationale": "You should use new ARM/v2 resources as the ARM model provides several security enhancements such as: stronger access control (RBAC), better auditing, ARM-based deployment/governance, access to managed identities, access to key vault for secrets, AAD-based authentication, support for tags and resource groups for easier security management, etc.",
      "Recommendation": "Migrate each v1/ASM-based service connections to a corresponding v2/ARM-based connection. Refer: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/migration-classic-resource-manager-overview",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Disable_Inherited_Permissions",
      "Description": "Do not allow inherited permissions on service connections",
      "Id": "ServiceConnection160",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckRBACInheritPermissions",
      "Rationale": "Service connections represent credentials of various services/repositories accessed by your project's build/release process. You should exercise fine-grained control over who can access them. Removing inherited access ensures that individuals beyond your control do not get access.",
      "Recommendation": "To remediate this, navigate to the service connections settings page for your project -> select your service connection from the list -> click on three dots on top right -> select Security -> In user permissions go to Inheritance -> Turn OFF Inheritance",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Dont_Allow_Global_Groups",
      "Description": "Do not grant global groups access to service connections",
      "Id": "ServiceConnection170",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckGlobalGroupsAddedToServiceConnections",
      "Rationale": "Global groups are maintained at organization and project level and may contain users at a very broad scope (e.g., all users in the organization). Granting elevated permissions to these groups can risk exposure of service connections to unwarranted individuals.",
      "Recommendation": "Refer detailed log files for the list of non compliant service connections. To remediate this follow steps given here: 1. Navigate to the project settings page 2. Select service connection under pipelines category 3. Select your service connection from the list 4. Select Roles from the menu 5. Check for a global security group - (a) global security group added as a User (b) global security group added as an Administrator 6. Remove all global security groups. 7. Save changes and refresh the page to confirm that your changes have been saved. Note: Global security groups are the groups maintained at organization and project level and may contain users at a very broad scope (e.g., all users in the organization). For more information, refer: https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops#secure-a-service-connection",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Dont_Grant_BuildServAcc_Permission",
      "Description": "Do not grant Build Service Account access for connections",
      "Id": "ServiceConnection180",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBuildServiceAccountAccess",
      "Rationale": "Build service account is default identity used as part every build in project. Providing access to this common service account will expose connection details to all build definition under project.",
      "Recommendation": "To remediate this, navigate to the service connections settings page for your project -> select your service connection from the list -> select three dots on top right -> select security -> remove 'Project Collection Build Service Accounts' access from user permission.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_Dont_Grant_All_Pipelines_Access",
      "Description": "Do not make service connections accessible to all pipelines.",
      "Id": "ServiceConnection190",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckServiceConnectionBuildAccess",
      "Rationale": "To support security of the pipeline operations, connections must not be granted access to all pipelines. This is in keeping with the principle of least privilege because a vulnerability in components used by one pipeline can be leveraged by an attacker to attack other pipelines having access to critical resources.",
      "Recommendation": "To remediate this, navigate to the service connections settings page for your project -> select your service connection from the list -> click Edit -> uncheck 'Grant access permission to all pipelines'.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_AuthZ_PAT_Or_Auth",
      "Description": "Justify GitHub service connections are authenticated with full scope GitHub PATs instead of the OAuth flow.",
      "Id": "ServiceConnection200",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckServiceConnectionForPATOrAuth",
      "Rationale": "Full scope PAT is equivalent to full account compromise. The OAuth flow creates a token that only allows source code and webhook read/write access on GitHub. The impact of losing control of a scoped OAuth token is far lower.",
      "Recommendation": "Go to Project Settings --> Service Connections --> Select Service Connection --> Select Edit --> Verify connection authentication type.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_SI_Review_Inactive_Connection",
      "Description": "Inactive service connection must be removed if no more required.",
      "Id": "ServiceConnection210",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckInactiveConnection",
      "Rationale": "Each additional service connection being used by pipelines to access repositories increases the attack surface. To minimize this risk ensure that only active and legitimate service connections are present in organization.",
      "Recommendation": "To remove inactive service connection, follow the steps given here: 1.Navigate to the service connection settings. 2. Select service connection. 3. Select three dots (present at right top). 4. Click on Delete.",
      "Tags": [
        "SDL",
        "Best Practice",
        "Automated",
        "SI"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_SI_Dont_Allow_Project_Sharing",
      "Description": "Service connections should not be shared across multiple projects.",
      "Id": "ServiceConnection220",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckCrossProjectSharing",
      "Rationale": "If a service connection is shared across multiple multiple projects, then a vulnerability in components used by one project can be leveraged by an attacker to attack other projects. This is also in keeping with the principle of least privilege.",
      "Recommendation": "To remediate this, navigate to the service connections settings page for your project -> select your service connection from the list -> click Security -> Under 'Project Permissions', remove projects that service connection no more requires access to.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    },
    {
      "ControlID": "AzureDevOps_ServiceConnection_SI_Review_Pipeline_Sharing",
      "Description": "Service connections should not be shared across multiple pieplines.",
      "Id": "ServiceConnection230",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckCrossPipelineSharing",
      "Rationale": "If a service connection is shared across multiple multiple pipelines, then a vulnerability in components used by one pipeline can be leveraged by an attacker to attack other pipelines having access to critical resources. This is also in keeping with the principle of least privilege.",
      "Recommendation": "To remediate this, navigate to the service connections settings page for your project -> select your service connection from the list -> click Security -> Under 'Pipeline Permissions', remove pipelines that service connection no more requires access to.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "RBAC"
      ],
      "Enabled": true
    }
 
  ]
}