Framework/Configurations/SVT/ADO/ADO.ServiceConnection.json

{
  "FeatureName": "ServiceConnection",
  "Reference": "aka.ms/azsktcp/ServiceConnection",
  "IsMaintenanceMode": false,
  "Controls": [
    {
      "ControlID": "ADO_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",
        "Azure",
        "AzureRM"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Use_Least_Privilege_Access",
      "Description": "Azure service connection should not be provided access at subscription/management group scope.",
      "Id": "ServiceConnection120",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckServiceConnectionAccess",
      "Rationale": "SPN-based logins do not have MFA protection. It is important to restrict the access granted to Azure service connections only to specific resource/resource group as needed. This can contain the extent of damage in case of compromise.",
      "Recommendation": "1. Navigate to the service connections settings page for your project --> 2. Select your service connection from the list --> 3. Reduce the service connection scope to the appropriate resource group(s) and save. (If a service connection is scoped at Management group or subscription level and is not in use, then delete it using Remove-AzRoleAssignment or equivalent steps in the portal on the Azure side.)",
      "Tags": [
        "SDL",
        "Automated",
        "TCP",
        "AuthZ",
        "AzureRM"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_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": "ADO_ServiceConnection_AuthZ_Dont_Use_Classic_Connections",
      "Description": "Do not use classic Azure service connections to access a subscription.",
      "Id": "ServiceConnection150",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckClassicConnection",
      "Rationale": "You should use Azure resource Manager type service connection 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": "Delete the Azure Classic service connection and create a new service connection of type 'Azure resource Manager'(i.e., ARM based) scoped to a resource/resource group in subscription.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "Azure",
        "MSW"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Disable_Inherited_Permissions",
      "Description": "Do not allow inherited permissions on service connections.",
      "Id": "ServiceConnection160",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckInheritedPermissions",
      "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"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_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"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Dont_Grant_BuildSvcAcct_Permission",
      "Description": "Do not grant Build Service Account direct access to service connections",
      "Id": "ServiceConnection180",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBuildServiceAccountAccess",
      "Rationale": "Build service account is default identity used as part every build in project. Providing direct access to this common service account will expose connection details to all build definitions in the project.",
      "Recommendation": "1. Navigate to the service connections settings page for your project --> 2. Select your service connection from the list --> 3. Select three dots on top right -> 4. Select security --> 5. Remove 'Project Collection Build Service Accounts/[Project] Build Service Account' access from user permission.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "MSW",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Dont_Grant_All_Pipelines_Access",
      "Description": "Do not make service connection accessible to all (YAML) 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 YAML 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. Note that this does not prevent classic pipelines from accessing the service connection as it depends on the permissions granted to pipeline user.",
      "Recommendation": "1. Navigate to the service connections settings page for your project --> 2. Select your service connection from the list --> 3. Click on three dots --> 4. Click Security --> 5. Under 'Pipeline Permissions', click 'Restrict Permission' to avoid granting access to all YAML pipelines and add only those YAML pipelines that need explicit access on service connection. For classic pipelines, review user permissions on the service connection.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "MSW",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthN_Use_Secure_Auth_Method",
      "Description": "Service connections should use strong authentication methods.",
      "Id": "ServiceConnection200",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckSecureAuthN",
      "Rationale": "Weaker authentication methods such as basic authentication can be easily compromised. Stronger authentication methods (certificate, token etc.) offer better security.",
      "Recommendation": "Go to Project Settings --> Service Connections --> Select Service Connection --> Select Edit --> Use the recommended (stronger) authentication method as mentioned in the detailed scan logs.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthN"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_DP_Review_Inactive_Connection",
      "Description": "Inactive service connection must be removed if no more required.",
      "Id": "ServiceConnection210",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckInactiveConnection",
      "Rationale": "Each inactive service connection increases the window of attack for a malicious user who can use a service connection to access an underlying target resource such as repositories, storage account, azure subscriptions or a CI environment. To minimize this risk ensure that inactive service connections are proactively deleted.",
      "Recommendation": "To remove inactive service connection: 1. Navigate to the service connection settings using resource link --> 2. Click on the three dots (top right) --> 3. Click on Delete.",
      "Tags": [
        "SDL",
        "Best Practice",
        "Automated",
        "DP",
        "MSW"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_SI_Dont_Share_Across_Projects",
      "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 projects, then a user in another project can access data/components that they were otherwise not supposed to access. So, in keeping with principle of least privilege, it is best to limit access to the service connection to your (current) project.",
      "Recommendation": "1. Navigate to the project settings --> 2. Go to service connections, select service connection -> 3. Click Security -> 4. Under 'Project Permissions', remove projects that service connection no more requires access to.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_SI_Review_Pipeline_Sharing",
      "Description": "Ensure that service connection access is granted only to (YAML) pipelines that require it.",
      "Id": "ServiceConnection230",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckCrossPipelineSharing",
      "Rationale": "If a service connection is shared across 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 YAML pipelines that service connection no more requires access to or click 'Restrict Permission' to avoid granting access to all YAML pipelines. Note that this does not prevent classic pipelines from accessing the service connection as it depends on the permissions granted to pipeline user.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Restrict_Broader_Group_Access",
      "Description": "Broader groups (contributors, project valid users, etc.) should not have excessive permissions on service connection.",
      "Id": "ServiceConnection240",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBroaderGroupAccess",
      "Rationale": "If broader groups (e.g., Contributors) have excessive permissions (Admin/User) on service connection, then confidentiality/integrity of a pipeline using the service connection can be compromised by a malicious user. Removing access/privileges that are not required minimizes exposure of the resources in case of user account/service connection compromise.",
      "Recommendation": "1. Go to Project Settings --> 2. Service connections --> 3. Select your service connection --> 4. Select Security --> 5. User Permissions --> 6. Ensure broader groups have read-only access. Refer to detailed scan log (ServiceConnection.LOG) for broader group list.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "MSW",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_Cannot_Use_Disallowed_Environment",
      "Description": "Azure service connections to certain environments are not permitted from this org.",
      "Id": "ServiceConnection250",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckRestricedCloudEnvironment",
      "Rationale": "Service connection should not connect to restricted cloud environments to align with data sovereignty requirements and ensure their data and workloads stays in allowed cloud environments.",
      "Recommendation": "(1) Review the environment of your service connection: Go to Project Settings --> Pipelines --> Service connections --> Select your service connection --> Click Edit (2) Remove the service connection if it is to disallowed environments (per details available in detailed control scan logs).",
      "Tags": [
        "SDL",
        "TCP",
        "Automated"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_AuthZ_Enable_Branch_Control",
      "Description": "Allow service connections to be accessed only by select branches.",
      "Id": "ServiceConnection260",
      "ControlSeverity": "Medium",
      "Automated": "Yes",
      "MethodName": "CheckBranchControlForSvcConn",
      "Rationale": "Once a service connection is made accessible to a YAML pipeline, malicious users with 'create branch' permissions on the repository will be able to access the service connection by queueing the pipeline from the branch they select even if they do not have access to the service connection. To prevent this ensure that the service connection can be accessed only from select branches (eg. 'main').",
      "Recommendation": "1. Navigate to the service connection --> 2. Click on 'Approvals and Checks' --> Create a branch control --> Provide the branches from which you would like the service connection to be accessed from. For additional protection, enable 'Verify branch protection'.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_ServiceConnection_DP_Use_Template_From_Protected_Branch",
      "Description": "Allow service connections to be accessed by templates only from protected branches.",
      "Id": "ServiceConnection270",
      "ControlSeverity": "Medium",
      "Automated": "Yes",
      "MethodName": "CheckTemplateBranchForSvcConn",
      "Rationale": "If malicious users have 'contribute' permissions to the repository containing the template required to access the service connection, they can tamper the template itself and misuse the service connection. To prevent this, enable branch protection policies on the branch which contains the template required to access this resource.",
      "Recommendation": "1. Navigate to the service connection --> 2. Click on 'Approvals and Checks' --> Create a branch control --> Provide the branches from which you would like the service connection to be accessed from. For additional protection, enable 'Verify branch protection'.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "DP"
      ],
      "Enabled": true
     },
    {
      "ControlID": "ADO_ServiceConnection_Dont_Grant_Broader_Group_Access_As_Approvers",
      "Description": "Broader groups (contributors, project valid users, etc.) should not be added as approvers on service connection.",
      "Id": "ServiceConnection280",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBroaderGroupApproversOnSvcConn",
      "Rationale": " Any user/ group can be added as an approver to the service connection, which gives users the permission to approve any run of pipelines accessing the resource even if they do not have access to the service connection. To prevent illegitimate consumption and approval of the resource, ensure that broader groups are not added as approvers.",
      "Recommendation": "1. Navigate to the service connection --> 2. Click on 'Approvals and Checks' --> Remove Broader groups from Approvals. Refer to detailed scan log (ServiceConnection.LOG) for broader group list.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    }
  ]
}