Framework/Configurations/SVT/ADO/ADO.AgentPool.json

{
  "FeatureName": "AgentPool",
  "Reference": "aka.ms/azsktcp/AgentPool",
  "IsMaintenanceMode": false,
  "Controls": [
    {
      "ControlID": "ADO_AgentPool_SI_Apply_Security_Patches",
      "Description": "Non-hosted agent virtual machine must have all the required security patches installed.",
      "Id": "AgentPool120",
      "ControlSeverity": "High",
      "Automated": "No",
      "MethodName": "",
      "Rationale": "Unpatched VMs are easy targets for compromise from various malware/trojan attacks that exploit known vulnerabilities in operating systems and related software.",
      "Recommendation": "Refer: https://docs.microsoft.com/en-us/azure/automation/automation-tutorial-update-management",
      "Tags": [
        "SDL",
        "TCP",
        "Manual",
        "SI"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_SI_Lockdown_Machine",
      "Description": "Use a security hardened, locked down OS image for self-hosted VMs in agent pool.",
      "Id": "AgentPool130",
      "ControlSeverity": "Medium",
      "Automated": "No",
      "MethodName": "",
      "Rationale": "The connector machine is serving as a 'gateway' into the corporate environment allowing internet based client endpoints access to enterprise data. Using a locked-down, secure baseline configuration ensures that this machine does not get leveraged as an entry point to attack the applications/corporate network.",
      "Recommendation": "Use a locked down OS configuration. Ensure that the system is always fully patched, has real-time malware protection enabled, OS firewall and disk encryption turned on, etc. Also, monitor this VM just like you'd monitor a high-value asset.",
      "Tags": [
        "SDL",
        "TCP",
        "Manual",
        "SI"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_AuthZ_Disable_Inherited_Permissions",
      "Description": "Do not allow inherited permission on agent pool.",
      "Id": "AgentPool140",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckInheritedPermissions",
      "Rationale": "Disabling inherit permissions lets you finely control access to various operations at the agent level for different stakeholders. This ensures that you follow the principle of least privilege and provide access only to the persons that require it.",
      "Recommendation": "To disable inheritance follow the steps given here: 1.Navigate to the agent pool. 2. Select Security. 3. Under User Permissions, add the service lead & service owner as users with allow permissions for each permission line item. 4. Select Off under Inheritance. 5. Add users/groups to agent and provide only required access. As best practice, all teams/groups must be granted minimum required permissions on agent pool.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_AuthZ_Dont_Enable_Auto_Provisioning",
      "Description": "Do not enable auto-provisioning for agent pools.",
      "Id": "AgentPool150",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckOrgAgtAutoProvisioning",
      "Rationale": "By enabling auto-provisioning the organization agent pool is imported in all your new team projects and is accessible there immediately. Therefore, a vulnerability in components used by one project can be leveraged by an attacker to attack other projects.",
      "Recommendation": "1.Navigate to the Organization settings. --> 2. Select agent pool. --> 3. Select Settings. --> 4. Change the settings for 'Auto-provisioning this agent pools in new projects'",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_AuthZ_Dont_Grant_All_Pipelines_Access",
      "Description": "Do not make agent pool accessible to all (YAML) pipelines in the project.",
      "Id": "AgentPool160",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckPrjAllPipelineAccess",
      "Rationale": "To support security of the pipeline operations, agent pools 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 agent pool as it depends on the permissions granted to pipeline user.",
      "Recommendation": "1. Go to 'Project settings' --> 2. 'Agent pools' --> 3. Select the agent pool --> 4. Security --> 5. Disable 'Grant access permission to all pipeline'. For classic pipelines, review the user permissions carefully.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "MSW",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_DP_Review_Inactive_Pool",
      "Description": "Inactive agent pools must be removed if no more required.",
      "Id": "AgentPool170",
      "ControlSeverity": "Medium",
      "Automated": "Yes",
      "MethodName": "CheckInactiveAgentPool",
      "Rationale": "Agent pools may contain potentially sensitive information (such as code, secrets, pre-release information and logs) from previously run pipelines. Thus each inactive agent pool can increase the exposure of such important information to a malicious user. To minimize this risk ensure that inactive agent pools are proactively deleted.",
      "Recommendation": "To remove inactive agent pool: 1. Navigate to the agent pools from the project settings --> 2. Locate the inactive agent pool --> 3. Click on the 'Delete' icon",
      "Tags": [
        "SDL",
        "TCP",
        "Manual",
        "DP"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_DP_Enable_Auto_Update",
      "Description": "Enable auto-update of agents in the pool.",
      "Id": "AgentPool180",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckAutoUpdate",
      "Rationale": "Unpatched agents are easy targets for compromise from various malware/trojan attacks that exploit known vulnerabilities in operating systems and related software. Being on the latest OS version significantly reduces risks from security design issues and security bugs that may be present in older versions.",
      "Recommendation": "To enable auto-update settings: 1.Navigate to the Organization settings. 2. Open Agent pools. 3. Select Settings. 4. Enable 'Allow agents in this pool to automatically update'.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "DP",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_DP_No_Secrets_In_Capabilities",
      "Description": "Secrets and keys must not be stored as plain text in agent capabilities.",
      "Id": "AgentPool190",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckCredInEnvironmentVariables",
      "Rationale": "Keeping secrets such as connection strings, passwords, keys, etc. as a plain text in agent capabilities can expose the credentials to a wider audience and lead to credential theft. Any user who can deploy a pipeline to run on such agents can access these secrets and compromise the security of resources involving the secrets.",
      "Recommendation": "1. Go to agent pool --> 2. Agents --> 3. Select each agent --> 4. Capabilities --> 5. Remove all user defined capabilities that contain secret.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "DP",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_AuthZ_Restrict_Broader_Group_Access",
      "Description": "Broader groups (contributors, project valid users, etc.) should not have excessive permissions on agent pool.",
      "Id": "AgentPool200",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBroaderGroupAccess",
      "Rationale": "If broader groups (e.g., Contributors) have excessive permissions (Admin/User) on an agent pool, integrity of your agent pool can be compromised by a malicious user. Removing access/privileges that are not required minimizes exposure of the resources in case of user account/agent pool compromise.",
      "Recommendation": "1. Go to Project Settings --> 2. Pipelines --> 3. Agent pools --> 4. Select your agent pool --> 5. Select Security --> 6. Ensure broader groups have read-only access. Refer to detailed scan log (Agentpool.LOG) for broader group list.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ",
        "MSW",
        "AutomatedFix"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_Dont_Grant_Broader_Group_Access_As_Approvers",
      "Description": "Broader groups (contributors, project valid users, etc.) should not be added as approvers on agent pool.",
      "Id": "AgentPool210",
      "ControlSeverity": "High",
      "Automated": "Yes",
      "MethodName": "CheckBroaderGroupApproversOnAgentPool",
      "Rationale": "Any user/group can be added as an approver to the agent pool, which gives user/group the permission to approve any run of pipelines accessing the resource even if they do not have access to the agent pool. To prevent illegitimate consumption and approval of the resource, ensure that broader groups are not added as approvers.",
      "Recommendation": "1. Go to Project Settings --> 2. Pipelines --> 3. Agent pools --> 4. Select your agent pool --> 5. Select Security --> 6. Click on 'Approvals and Checks' --> Remove Broader groups from Approvals. Refer to detailed scan log (*AgentPool.LOG*) for broader group list.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_AuthZ_Enable_Branch_Control",
      "Description": "Allow agent pools to be accessed only by select branches.",
      "Id": "AgentPool220",
      "ControlSeverity": "Medium",
      "Automated": "Yes",
      "MethodName": "CheckBranchControlForAgentPool",
      "Rationale": "Once an agent pool is made accessible to a YAML pipeline, malicious users with 'create branch' permissions on the repository will be able to access the agent pool by queueing the pipeline from the branch they select even if they do not have access to the agent pool. To prevent this ensure that the agent pool can be accessed only from select branches (e.g., 'main').",
      "Recommendation": "1. Go to Project Settings --> 2. Pipelines --> 3. Agent pools --> 4. Select your agent pool --> 5. Select Approvals and Checks --> 6. Click on 'Branch Control' --> Create a branch control --> Provide the branches from which you would like the agent pool to be accessed from. For additional protection, enable 'Verify branch protection'.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "AuthZ"
      ],
      "Enabled": true
    },
    {
      "ControlID": "ADO_AgentPool_DP_Use_Template_From_Protected_Branch",
      "Description": "Allow agent pools to be accessed by templates only from protected branches.",
      "Id": "AgentPool230",
      "ControlSeverity": "Medium",
      "Automated": "Yes",
      "MethodName": "CheckTemplateBranchForAgentPool",
      "Rationale": "If malicious users have 'contribute' permissions to the repository containing the template required to access the agent pool, 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. Go to Project Settings --> 2. Pipelines --> 3. Agent pools --> 4. Select your agent pool --> 5. Select Approvals and checks --> 6. Click on 'See All' --> 7. Select Required Template --> 8. Click on 'Next' --> 9.Add required YAML template --> Provide the repository, ref and the path to required YAML template.",
      "Tags": [
        "SDL",
        "TCP",
        "Automated",
        "DP"
      ],
      "Enabled": true
    }
  ]
}