From bb6158683e1a259e283acd72191a859d9358831b Mon Sep 17 00:00:00 2001 From: RoderickB <13252390+webtonize@users.noreply.github.com> Date: Sat, 21 Oct 2023 14:31:11 +0200 Subject: [PATCH] 47 parameter for token access level (#51) * Feature: Fix #47 - Token scopes * Update README examples * Bump version --- .github/workflows/module-ci.yml | 2 + .gitignore | 2 +- README.md | 24 +- docs/token-permissions.md | 158 ++++ .../Functions/Common.ps1 | 10 +- .../Functions/DevOps.Pipelines.Core.ps1 | 147 ++-- .../DevOps.Pipelines.Environments.ps1 | 155 ++-- .../Functions/DevOps.Pipelines.Releases.ps1 | 126 ++- .../Functions/DevOps.Pipelines.Settings.ps1 | 32 +- .../Functions/DevOps.Repos.ps1 | 237 ++++-- .../Functions/DevOps.ServiceConnections.ps1 | 51 +- .../Functions/DevOps.Tasks.VariableGroups.ps1 | 49 +- .../PSRule.Rules.AzureDevOps.psd1 | 2 +- .../PSRule.Rules.AzureDevOps.psm1 | 50 +- ...Ops.Pipelines.Core.InheritedPermissions.md | 2 + ...evOps.Pipelines.Core.NoPlainTextSecrets.md | 2 + ...DevOps.Pipelines.Core.UseYamlDefinition.md | 2 + ...vOps.Pipelines.Environments.Description.md | 2 + ...ines.Environments.ProductionBranchLimit.md | 2 + ....Environments.ProductionCheckProtection.md | 2 + ...es.Environments.ProductionHumanApproval.md | 2 + ....PipelineYaml.AgentPoolVersionNotLatest.md | 2 + ....Pipelines.PipelineYaml.StepDisplayName.md | 2 + ...eleases.Definition.InheritedPermissions.md | 2 + ....Releases.Definition.NoPlainTextSecrets.md | 2 + ....Releases.Definition.ProductionApproval.md | 2 + ...elines.Releases.Definition.SelfApproval.md | 2 + ...nes.Settings.LimitJobAuthorizationScope.md | 2 + ...obAuthorizationScopeForReleasePipelines.md | 2 + ...itJobAuthorizationScopeForYamlPipelines.md | 2 + ...s.Settings.LimitSetVariablesAtQueueTime.md | 2 + ...gs.RequireCommentForPullRequestFromFork.md | 2 + ...s.RestrictSecretsForPullRequestFromFork.md | 2 + ...nes.Settings.SanitizeShellTaskArguments.md | 2 + ...Ops.Repos.BranchPolicyAllowSelfApproval.md | 2 + ...Ops.Repos.BranchPolicyCommentResolution.md | 2 + ...epos.BranchPolicyEnforceLinkedWorkItems.md | 2 + ...zure.DevOps.Repos.BranchPolicyIsEnabled.md | 2 + ....DevOps.Repos.BranchPolicyMergeStrategy.md | 2 + ...vOps.Repos.BranchPolicyMinimumReviewers.md | 1 + ...e.DevOps.Repos.BranchPolicyRequireBuild.md | 2 + ...ure.DevOps.Repos.BranchPolicyResetVotes.md | 2 + ...Repos.GitHubAdvancedSecurityBlockPushes.md | 2 + ...Ops.Repos.GitHubAdvancedSecurityEnabled.md | 2 + .../en/Azure.DevOps.Repos.HasBranchPolicy.md | 2 + ...Azure.DevOps.Repos.InheritedPermissions.md | 2 + .../en/Azure.DevOps.Repos.License.md | 2 + .../en/Azure.DevOps.Repos.Readme.md | 2 + ....DevOps.ServiceConnections.ClassicAzure.md | 2 + ...e.DevOps.ServiceConnections.Description.md | 2 + ...ure.DevOps.ServiceConnections.GitHubPAT.md | 2 + ...erviceConnections.ProductionBranchLimit.md | 2 + ...ceConnections.ProductionCheckProtection.md | 2 + ...viceConnections.ProductionHumanApproval.md | 2 + .../Azure.DevOps.ServiceConnections.Scope.md | 2 + ...eConnections.WorkloadIdentityFederation.md | 2 + ....DevOps.Tasks.VariableGroup.Description.md | 2 + ...Tasks.VariableGroup.NoKeyVaultNoSecrets.md | 2 + ....Tasks.VariableGroup.NoPlainTextSecrets.md | 2 + ...Ops.Pipelines.Core.InheritedPermissions.md | 2 + ...evOps.Pipelines.Core.NoPlainTextSecrets.md | 2 + ...DevOps.Pipelines.Core.UseYamlDefinition.md | 2 + ...vOps.Pipelines.Environments.Description.md | 2 + ...ines.Environments.ProductionBranchLimit.md | 2 + ....Environments.ProductionCheckProtection.md | 2 + ...es.Environments.ProductionHumanApproval.md | 2 + ....PipelineYaml.AgentPoolVersionNotLatest.md | 2 + ....Pipelines.PipelineYaml.StepDisplayName.md | 2 + ...eleases.Definition.InheritedPermissions.md | 2 + ....Releases.Definition.NoPlainTextSecrets.md | 2 + ....Releases.Definition.ProductionApproval.md | 2 + ...elines.Releases.Definition.SelfApproval.md | 2 + ...nes.Settings.LimitJobAuthorizationScope.md | 2 + ...obAuthorizationScopeForReleasePipelines.md | 2 + ...itJobAuthorizationScopeForYamlPipelines.md | 2 + ...s.Settings.LimitSetVariablesAtQueueTime.md | 2 + ...gs.RequireCommentForPullRequestFromFork.md | 2 + ...s.RestrictSecretsForPullRequestFromFork.md | 2 + ...nes.Settings.SanitizeShellTaskArguments.md | 2 + ...Ops.Repos.BranchPolicyAllowSelfApproval.md | 2 + ...Ops.Repos.BranchPolicyCommentResolution.md | 2 + ...epos.BranchPolicyEnforceLinkedWorkItems.md | 2 + ...zure.DevOps.Repos.BranchPolicyIsEnabled.md | 2 + ....DevOps.Repos.BranchPolicyMergeStrategy.md | 2 + ...vOps.Repos.BranchPolicyMinimumReviewers.md | 2 + ...e.DevOps.Repos.BranchPolicyRequireBuild.md | 2 + ...ure.DevOps.Repos.BranchPolicyResetVotes.md | 2 + ...Repos.GitHubAdvancedSecurityBlockPushes.md | 2 + ...Ops.Repos.GitHubAdvancedSecurityEnabled.md | 1 + .../nl/Azure.DevOps.Repos.HasBranchPolicy.md | 2 + ...Azure.DevOps.Repos.InheritedPermissions.md | 2 + .../nl/Azure.DevOps.Repos.License.md | 2 + .../nl/Azure.DevOps.Repos.Readme.md | 2 + ....DevOps.ServiceConnections.ClassicAzure.md | 2 + ...e.DevOps.ServiceConnections.Description.md | 2 + ...ure.DevOps.ServiceConnections.GitHubPAT.md | 2 + ...erviceConnections.ProductionBranchLimit.md | 2 + ...ceConnections.ProductionCheckProtection.md | 2 + ...viceConnections.ProductionHumanApproval.md | 2 + .../Azure.DevOps.ServiceConnections.Scope.md | 2 + ...eConnections.WorkloadIdentityFederation.md | 2 + ....DevOps.Tasks.VariableGroup.Description.md | 2 + ...Tasks.VariableGroup.NoKeyVaultNoSecrets.md | 2 + ....Tasks.VariableGroup.NoPlainTextSecrets.md | 2 + .../rules/AzureDevOps.Pipelines.Core.Rule.ps1 | 1 + .../AzureDevOps.Pipelines.Releases.Rule.ps1 | 1 + .../rules/AzureDevOps.Repos.Rule.ps1 | 3 + tests/PSRule.Rules.AzureDevOps.Tests.ps1 | 189 ++++- tests/Rules.Tests.ps1 | 742 ++++++++++++++++++ 109 files changed, 1857 insertions(+), 302 deletions(-) create mode 100644 docs/token-permissions.md diff --git a/.github/workflows/module-ci.yml b/.github/workflows/module-ci.yml index 7883783..c4ab759 100644 --- a/.github/workflows/module-ci.yml +++ b/.github/workflows/module-ci.yml @@ -65,6 +65,8 @@ jobs: ADO_PAT: ${{ secrets.ADO_PAT }} ADO_ORGANIZATION: ${{ secrets.ADO_ORGANIZATION }} ADO_PROJECT: ${{ secrets.ADO_PROJECT }} + ADO_PAT_FINEGRAINED: ${{ secrets.ADO_PAT_FINEGRAINED }} + ADO_PAT_READONLY: ${{ secrets.ADO_PAT_READONLY }} - name: Upload Test Results uses: EnricoMi/publish-unit-test-result-action@v2.9.0 diff --git a/.gitignore b/.gitignore index 4a0c915..9095e7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -tests/out +tests/out* coverage.xml myenv.ps1 \ No newline at end of file diff --git a/README.md b/README.md index 12264f3..fe5bf4a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,15 @@ Install-Module -Name PSRule.Rules.AzureDevOps -Scope CurrentUser Once you have both modules installed, you can run an export of your Azure DevOps project and run the rules on the exported data. The `-PAT` value needs to be an Azure DevOps Personal Access Token -with sufficient permissions to read the project data. +with sufficient permissions to read the project data. The default +expects a PAT with full access permissions. Alternately, you can +use a PAT with only read permissions or fine-grained permissions +with the `-TokenType` parameter. The fine-grained permissions expect +read access to all scopes and read & manage for scope that do not +have read-only access. Documentation on how to create the PATs can +be found in the [docs/token-permissions.md](docs/token-permissions.md). + +#### Example: Run with full access token ```powershell Export-AzDevOpsRuleData ` @@ -56,6 +64,20 @@ Assert-PSRule ` -Module PSRule.Rules.AzureDevOps ``` +#### Example: Run with read-only access token + +```powershell +Export-AzDevOpsRuleData ` + -Organization "MyOrg" ` + -Project "MyProject" ` + -PAT $MyPAT ` + -OutputPath "C:\Temp\MyProject" ` + -TokenType ReadOnly +Assert-PSRule ` + -InputPath "C:\Temp\MyProject\" ` + -Module PSRule.Rules.AzureDevOps +``` + ![Screenshot of version 0.0.9 run](assets/media/run-0.0.9.png) ### Organization level export diff --git a/docs/token-permissions.md b/docs/token-permissions.md new file mode 100644 index 0000000..8f912f5 --- /dev/null +++ b/docs/token-permissions.md @@ -0,0 +1,158 @@ +# PSRule.Rules.AzureDevOps Token Permissions + +## Details on how to configure token permissions + +PSRule.Rules.AzureDevOps requires a personal access token with the appropriate +permissions to export data from Azure DevOps. When running PSRule.Rules.AzureDevOps +you can choose 3 different token types: + +- **FullAccess**: Allows for full access to Azure DevOps, use with caution +- **FineGrained**: Allows for fine-grained access to Azure DevOps, this is the recommended token type +- **ReadOnly**: Allows for read-only access to Azure DevOps + +### FullAccess TokenType + +The `FullAccess` token type is the most permissive and allows for maximum rule +coverage. This token type is recommended for use with PSRule.Rules.AzureDevOps +but should be used with caution. Check your organization's security policies +before using this token type. + +The FullAccess token type can be created in Azure DevOps by following these +steps: + +1. Navigate to your Azure DevOps organization +2. Select the **User Settings** option from the top right menu +3. Select the **Personal access tokens** option from the menu +4. Click the **New Token** button +5. Enter a name for the token +6. Select the **Full access** scope +7. Click the **Create** button +8. Copy the token value and store it in a secure location +9. Use the token value in your pipeline + +### FineGrained TokenType + +The `FineGrained` token type is the recommended token type for use with +PSRule.Rules.AzureDevOps. This token type allows for fine-grained access to +Azure DevOps and is the most secure token type that allows for near-maximum +rule coverage while still offering a detailed overview of the required permissions. + +The FineGrained token type can be created in Azure DevOps by following these +steps: + +1. Navigate to your Azure DevOps organization +2. Select the **User Settings** option from the top right menu +3. Select the **Personal access tokens** option from the menu +4. Click the **New Token** button +5. Enter a name for the token +6. Select the **Custom defined** scope +7. Select `Read` for all scopes that have a `Read` option +8. Select `Read & Manage` for all scopes that have a `Read & Manage` option +9. Do not select any other scopes +10. Click the **Create** button +11. Copy the token value and store it in a secure location +12. Use the token value in your pipeline + +### ReadOnly TokenType + +The `ReadOnly` token type is the most restrictive and allows for read-only access +to Azure DevOps. This token type is recommended for use with PSRule.Rules.AzureDevOps +when your security policies do not allow for the use of the `FullAccess` or `FineGrained` +token types. + +The ReadOnly token type can be created in Azure DevOps by following these +steps: + +1. Navigate to your Azure DevOps organization +2. Select the **User Settings** option from the top right menu +3. Select the **Personal access tokens** option from the menu +4. Click the **New Token** button +5. Enter a name for the token +6. Select the **Custom defined** scope +7. Select `Read` for all scopes that have a `Read` option +8. Do not select any other scopes +9. Click the **Create** button +10. Copy the token value and store it in a secure location +11. Use the token value in your pipeline + +## Token Scopes for module functions + +The following table lists the token scopes that are required for each command. + +| Rule Function | API(s) | Version | Method | Scope(s) | PAT Category | PAT Name | +|-------------------------------------------|------------------------------------------|---------------|--------|-------------------------|---------------------|-----------------| +| Get-AzDevOpsProjects | projects | 6.0 | GET | vso.profile | User Profile | Read | +| | | | | vso.project | Project and Team | Read | +| Get-AzDevOpsPipelines | pipelines | 6.0-preview.1 | GET | vso.build | Build | Read | +| | pipelines/{pipelineid} | 6.0-preview.1 | GET | vso.build | Build | Read | +| Get-AzDevOpsPipelineAcls | accesscontrollists/{securityid} | 6.0 | GET | vso.security_manage | Security | Manage | +| Get-AzDevOpsPipelineYaml | pipelines/{pipelineid}/runs | 5.1-preview | POST | vso.build | Build | Read | +| | pipelines/{pipelineid} | 7.1-preview.1 | GET | vso.build | Build | Read | +| | git/repositories/{repositoryid}/items | 6.0 | GET | vso.code | Code | Read | +| Get-AzDevOpsEnvironments | pipelines/environments | 6.0-preview.1 | GET | vso.environment_manage | Agent Pools | Read and Manage | +| | | | | vso.build | Build | Read | +| | pipelines/checks/configurations | 7.2-preview.1 | GET | vso.build | Build | Read | +| Get-AzDevOpsReleaseDefinitions | release/definitions | 7.2-preview.4 | GET | vso.release | Release | Read | +| Get-AzDevOpsReleaseDefinitionAcls | accesscontrollists/{securityid} | 6.0 | GET | vso.security_manage | Security | Manage | +| Get-AzDevOpsPipelinesSettings | build/generalsettings | 7.1-preview.1 | GET | vso.project | Build | Read | +| Get-AzDevOpsRepos | git/repositories | 6.0 | GET | vso.code | Code | Read | +| Get-AzDevOpsBranchPolicy | policy/configurations | 6.0 | GET | vso.code | Code | Read | +| Get-AzDevOpsRepositoryPipelinePermissions | pipelines/pipelinePermissions/repository | | GET | vso.build | Build | Read | +| Get-AzDevOpsRepositoryAcls | accesscontrollists/{securityid} | 6.0 | GET | vso.security_manage | Security | Manage | +| Test-AzDevOpsFileExists | git/repositories/{repositoryid}/items | 6.0 | GET | vso.code | Code | Read | +| Get-AzDevOpsRepositoryGhas | Contribution/HierarchyQuery | 5.0-preview.1 | POST | tbc | tbc | FullACcess | +| Get-AzDevOpsArmServiceConnections | serviceendpoint/endpoints | 6.0-preview.4 | GET | vso.serviceendpoint | Service Connections | Read | +| Get-AzDevOpsArmServiceConnectionChecks | bipelines/checks/configurations | 7.2-preview.1 | GET | vso.build | Build | Read | +| Get-AzDevOpsVariableGroups | distributed task/variablegroups | 7.2-preview.2 | GET | vso.variablegroups_read | Variable Groups | Read | + +## Token Scopes for rules + +The following table lists the token scopes that are required for each rule. + +| Rule | Minimum TokenType | +|------|-------------------| +|[Azure.DevOps.Pipelines.Core.UseYamlDefinition](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Core.InheritedPermissions](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md)|FineGrained| +|[Azure.DevOps.Pipelines.Core.NoPlainTextSecrets](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md)|ReadOnly| +|[Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md)|ReadOnly| +|[Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Environments.Description](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.Description.md)|FineGrained| +|[Azure.DevOps.Pipelines.Environments.ProductionBranchLimit](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md)|FineGrained| +|[Azure.DevOps.Pipelines.Environments.ProductionCheckProtection](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md)|FineGrained| +|[Azure.DevOps.Pipelines.Environments.ProductionHumanApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md)|FineGrained| +|[Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Releases.Definition.SelfApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md)|FineGrained| +|[Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md)|ReadOnly| +|[Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyAllowSelfApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyCommentResolution](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyIsEnabled](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyMergeStrategy](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyMinimumReviewers](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyRequireBuild](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md)|ReadOnly| +|[Azure.DevOps.Repos.BranchPolicyResetVotes](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyResetVotes.md)|ReadOnly| +|[Azure.DevOps.Repos.HasBranchPolicy](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.HasBranchPolicy.md)|ReadOnly| +|[Azure.DevOps.Repos.License](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.License.md)|ReadOnly| +|[Azure.DevOps.Repos.Readme](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.Readme.md)|ReadOnly| +|[Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md)|FullAccess| +|[Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md)|FullAccess| +|[Azure.DevOps.Repos.InheritedPermissions](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md)|FineGrained| +|[Azure.DevOps.ServiceConnections.ClassicAzure](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.Description](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.GitHubPAT](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.ProductionBranchLimit](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.ProductionCheckProtection](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.ProductionHumanApproval](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.Scope](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md)|ReadOnly| +|[Azure.DevOps.ServiceConnections.WorkloadIdentityFederation](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md)|ReadOnly| +|[Azure.DevOps.Tasks.VariableGroup.Description](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.Description.md)|ReadOnly| +|[Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md)|ReadOnly| +|[Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets](src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md)|ReadOnly| diff --git a/src/PSRule.Rules.AzureDevOps/Functions/Common.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/Common.ps1 index 74a65e6..b38afc3 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/Common.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/Common.ps1 @@ -51,10 +51,16 @@ function Get-AzDevOpsProjects { [CmdletBinding()] [OutputType([System.Object[]])] param ( - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + + [Parameter(ParameterSetName = 'PAT')] [string] $Organization ) diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Core.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Core.ps1 index 30b64dd..f6c229e 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Core.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Core.ps1 @@ -9,6 +9,9 @@ .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly .PARAMETER Organization Organization name for Azure DevOps @@ -20,15 +23,19 @@ Get-AzDevOpsPipelines -PAT $PAT -Organization $Organization -Project $Project #> function Get-AzDevOpsPipelines { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory,ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project ) @@ -76,6 +83,9 @@ Export-ModuleMember -Function Get-AzDevOpsPipelines .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -89,36 +99,46 @@ Export-ModuleMember -Function Get-AzDevOpsPipelines Get-AzDevOpsPipelineAcls -PAT $PAT -Organization $Organization -ProjectId $ProjectId -PipelineId $PipelineId #> function Get-AzDevOpsPipelineAcls { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $ProjectId, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PipelineId ) - $header = Get-AzDevOpsHeader -PAT $PAT - $uri = "https://dev.azure.com/$Organization/_apis/accesscontrollists/33344d9c-fc72-4d6f-aba5-fa317101a7e9?api-version=6.0&token=$($ProjectId)/$($PipelineId)" - Write-Verbose "Getting pipeline ACLs from $uri" - Write-Verbose "PROJECTID: $ProjectId" - try { - $response = (Invoke-RestMethod -Uri $uri -Method Get -Headers $header -ContentType "application/json") #| Where-Object { $_.token -eq "$($ProjectId)/$($PipelineId)" } - # if the response is not an object but a string, the authentication failed - if ($response -is [string]) { - throw "Authentication failed or project not found" + # If Token Type is ReadOnly, write a warning and exit the function returning null + if ($TokenType -eq 'ReadOnly') { + Write-Warning "Token Type is set to ReadOnly, no pipeline ACLs will be returned" + return $null + } else { + $header = Get-AzDevOpsHeader -PAT $PAT + $uri = "https://dev.azure.com/$Organization/_apis/accesscontrollists/33344d9c-fc72-4d6f-aba5-fa317101a7e9?api-version=6.0&token=$($ProjectId)/$($PipelineId)" + Write-Verbose "Getting pipeline ACLs from $uri" + Write-Verbose "PROJECTID: $ProjectId" + try { + $response = (Invoke-RestMethod -Uri $uri -Method Get -Headers $header -ContentType "application/json") #| Where-Object { $_.token -eq "$($ProjectId)/$($PipelineId)" } + # if the response is not an object but a string, the authentication failed + if ($response -is [string]) { + throw "Authentication failed or project not found" + } } + catch { + throw $_.Exception.Message + } + return $response.value } - catch { - throw $_.Exception.Message - } - return $response.value } Export-ModuleMember -Function Get-AzDevOpsPipelineAcls # End of Function Get-AzDevOpsPipelineAcls @@ -134,6 +154,9 @@ Export-ModuleMember -Function Get-AzDevOpsPipelineAcls .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -147,18 +170,22 @@ Export-ModuleMember -Function Get-AzDevOpsPipelineAcls Get-AzDevOpsPipelineYaml -PAT $PAT -Organization $Organization -Project $Project -PipelineId $PipelineId #> function Get-AzDevOpsPipelineYaml { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PipelineId ) @@ -212,6 +239,9 @@ Export-ModuleMember -Function Get-AzDevOpsPipelineYaml .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -228,24 +258,28 @@ Export-ModuleMember -Function Get-AzDevOpsPipelineYaml Export-AzDevOpsPipelineYaml -PAT $PAT -Organization $Organization -Project $Project -PipelineId $PipelineId -OutputPath $OutputPath #> function Export-AzDevOpsPipelineYaml { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PipelineId, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PipelineName, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) @@ -269,6 +303,9 @@ Export-ModuleMember -Function Export-AzDevOpsPipelineYaml .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -282,47 +319,55 @@ Export-ModuleMember -Function Export-AzDevOpsPipelineYaml Export-AzDevOpsPipelines -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath #> function Export-AzDevOpsPipelines { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) Write-Verbose "Getting pipelines from Azure DevOps" - $pipelines = Get-AzDevOpsPipelines -PAT $PAT -Organization $Organization -Project $Project + # If invoking parameter set is PAT, get all pipelines from Azure DevOps + if ($PSCmdlet.ParameterSetName -eq 'PAT') { + $pipelines = Get-AzDevOpsPipelines -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project + } foreach ($pipeline in $pipelines) { # Add ObjectType Azure.DevOps.Pipeline to the pipeline object $pipeline | Add-Member -MemberType NoteProperty -Name ObjectType -Value "Azure.DevOps.Pipeline" # Get the project ID from the pipeline object web.href property $ProjectId = $pipeline._links.web.href.Split('/')[4] - # Add the pipeline ACLs to the pipeline object - $pipeline | Add-Member -MemberType NoteProperty -Name Acls -Value (Get-AzDevOpsPipelineAcls -PAT $PAT -Organization $Organization -ProjectId $ProjectId -PipelineId $pipeline.id) + # Add the pipeline ACLs to the pipeline object if the token type is not ReadOnly + if ($TokenType -ne 'ReadOnly') { + Write-Verbose "Getting pipeline ACLs for pipeline $($pipeline.name)" + $pipeline | Add-Member -MemberType NoteProperty -Name Acls -Value (Get-AzDevOpsPipelineAcls -PAT $PAT -Organization $Organization -ProjectId $ProjectId -PipelineId $pipeline.id) + } else { + Write-Verbose "Token Type is set to ReadOnly, no pipeline ACLs will be returned" + } Write-Verbose "Exporting pipeline $($pipeline.name) to JSON file" Write-Verbose "Exporting pipeline as JSON file to $OutputPath\$($pipeline.name).ado.pl.json" $pipeline | ConvertTo-Json -Depth 100 | Out-File "$OutputPath\$($pipeline.name).ado.pl.json" if ($pipeline.configuration.type -eq 'yaml' -and $pipeline.configuration.repository.type -eq 'azureReposGit') { Write-Verbose "Pipeline $($pipeline.name) is a YAML pipeline" - Write-Verbose "Getting YAML definition for pipeline $($pipeline.name)" - $yaml = "ObjectType: Azure.DevOps.Pipelines.PipelineYaml`n" - $yaml += "PipelineName: $($pipeline.name)`n" - $yaml += Get-AzDevOpsPipelineYaml -PAT $PAT -Organization $Organization -Project $Project -PipelineId $pipeline.id - Write-Verbose "Exporting YAML definition to $OutputPath\$($pipeline.name).yaml" - $yaml | Out-File "$OutputPath\$($pipeline.name).yaml" - Write-Verbose "Exporting pipeline YAML definition to $OutputPath\$($pipeline.name).yaml" - Export-AzDevOpsPipelineYaml -PAT $PAT -Organization $Organization -Project $Project -PipelineId $pipeline.id -PipelineName $pipeline.name -OutputPath $OutputPath + # If invoking parameter set is PAT, get pipeline yaml from Azure DevOps + if ($PSCmdlet.ParameterSetName -eq 'PAT') { + Export-AzDevOpsPipelineYaml -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -PipelineId $pipeline.id -PipelineName $pipeline.name -OutputPath $OutputPath + } } } } Export-ModuleMember -Function Export-AzDevOpsPipelines -# End of Function Export-AzDevOpsPipelines \ No newline at end of file +# End of Function Export-AzDevOpsPipelines diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Environments.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Environments.ps1 index 4ee3e77..5046d0b 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Environments.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Environments.ps1 @@ -8,6 +8,9 @@ .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -20,32 +23,42 @@ function Get-AzDevOpsEnvironments { [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project ) - $header = Get-AzDevOpsHeader -PAT $PAT - Write-Verbose "Getting environments for project $Project" - $uri = "https://dev.azure.com/$Organization/$Project/_apis/pipelines/environments?api-version=6.0-preview.1" - Write-Verbose "URI: $uri" - try { - $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header - # If the response is a string and not an object, throw an exception for authentication failure or project not found - if ($response -is [string]) { - throw "Authentication failed or project not found" + # If token type is ReadOnly, write a warning and exit the function returing null + if($TokenType -eq 'ReadOnly') { + Write-Warning "Token type ReadOnly does not have access to Azure DevOps Pipelines Environments" + return $null + } else { + $header = Get-AzDevOpsHeader -PAT $PAT + Write-Verbose "Getting environments for project $Project" + $uri = "https://dev.azure.com/$Organization/$Project/_apis/pipelines/environments?api-version=6.0-preview.1" + Write-Verbose "URI: $uri" + try { + $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header + # If the response is a string and not an object, throw an exception for authentication failure or project not found + if ($response -is [string]) { + throw "Authentication failed or project not found" + } } + catch { + throw $_.Exception.Message + } + $environments = $response.value + return $environments } - catch { - throw $_.Exception.Message - } - $environments = $response.value - return $environments } Export-ModuleMember -Function Get-AzDevOpsEnvironments @@ -59,6 +72,9 @@ Export-ModuleMember -Function Get-AzDevOpsEnvironments .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -78,43 +94,53 @@ Export-ModuleMember -Function Get-AzDevOpsEnvironments https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/check-configurations/list?view=azure-devops-rest-7.2&tabs=HTTP #> function Get-AzDevOpsEnvironmentChecks { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Environment ) - $header = Get-AzDevOpsHeader -PAT $PAT - Write-Verbose "Getting checks for environment $Environment" - $uri = "https://dev.azure.com/$Organization/$Project/_apis/pipelines/checks/configurations?api-version=7.2-preview.1&resourceType=environment&resourceId=$($Environment)&`$expand=settings" - Write-Verbose "URI: $uri" - try { - $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header - # If the response is a string and not an object, throw an exception for authentication failure or project not found - if ($response -is [string]) { - throw "Authentication failed or project not found" + # If token type is ReadOnly, write a warning and exit the function returing null + if($TokenType -eq 'ReadOnly') { + Write-Warning "Token type ReadOnly does not have access to Azure DevOps Pipelines Environments" + return $null + } else { + $header = Get-AzDevOpsHeader -PAT $PAT + Write-Verbose "Getting checks for environment $Environment" + $uri = "https://dev.azure.com/$Organization/$Project/_apis/pipelines/checks/configurations?api-version=7.2-preview.1&resourceType=environment&resourceId=$($Environment)&`$expand=settings" + Write-Verbose "URI: $uri" + try { + $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header + # If the response is a string and not an object, throw an exception for authentication failure or project not found + if ($response -is [string]) { + throw "Authentication failed or project not found" + } } + catch { + throw $_.Exception.Message + } + $checks = $response.value + if($null -eq $checks) { + return @() + # Else if $checks is not an array, but a single object + } elseif ($null -eq $checks.Count -or $checks.Count -eq 0) { + return @($checks) + } + return $checks } - catch { - throw $_.Exception.Message - } - $checks = $response.value - if($null -eq $checks) { - return @() - # Else if $checks is not an array, but a single object - } elseif ($null -eq $checks.Count -or $checks.Count -eq 0) { - return @($checks) - } - return $checks } Export-ModuleMember -Function Get-AzDevOpsEnvironmentChecks <# @@ -127,6 +153,9 @@ Export-ModuleMember -Function Get-AzDevOpsEnvironmentChecks .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -137,34 +166,44 @@ Export-ModuleMember -Function Get-AzDevOpsEnvironmentChecks Export-AzDevOpsEnvironmentChecks -PAT $PAT -Organization $Organization -Project $Project #> function Export-AzDevOpsEnvironmentChecks { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([System.Object[]])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) - $environments = Get-AzDevOpsEnvironments -PAT $PAT -Organization $Organization -Project $Project - $environments | ForEach-Object { - if($null -ne $_) { - $environment = $_ - # Add a ObjectType indicator for Azure.DevOps.Pipelines.Environment - $environment | Add-Member -MemberType NoteProperty -Name ObjectType -Value 'Azure.DevOps.Pipelines.Environment' - $checks = @(Get-AzDevOpsEnvironmentChecks -PAT $PAT -Organization $Organization -Project $Project -Environment $environment.id) - $environment | Add-Member -MemberType NoteProperty -Name checks -Value $checks - Write-Verbose "Exporting environment $($environment.name) to JSON" - Write-Verbose "Output file: $OutputPath\$($environment.name).ado.env.json" - $environment | ConvertTo-Json -Depth 100 | Out-File -FilePath "$OutputPath\$($environment.name).ado.env.json" + # If token type is ReadOnly, write a warning and exit the function returing null + if($TokenType -eq 'ReadOnly') { + Write-Warning "Token type ReadOnly does not have access to Azure DevOps Pipelines Environments" + return $null + } else { + $environments = Get-AzDevOpsEnvironments -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project + $environments | ForEach-Object { + if($null -ne $_) { + $environment = $_ + # Add a ObjectType indicator for Azure.DevOps.Pipelines.Environment + $environment | Add-Member -MemberType NoteProperty -Name ObjectType -Value 'Azure.DevOps.Pipelines.Environment' + $checks = @(Get-AzDevOpsEnvironmentChecks -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -Environment $environment.id) + $environment | Add-Member -MemberType NoteProperty -Name checks -Value $checks + Write-Verbose "Exporting environment $($environment.name) to JSON" + Write-Verbose "Output file: $OutputPath\$($environment.name).ado.env.json" + $environment | ConvertTo-Json -Depth 100 | Out-File -FilePath "$OutputPath\$($environment.name).ado.env.json" + } } } } diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Releases.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Releases.ps1 index 68f26a0..0af4ae5 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Releases.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Releases.ps1 @@ -14,19 +14,27 @@ .PARAMETER PAT A personal access token (PAT) used to authenticate with Azure DevOps. + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .EXAMPLE Get-AzDevOpsReleaseDefinitions -Organization 'contoso' -Project 'myproject' -PAT $MyPAT #> Function Get-AzDevOpsReleaseDefinitions { + [CmdletBinding(DefaultParameterSetName = 'PAT')] Param( - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $PAT, + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Organization, - [Parameter(Mandatory = $true)] - [string]$Project, - - [Parameter(Mandatory = $true)] - [string]$PAT + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string]$Project ) Write-Verbose "Getting release definitions for project $Project" $uri = "https://vsrm.dev.azure.com/$Organization/$Project/_apis/release/definitions?api-version=7.2-preview.4" @@ -67,6 +75,9 @@ Export-ModuleMember -Function Get-AzDevOpsReleaseDefinitions .PARAMETER PAT A personal access token (PAT) used to authenticate with Azure DevOps. + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Folder The folder where the release definition is located. @@ -74,43 +85,55 @@ Export-ModuleMember -Function Get-AzDevOpsReleaseDefinitions Get-AzDevOpsReleaseDefinitionAcls -Organization 'contoso' -ProjectId '12345678-1234-1234-1234-123456789012' -ReleaseDefinitionId 1 -PAT $MyPAT -Folder 'myfolder' #> Function Get-AzDevOpsReleaseDefinitionAcls { + [CmdletBinding(DefaultParameterSetName = 'PAT')] Param( - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $PAT, + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Organization, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$ProjectId, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [int]$ReleaseDefinitionId, - [Parameter(Mandatory = $true)] - [string]$PAT, - - [Parameter(Mandatory = $false)] + [Parameter(ParameterSetName = 'PAT')] [string]$Folder = '' ) - Write-Verbose "Getting release definition ACLs for release definition $ReleaseDefinitionId" - if ($Folder -eq '') { - $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/c788c23e-1b46-4162-8f5e-d7585343b5de?api-version=6.0&token={1}/{2}" -f $Organization, $ProjectId, $ReleaseDefinitionId - } - else { - $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/c788c23e-1b46-4162-8f5e-d7585343b5de?api-version=6.0&token={1}/{2}/{3}" -f $Organization, $ProjectId, $Folder, $ReleaseDefinitionId - } - Write-Verbose "URI: $uri" - $header = Get-AzDevOpsHeader -PAT $PAT - # try to get the release definition ACLs, throw a descriptive error if it fails for authentication or other reasons - try { - $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header - # If the response is not an object but a string, the authentication failed - if ($response -is [string]) { - throw "Authentication failed or project not found" + # IF token type is ReadOnly, write a warning and exit the function returing null + if ($TokenType -eq 'ReadOnly') { + Write-Warning "The ReadOnly token type is not supported for this function" + return $null + } else { + Write-Verbose "Getting release definition ACLs for release definition $ReleaseDefinitionId" + if ($Folder -eq '') { + $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/c788c23e-1b46-4162-8f5e-d7585343b5de?api-version=6.0&token={1}/{2}" -f $Organization, $ProjectId, $ReleaseDefinitionId } + else { + $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/c788c23e-1b46-4162-8f5e-d7585343b5de?api-version=6.0&token={1}/{2}/{3}" -f $Organization, $ProjectId, $Folder, $ReleaseDefinitionId + } + Write-Verbose "URI: $uri" + $header = Get-AzDevOpsHeader -PAT $PAT + # try to get the release definition ACLs, throw a descriptive error if it fails for authentication or other reasons + try { + $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header + # If the response is not an object but a string, the authentication failed + if ($response -is [string]) { + throw "Authentication failed or project not found" + } + } + catch { + throw $_.Exception.Message + } + return $response.value } - catch { - throw $_.Exception.Message - } - return $response.value } Export-ModuleMember -Function Get-AzDevOpsReleaseDefinitionAcls # End of function Get-AzDevOpsReleaseDefinitionAcls @@ -131,6 +154,9 @@ Export-ModuleMember -Function Get-AzDevOpsReleaseDefinitionAcls .PARAMETER PAT A personal access token (PAT) used to authenticate with Azure DevOps. + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER OutputPath The path to the directory where the JSON files will be exported. @@ -138,20 +164,29 @@ Export-ModuleMember -Function Get-AzDevOpsReleaseDefinitionAcls Export-AzDevOpsReleaseDefinitions -Organization 'contoso' -Project 'myproject' -PAT $MyPAT -OutputPath 'C:\temp' #> Function Export-AzDevOpsReleaseDefinitions { + [CmdletBinding(DefaultParameterSetName = 'PAT')] Param( - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $PAT, + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Organization, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Project, - [Parameter(Mandatory = $true)] - [string]$PAT, - - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$OutputPath ) - $definitions = Get-AzDevOpsReleaseDefinitions -Organization $Organization -Project $Project -PAT $PAT + # If ParameterSet is PAT, get all release definitions for the project + If ($PSCmdlet.ParameterSetName -eq 'PAT') { + $definitions = Get-AzDevOpsReleaseDefinitions -Organization $Organization -Project $Project -PAT $PAT -TokenType $TokenType + } foreach ($definition in $definitions) { if ($null -ne $definition.id) { $definitionId = $definition.id @@ -180,10 +215,15 @@ Function Export-AzDevOpsReleaseDefinitions { else { $folder = $response.path.replace('\','/') } - # Get the release definition ACLs - $acls = Get-AzDevOpsReleaseDefinitionAcls -Organization $Organization -ProjectId $projectId -ReleaseDefinitionId $definitionId -PAT $PAT -Folder $folder - # Add the ACLs to the response - $response | Add-Member -MemberType NoteProperty -Name 'Acls' -Value $acls + # If the token type is not ReadOnly, get the release definitions ACLs + if ($TokenType -ne 'ReadOnly') { + # Get the release definition ACLs + $acls = Get-AzDevOpsReleaseDefinitionAcls -Organization $Organization -ProjectId $projectId -ReleaseDefinitionId $definitionId -PAT $PAT -Folder $folder + # Add the ACLs to the response + $response | Add-Member -MemberType NoteProperty -Name 'Acls' -Value $acls + } else { + Write-Warning "The ReadOnly token type is not supported for ACL export" + } $response | ConvertTo-Json -Depth 100 | Out-File -FilePath $definitionPath } } diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Settings.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Settings.ps1 index 92239f7..87be5ab 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Settings.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Pipelines.Settings.ps1 @@ -8,6 +8,9 @@ .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -18,15 +21,19 @@ Get-AzDevOpsPipelinesSettings -PAT $PAT -Organization $Organization -ProjectId $ProjectId #> Function Get-AzDevOpsPipelinesSettings { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project ) @@ -58,6 +65,9 @@ Export-ModuleMember -Function Get-AzDevOpsPipelinesSettings .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -71,18 +81,22 @@ Export-ModuleMember -Function Get-AzDevOpsPipelinesSettings Export-AzDevOpsPipelinesSettings -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath #> function Export-AzDevOpsPipelinesSettings { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Repos.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Repos.ps1 index c3fe4a7..081ea97 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Repos.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Repos.ps1 @@ -8,6 +8,9 @@ .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -18,16 +21,20 @@ Get-AzDevOpsRepos -PAT $PAT -Organization $Organization -Project $Project #> Function Get-AzDevOpsRepos { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([System.Object[]])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project ) @@ -60,6 +67,9 @@ Export-ModuleMember -Function Get-AzDevOpsRepos .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -79,22 +89,26 @@ Export-ModuleMember -Function Get-AzDevOpsRepos This function returns an empty object if no branch policy is found for the branch #> Function Get-AzDevOpsBranchPolicy { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([object[]])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Repository, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Branch ) @@ -130,6 +144,9 @@ Export-ModuleMember -Function Get-AzDevOpsBranchPolicy .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -143,19 +160,23 @@ Export-ModuleMember -Function Get-AzDevOpsBranchPolicy Get-AzDevOpsRepositoryPipelinePermissions -PAT $PAT -Organization $Organization -ProjectId $ProjectId -RepositoryId $RepositoryId #> Function Get-AzDevOpsRepositoryPipelinePermissions { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([object[]])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $ProjectId, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $RepositoryId ) @@ -186,6 +207,9 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryPipelinePermissions .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -199,36 +223,46 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryPipelinePermissions Get-AzDevOpsRepositoryAcls -PAT $PAT -Organization $Organization -ProjectId $ProjectId -RepositoryId $RepositoryId #> Function Get-AzDevOpsRepositoryAcls { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([object[]])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $ProjectId, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $RepositoryId ) - $header = Get-AzDevOpsHeader -PAT $PAT - $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87?api-version=6.0" -f $Organization - try { - $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header -ContentType "application/json" - # If the response is a string and not an object, throw an exception for authentication failure or project not found - if ($response -is [string]) { - throw "Authentication failed or project not found" + # If the token type is ReadOnly, write a warning and return null + if ($TokenType -eq "ReadOnly") { + Write-Warning "The ReadOnly token type does not have access to the Repositories ACLs API, returning null" + return $null + } else { + $header = Get-AzDevOpsHeader -PAT $PAT + $uri = "https://dev.azure.com/{0}/_apis/accesscontrollists/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87?api-version=6.0" -f $Organization + try { + $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $header -ContentType "application/json" + # If the response is a string and not an object, throw an exception for authentication failure or project not found + if ($response -is [string]) { + throw "Authentication failed or project not found" + } + $thisRepoPerms = $response.value | where-object {($_.token -eq "repoV2/$($ProjectId)/$($RepositoryId)")} } - $thisRepoPerms = $response.value | where-object {($_.token -eq "repoV2/$($ProjectId)/$($RepositoryId)")} - } - catch { - throw $_.Exception.Message + catch { + throw $_.Exception.Message + } + return $thisRepoPerms } - return $thisRepoPerms } Export-ModuleMember -Function Get-AzDevOpsRepositoryAcls # End of Function Get-AzDevOpsRepositoryAcls @@ -243,6 +277,9 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryAcls .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -262,22 +299,26 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryAcls This function return $true if the file exists and $false if it does not #> function Test-AzDevOpsFileExists { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([bool])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Repository, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Path ) @@ -306,6 +347,9 @@ Export-ModuleMember -Function Test-AzDevOpsFileExists .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -319,47 +363,57 @@ Export-ModuleMember -Function Test-AzDevOpsFileExists Get-AzDevOpsRepositoryGhas -PAT $PAT -Organization $Organization -Project $Project -Repository $Repository #> Function Get-AzDevOpsRepositoryGhas { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] [OutputType([object])] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $ProjectId, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $RepositoryId ) - $header = Get-AzDevOpsHeader -PAT $PAT - $payload = @{ - contributionIds = @( - "ms.vss-features.my-organizations-data-provider" - "ms.vss-advsec.advanced-security-enablement-data-provider" - ) - dataProviderContext = @{ - properties = @{ - givenProjectId = $ProjectId - givenRepoId = $RepositoryId + # token is not FullAccess, write a warning and return null + if ($TokenType -ne "FullAccess") { + Write-Warning "The $TokenType token type does not have access to the Repositories API, returning null" + return $null + } else { + $header = Get-AzDevOpsHeader -PAT $PAT + $payload = @{ + contributionIds = @( + "ms.vss-features.my-organizations-data-provider" + "ms.vss-advsec.advanced-security-enablement-data-provider" + ) + dataProviderContext = @{ + properties = @{ + givenProjectId = $ProjectId + givenRepoId = $RepositoryId + } } } - } - $url = "https://dev.azure.com/$Organization/_apis/Contribution/HierarchyQuery?api-version=5.0-preview.1" - try { - $response = Invoke-RestMethod -Uri $url -Method Post -Headers $header -Body ($payload | ConvertTo-Json) -ContentType "application/json" - # If the response is a string and not an object, throw an exception for authentication failure or project not found - if ($response -is [string]) { - throw "Authentication failed or project not found" + $url = "https://dev.azure.com/$Organization/_apis/Contribution/HierarchyQuery?api-version=5.0-preview.1" + try { + $response = Invoke-RestMethod -Uri $url -Method Post -Headers $header -Body ($payload | ConvertTo-Json) -ContentType "application/json" + # If the response is a string and not an object, throw an exception for authentication failure or project not found + if ($response -is [string]) { + throw "Authentication failed or project not found" + } } + catch { + throw $_.Exception.Message + } + return $response.dataProviders.'ms.vss-advsec.advanced-security-enablement-data-provider' } - catch { - throw $_.Exception.Message - } - return $response.dataProviders.'ms.vss-advsec.advanced-security-enablement-data-provider' } Export-ModuleMember -Function Get-AzDevOpsRepositoryGhas # End of Function Get-AzDevOpsRepositoryGhas @@ -374,6 +428,9 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryGhas .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token Type for Azure DevOps, can be FullAccess, FineGrained or ReadOnly + .PARAMETER Organization Organization name for Azure DevOps @@ -390,51 +447,65 @@ Export-ModuleMember -Function Get-AzDevOpsRepositoryGhas This function returns an empty object if no branch policy is found for the branch #> function Export-AzDevOpsReposAndBranchPolicies { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) - # Get all repos in project - $repos = Get-AzDevOpsRepos -PAT $PAT -Organization $Organization -Project $Project + # If the parameter set is PAT, get the repositories + if ($PSCmdlet.ParameterSetName -eq 'PAT') { + $repos = Get-AzDevOpsRepos -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project + } $repos | ForEach-Object { if ($null -ne $_) { $repo = $_ # Add ObjectType Azure.DevOps.Repo to repo object $repo | Add-Member -MemberType NoteProperty -Name ObjectType -Value "Azure.DevOps.Repo" Write-Verbose "Getting branch policy for repo $($repo.name)" - $branchPolicy = Get-AzDevOpsBranchPolicy -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Branch $repo.defaultBranch + If($repo.defaultBranch) { + $branchPolicy = Get-AzDevOpsBranchPolicy -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -Repository $repo.id -Branch $repo.defaultBranch + } $repo | Add-Member -MemberType NoteProperty -Name MainBranchPolicy -Value $branchPolicy # Add a property indicating if a file named README.md or README exists in the repo - $readmeExists = ((Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "README.md") -or (Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "README")) + $readmeExists = ((Test-AzDevOpsFileExists -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -Repository $repo.id -Path "README.md") -or (Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "README")) $repo | Add-Member -MemberType NoteProperty -Name ReadmeExists -Value $readmeExists # Add a property indicating if a file named LICENSE or LICENSE.md exists in the repo - $licenseExists = ((Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "LICENSE") -or (Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "LICENSE.md")) + $licenseExists = ((Test-AzDevOpsFileExists -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -Repository $repo.id -Path "LICENSE") -or (Test-AzDevOpsFileExists -PAT $PAT -Organization $Organization -Project $Project -Repository $repo.id -Path "LICENSE.md")) $repo | Add-Member -MemberType NoteProperty -Name LicenseExists -Value $licenseExists - # Add a property for GitHub Advanced Security (GHAS) data - $ghas = Get-AzDevOpsRepositoryGhas -PAT $PAT -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id - $repo | Add-Member -MemberType NoteProperty -Name Ghas -Value $ghas - + # Add a property for GitHub Advanced Security (GHAS) data if the token type is FullAccess + if ($TokenType -eq "FullAccess") { + $ghas = Get-AzDevOpsRepositoryGhas -PAT $PAT -TokenType $TokenType -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id + $repo | Add-Member -MemberType NoteProperty -Name Ghas -Value $ghas + } else { + Write-Warning "The $TokenType token type does not have access to the GHAS API, returning null" + } + # Add a property with pipeline permissions - $pipelinePermissions = Get-AzDevOpsRepositoryPipelinePermissions -PAT $PAT -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id + $pipelinePermissions = Get-AzDevOpsRepositoryPipelinePermissions -PAT $PAT -TokenType $TokenType -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id $repo | Add-Member -MemberType NoteProperty -Name PipelinePermissions -Value $pipelinePermissions - # Add a property with repo ACLs - $repoAcls = Get-AzDevOpsRepositoryAcls -PAT $PAT -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id - $repo | Add-Member -MemberType NoteProperty -Name Acls -Value $repoAcls - + # Add a property with repo ACLs if the token type is not ReadOnly + if ($TokenType -ne "ReadOnly") { + $repoAcls = Get-AzDevOpsRepositoryAcls -PAT $PAT -TokenType $TokenType -Organization $Organization -ProjectId $repo.project.id -RepositoryId $repo.id + $repo | Add-Member -MemberType NoteProperty -Name Acls -Value $repoAcls + } + # Export repo object to JSON file Write-Verbose "Exporting repo $($repo.name) to JSON as file $($repo.name).ado.repo.json" $repo | ConvertTo-Json -Depth 100 | Out-File -FilePath "$OutputPath\$($repo.name).ado.repo.json" diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.ServiceConnections.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.ServiceConnections.ps1 index ce881c6..e7e7d82 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.ServiceConnections.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.ServiceConnections.ps1 @@ -8,6 +8,9 @@ .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .PARAMETER Organization Organization name for Azure DevOps @@ -18,15 +21,19 @@ Get-AzDevOpsServiceConnections -PAT $PAT -Organization $Organization -Project $Project #> function Get-AzDevOpsServiceConnections { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project ) @@ -59,6 +66,9 @@ Export-ModuleMember -Function Get-AzDevOpsServiceConnections .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .PARAMETER Organization Organization name for Azure DevOps @@ -75,18 +85,22 @@ Export-ModuleMember -Function Get-AzDevOpsServiceConnections https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/check-configurations/list?view=azure-devops-rest-7.2&tabs=HTTP #> function Get-AzDevOpsServiceConnectionChecks { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $ServiceConnectionId ) @@ -117,6 +131,9 @@ Export-ModuleMember -Function Get-AzDevOpsServiceConnectionChecks .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .PARAMETER Organization Organization name for Azure DevOps @@ -133,18 +150,22 @@ Export-ModuleMember -Function Get-AzDevOpsServiceConnectionChecks https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/check-configurations/list?view=azure-devops-rest-7.2&tabs=HTTP #> function Export-AzDevOpsServiceConnections { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) @@ -162,4 +183,4 @@ function Export-AzDevOpsServiceConnections { } } Export-ModuleMember -Function Export-AzDevOpsServiceConnections -# End of Function Export-AzDevOpsServiceConnections \ No newline at end of file +# End of Function Export-AzDevOpsServiceConnections diff --git a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Tasks.VariableGroups.ps1 b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Tasks.VariableGroups.ps1 index 00dc52c..55b5bbe 100644 --- a/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Tasks.VariableGroups.ps1 +++ b/src/PSRule.Rules.AzureDevOps/Functions/DevOps.Tasks.VariableGroups.ps1 @@ -14,19 +14,29 @@ .PARAMETER PAT A personal access token (PAT) used to authenticate with Azure DevOps. + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .EXAMPLE Get-AzDevOpsVariableGroups -Organization 'myorganization' -Project 'myproject' -PAT $myPAT #> Function Get-AzDevOpsVariableGroups { + [CmdletBinding(DefaultParameterSetName = 'PAT')] param( - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Organization, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string]$Project, - [Parameter(Mandatory = $true)] - [string]$PAT + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $PAT, + + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess' ) Write-Verbose "Getting variable groups for project $Project" $url = "https://dev.azure.com/$Organization/$Project/_apis/distributedtask/variablegroups?api-version=7.2-preview.2" @@ -78,17 +88,26 @@ Export-ModuleMember -Function Get-AzDevOpsVariableGroups #> Function Export-AzDevOpsVariableGroups { param( - [Parameter(Mandatory = $true)] - [string]$Organization, - - [Parameter(Mandatory = $true)] - [string]$Project, - - [Parameter(Mandatory = $true)] - [string]$PAT, - - [Parameter(Mandatory = $true)] - [string]$OutputPath + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $Organization, + + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $Project, + + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $PAT, + + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + + [Parameter(Mandatory, ParameterSetName = 'PAT')] + [string] + $OutputPath ) $variableGroups = Get-AzDevOpsVariableGroups -Organization $Organization -Project $Project -PAT $PAT $variableGroups | ForEach-Object { diff --git a/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psd1 b/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psd1 index fbb1e46..26d6d47 100644 --- a/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psd1 +++ b/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psd1 @@ -12,7 +12,7 @@ RootModule = 'PSRule.Rules.AzureDevOps.psm1' # Version number of this module. -ModuleVersion = '0.0.12' +ModuleVersion = '0.2.0' # Supported PSEditions CompatiblePSEditions = @('Core','Desktop') diff --git a/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psm1 b/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psm1 index 4f718d6..dbeabd2 100644 --- a/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psm1 +++ b/src/PSRule.Rules.AzureDevOps/PSRule.Rules.AzureDevOps.psm1 @@ -20,6 +20,9 @@ Get-ChildItem -Path "$PSScriptRoot/Functions/*.ps1" | ForEach-Object { .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .PARAMETER Organization Organization name for Azure DevOps @@ -33,28 +36,32 @@ Get-ChildItem -Path "$PSScriptRoot/Functions/*.ps1" | ForEach-Object { Export-AzDevOpsRuleData -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath #> Function Export-AzDevOpsRuleData { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Project, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) - Export-AzDevOpsReposAndBranchPolicies -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath - Export-AzDevOpsEnvironmentChecks -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 - Export-AzDevOpsReleaseDefinitions -PAT $PAT -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsReposAndBranchPolicies -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsEnvironmentChecks -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsServiceConnections -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsPipelines -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsPipelinesSettings -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsVariableGroups -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath + Export-AzDevOpsReleaseDefinitions -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $Project -OutputPath $OutputPath } Export-ModuleMember -Function Export-AzDevOpsRuleData -Alias Export-AzDevOpsProjectRuleData # End of Function Export-AzDevOpsRuleData @@ -69,6 +76,9 @@ Export-ModuleMember -Function Export-AzDevOpsRuleData -Alias Export-AzDevOpsProj .PARAMETER PAT Personal Access Token (PAT) for Azure DevOps + .PARAMETER TokenType + Token type for Azure DevOps (FullAccess, FineGrained, ReadOnly) + .PARAMETER Organization Organization name for Azure DevOps @@ -79,19 +89,23 @@ Export-ModuleMember -Function Export-AzDevOpsRuleData -Alias Export-AzDevOpsProj Export-AzDevOpsOrganizationRuleData -PAT $PAT -Organization $Organization -OutputPath $OutputPath #> Function Export-AzDevOpsOrganizationRuleData { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'PAT')] param ( - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $PAT, - [Parameter()] + [Parameter(ParameterSetName = 'PAT')] + [ValidateSet('FullAccess', 'FineGrained', 'ReadOnly')] + [string] + $TokenType = 'FullAccess', + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $Organization, - [Parameter()] + [Parameter(Mandatory, ParameterSetName = 'PAT')] [string] $OutputPath ) - $projects = Get-AzDevOpsProjects -PAT $PAT -Organization $Organization + $projects = Get-AzDevOpsProjects -PAT $PAT -TokenType $TokenType -Organization $Organization $projects | ForEach-Object { $project = $_ # Create a subfolder for each project @@ -99,7 +113,7 @@ Function Export-AzDevOpsOrganizationRuleData { if(!(Test-Path -Path $subPath)) { New-Item -Path $subPath -ItemType Directory } - Export-AzDevOpsRuleData -PAT $PAT -Organization $Organization -Project $project.name -OutputPath $subPath + Export-AzDevOpsRuleData -PAT $PAT -TokenType $TokenType -Organization $Organization -Project $project.name -OutputPath $subPath } } Export-ModuleMember -Function Export-AzDevOpsOrganizationRuleData diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md index e676f77..9eb21af 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md @@ -15,6 +15,8 @@ Pipeline permissions should not be inherited from the project. Pipeline permissions should not be inherited from the project. Inherited permissions can lead to unexpected access to resources. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider removing inherited permissions from the pipeline and setting diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md index c453cf4..214845c 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ stored in Azure Key Vault and referenced in the variable group. This will preven secret from being exposed in the build logs. If the secret is stored in plain text, it will be exposed in the build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider storing secrets in Azure Key Vault and referencing them in the variable group. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md index 65031d7..7de3f62 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md @@ -18,6 +18,8 @@ you manage changes to your application code. You can use source control to view changes to your pipelines, roll back to previous versions, and easily collaborate with other developers on your team. +Mininum TokenType: `ReadOnly + ## RECOMMENDATION Use YAML pipeline definitions to define build and release pipelines. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.Description.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.Description.md index ed3e6e9..1ab0566 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.Description.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.Description.md @@ -17,6 +17,8 @@ Adding a description to an environment will help users understand the purpose of the environment. This will help users understand how and when it should be used. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider adding a description to the environment. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md index 7a616a0..bf81e72 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md @@ -16,6 +16,8 @@ A production environment should be limited to the branches it can be used in. Th the environment is not used in a non-production branch. This rule checks if the environment is limited to a production branch. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider limiting the environment to a production branch. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md index 4d81e6a..9bba8fa 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md @@ -18,6 +18,8 @@ checks to prevent accidental changes to production resources. Checks can be used to require a user to approve a deployment or require a successful build before a deployment can be made. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider adding one or more checks to the environment. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md index d721a59..cf9382c 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md @@ -19,6 +19,8 @@ changes to production resources. For example, a service connection scoped to production should be protected with a check that requires a minimum number of reviewers or a specific CI pipeline must pass. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider protecting a service connection scoped to production with a human diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md index 9cf0553..704fa2d 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md @@ -16,6 +16,8 @@ Microsoft Hosted agent pools should be pinned to a version. This ensures that the pipeline will not be impacted by changes to the agent pool and its operating system. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider pinning the agent pool to a specific version. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md index 53406d0..8e12282 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md @@ -15,6 +15,8 @@ Pipeline steps should have a display name. Pipeline steps should have a display name. This ensures that the pipeline is easier to read and understand. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider adding a display name to all steps. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md index fe550de..b1cc4d8 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md @@ -15,6 +15,8 @@ Release Pipeline permissions should not be inherited from the project. Release Pipeline permissions should not be inherited from the project. Inherited permissions can lead to unexpected access to resources. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider removing inherited permissions from the release pipeline and setting diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md index 734a2ab..45b61c7 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ stored in Azure Key Vault and referenced in the variable group. This will preven secret from being exposed in the build logs. If the secret is stored in plain text, it will be exposed in the build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider storing secrets in Azure Key Vault and referencing them in the variable group. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md index bb73e6c..a43451b 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md @@ -21,6 +21,8 @@ You can configure the minimum number of approvers for this rule by setting the `releaseMinimumProductionApproverCount` configuration value in PSRule. The default value is `1`. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider protecting a release stage environment scoped to production with a human diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md index 701dd09..b9dd0a3 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md @@ -16,6 +16,8 @@ An environment scoped to production should not allow self approval. This rule checks if a release stage environment scoped to production has self approval enabled. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider disabling self approval for the environment. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md index b85da0d..21e283f 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md @@ -16,6 +16,8 @@ Limiting the job authorization scope to the current project will prevent the job being able to access resources in other projects. This can help prevent accidental access to resources in other projects. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider limiting the job authorization scope to the current project in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md index 0d42c4e..80002e6 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md @@ -17,6 +17,8 @@ can be configured to use a different set of resources. Limiting the job authoriz scope to the current project will prevent the job from being able to access resources in other projects. This can help prevent accidental access to resources in other projects. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider limiting the job authorization scope for release pipelines to the current project in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md index 18239de..701f198 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md @@ -17,6 +17,8 @@ can be configured to use a different set of resources. Limiting the job authoriz scope to the current project will prevent the job from being able to access resources in other projects. This can help prevent accidental access to resources in other projects. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider limiting the job authorization scope for YAML pipelines to the current project in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md index ab0a4c8..8a65267 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md @@ -17,6 +17,8 @@ pipeline. This can be useful for testing or debugging. However, this can also be used to override variables that are used to control the behavior of the pipeline and may result in unexpected behavior. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider disabling the ability to set variables at queue time in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md index 9c3b5fc..90068be 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md @@ -14,6 +14,8 @@ Project settings should require a comment for pull requests from a fork. Before building a fork, a member of the project should review the changes and approve the pull request. This can help prevent malicious code from being introduced into the project. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider requiring a comment for pull requests from a fork in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md index c8607b3..19547e5 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md @@ -14,6 +14,8 @@ Project settings should restrict access to secrets for pull requests from a fork Secrets can be used to store sensitive information such as passwords and access tokens. Secrets can be used in pipelines to access resources such as Azure Key Vault. Secrets can be configured to be available to all pipelines or only to specific pipelines. Secrets can also be configured to be available to pull requests from forks. This can be useful for open source projects that accept contributions from the community. However, this can also be a security risk. A malicious user could create a pull request from a fork and access the secrets in the pipeline. This could allow the malicious user to access sensitive information such as passwords and access tokens. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider restricting access to secrets for pull requests from a fork in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md index b35f5dc..c8b7439 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md @@ -14,6 +14,8 @@ Project settings should enforce sanitization of shell task arguments to prevent Shell tasks can be used to run arbitrary commands on the agent. If the arguments are not sanitized, it is possible for a malicious actor to inject additional commands into the arguments. This can lead to the execution of malicious code on the agent. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider enforcing sanitization of shell task arguments in the project settings. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md index 6ae36bf..1cb9ca6 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md @@ -16,6 +16,8 @@ The branch policy should not allow creators to approve their own changes. This will help ensure that the code in the default branch is of a high quality and that the team's Git workflow is followed. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider disabling the option to allow creators to approve their own changes. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md index 303292c..369f83e 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md @@ -14,6 +14,8 @@ A policy should be configured to require comments for pull requests to be resolv Require comments for pull requests to be resolved to ensure that all comments are addressed. This helps to ensure that all comments are addressed and improves the quality of the pull request. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider enabling the policy to require comments for pull requests to be resolved. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md index 5b057da..987b20d 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md @@ -14,6 +14,8 @@ A policy should be configured to require linked work items for pull requests. Require linked work items for pull requests to ensure that changes are associated with a work item. This helps to track changes and ensure that changes are associated with a work item and thus documented in some way. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider enabling the policy to require linked work items for pull requests. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md index 7291fd6..6955e04 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md @@ -21,6 +21,8 @@ A branch policy can be enabled for the default branch of a repository. This will help ensure that the code in the default branch is of a high quality and that the team's Git workflow is followed. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Make sure that the branch policy is enabled for the default branch of your diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md index 7daee31..76f6bb1 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md @@ -14,6 +14,8 @@ A policy should be configured to define a merge strategy for pull requests. Define a merge strategy for pull requests to ensure that changes are merged in a consistent way. This helps to ensure that changes are merged in a consistent way and thus reduces the risk of merge conflicts. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider enabling the policy to define a merge strategy for pull requests. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md index 58d6c68..f77f03f 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md @@ -21,6 +21,7 @@ You can configure the minimum number of reviewers for this rule by setting the `branchMinimumApproverCount` configuration value in PSRule. The default value is `1`. +Mininum TokenType: `ReadOnly` ## RECOMMENDATION diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md index 92a7ca5..0b1e145 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md @@ -19,6 +19,8 @@ are validated before being merged into the default branch. This rule does not validate that the build or CI pipeline is configured correctly. It only validates that a build or CI pipeline is configured. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider enabling the branch policy to require a build or CI pipeline to pass diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyResetVotes.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyResetVotes.md index b556d8e..65b13aa 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyResetVotes.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.BranchPolicyResetVotes.md @@ -19,6 +19,8 @@ votes, the policy should be configured to reset votes when changes are updated. This will help ensure that the code in the default branch is of a high quality and that the team's Git workflow is followed. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider configuring the branch policy to reset votes when changes are updated. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md index fbd3ebc..13a2e39 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md @@ -16,6 +16,8 @@ GitHub Advanced Security provides a suite of security features for Azure DevOps repositories. This rule checks if GitHub Advanced Security is configured to block pushes not meeting security requirements. +Mininum TokenType: `FullAccess` + ## RECOMMENDATION Consider configuring GitHub Advanced Security to block pushes not meeting security diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md index b7c5098..f548dbc 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md @@ -23,6 +23,8 @@ GitHub Advanced Security adds the following features: - Secret scanning repo scanning - Dependency scanning +Mininum TokenType: `FullAccess` + ## RECOMMENDATION Consider enabling GitHub Advanced Security for the repository. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.HasBranchPolicy.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.HasBranchPolicy.md index 6b836a6..79c8b41 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.HasBranchPolicy.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.HasBranchPolicy.md @@ -17,6 +17,8 @@ team's Git workflow. Branch policies can enforce your team's code quality and change management standards. They can also help your team find and fix bugs earlier in the development cycle. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider adding a branch policy to the default branch of your repository. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md index 7fe5f25..2042bc6 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.InheritedPermissions.md @@ -15,6 +15,8 @@ Repository permissions should not be inherited from the project. Repository permissions should not be inherited from the project. Inherited permissions can lead to unexpected access to repositories and branches. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Consider removing inherited permissions from the repository and setting diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.License.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.License.md index 40654b4..a3cbf59 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.License.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.License.md @@ -17,6 +17,8 @@ Public repositories on Azure DevOps are often used to share open source software To license your project, create a LICENSE file in the repository root. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider creating a LICENSE file in the default branch to communicate how your diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.Readme.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.Readme.md index eb798fd..371d3b1 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.Readme.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Repos.Readme.md @@ -16,6 +16,8 @@ information. When someone visits the repository homepage the README.md in the default branch is automatically shown. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider creating a README.md file in repository default branch to provide diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md index b6ac164..85c155b 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ClassicAzure.md @@ -19,6 +19,8 @@ be scoped to a specific resource group or subscription. This means that any user 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. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider using a service connection type that can be scoped to a specific resource group diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md index f8b68f8..0139738 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Description.md @@ -17,6 +17,8 @@ Adding a description to a service connection will help users understand the purpose of the service connection. This will help users understand how and when it should be used. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider adding a description to the service connection. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md index 1388960..e2ab2b6 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.GitHubPAT.md @@ -19,6 +19,8 @@ linked to a personal account and cannot be traced back to the specific connectio Azure DevOps. This means any user with access to the service connection can impersonate the user who created the service connection. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider using an oauth-based service connection. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md index ac85f3b..2a6cc39 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md @@ -18,6 +18,8 @@ in. This ensures that the service connection is not used in a non-production branch. This rule checks that the service connection is limited to a production branch. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider limiting the service connection to a production branch. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md index 6acbd48..b5e9f17 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md @@ -18,6 +18,8 @@ accidental changes to production resources. For example, a service connection scoped to production should be protected with a check that requires a minimum number of reviewers or a specific CI pipeline must pass. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider protecting a service connection scoped to production with one or diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md index 0448da4..015ccc2 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md @@ -19,6 +19,8 @@ changes to production resources. For example, a service connection scoped to production should be protected with a check that requires a minimum number of reviewers or a specific CI pipeline must pass. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider protecting a service connection scoped to production with a human diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md index c58a3c1..0549d03 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.Scope.md @@ -21,6 +21,8 @@ or access is made to the production resources or beyond. Normally it is not desirable to have a service connection with access to all resource groups in a subscription. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider using a resource group scope for a service connection scoped to diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md index 5da7de3..d3ebedf 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md @@ -17,6 +17,8 @@ managed by Azure Active Directory to authenticate to Azure services instead of using a service principal managed by Azure DevOps. This is more secure as the service principal is not stored in Azure DevOps. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider using Workload Identity Federation for your service connections. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.Description.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.Description.md index 880c5eb..c0803d1 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.Description.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.Description.md @@ -17,6 +17,8 @@ Adding a description to a variable group will help users understand the purpose of the variable group. This will help users understand how and when it should be used. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider adding a description to the variable group. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md index 981bc18..255825e 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md @@ -14,6 +14,8 @@ A variable group should not contain any secrets when it is not linked to a key v A variable group should not contain any secrets when it is not linked to a key vault. This is because the secrets will be stored in plain text in the variable group and can be viewed by anyone with access to the variable group. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider removing any secrets from the variable group or replacing them with variables that are linked to a key vault. diff --git a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md index 2cc1f83..8bdcd81 100644 --- a/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ Azure Key Vault and referenced in the variable group. This will prevent the secr being exposed in the build logs. If the secret is stored in plain text, it will be exposed in the build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Consider storing secrets in Azure Key Vault and referencing them in the variable group. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.InheritedPermissions.md index 1ac6aa3..aed489f 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.InheritedPermissions.md @@ -15,6 +15,8 @@ Pipeline permissies mogen niet worden geërfd van het project. Pipeline permissies mogen niet worden geërfd van het project. Geërfde permissies kunnen leiden tot onverwachte toegang tot resources. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om geërfde permissies uit de pipeline te verwijderen en expliciet diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md index c5444c5..473e0c5 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ worden opgeslagen in Azure Key Vault en worden gerefereerd in de variabele groep voorkomen dat het geheim wordt blootgesteld in de build logs. Als het geheim in platte tekst wordt opgeslagen, wordt het blootgesteld in de build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om geheimen op te slaan in Azure Key Vault en ze te refereren in de variabele diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md index e43c716..bc57ed7 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md @@ -19,6 +19,8 @@ Het gebruik van YAML pipeline-definities biedt een aantal voordelen ten opzichte - YAML pipeline-definities kunnen worden gecontroleerd op wijzigingen en worden goedgekeurd voordat ze worden geïmplementeerd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om YAML pipeline-definities te gebruiken om build- en diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.Description.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.Description.md index b705b73..e80c13b 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.Description.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.Description.md @@ -15,6 +15,8 @@ Een Azure DevOps Pipelines environment zou een beschrijving moeten hebben. Het toevoegen van een beschrijving aan een Azure DevOps Pipelines environment kan helpen bij het begrijpen van de context van de environment. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om een beschrijving toe te voegen aan de Azure DevOps Pipelines diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md index d76e383..42c1168 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md @@ -16,6 +16,8 @@ Een productie environment moet beperkt zijn in de branches waarin deze kan worde niet-productiebranch. Deze regel controleert of de environment is beperkt tot een productiebranch. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om de environment te beperken tot een productiebranch. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md index a99f9f1..a8bef10 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md @@ -21,6 +21,8 @@ kunnen worden gebruikt om te eisen dat een gebruiker een implementatie goedkeurt of dat er een succesvolle build moet zijn voordat een implementatie kan worden uitgevoerd. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om een of meer controles toe te voegen aan de Azure DevOps diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md index 883eb1a..00b0190 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md @@ -20,6 +20,8 @@ te voorkomen dat er per ongeluk wijzigingen worden aangebracht in productiebronnen. Een goedkeuring kan worden gebruikt om te eisen dat een gebruiker een implementatie goedkeurt voordat deze kan worden uitgevoerd. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om een menselijke goedkeuring toe te voegen aan de Azure DevOps diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md index 805380b..28d8f38 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md @@ -16,6 +16,8 @@ Microsoft Hosted agent pools zouden vastgepind moeten worden op een versie. Dit zorgt ervoor dat de pipeline niet beïnvloed wordt door wijzigingen aan de agent pool en het besturingssysteem. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de agent pool vast te pinnen op een specifieke versie. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md index 84b2455..1e89ef4 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md @@ -15,6 +15,8 @@ Pipeline stappen moeten een weergavenaam hebben. Pipeline stappen moeten een weergavenaam hebben. Dit zorgt ervoor dat de pipeline makkelijker te lezen en te begrijpen is. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een weergavenaam toe te voegen aan de stappen. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md index 4f33ab0..6591b38 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md @@ -15,6 +15,8 @@ Release Pipeline permissies mogen niet worden overgenomen van het project. Release Pipeline permissies mogen niet worden overgenomen van het project. Geërfde permissies kunnen leiden tot onverwachte toegang tot resources. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om geërfde permissies uit de release pipeline te verwijderen en expliciete diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md index d603d5f..1a24a68 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ worden opgeslagen in Azure Key Vault en worden gerefereerd in de variabele groep voorkomen dat het geheim wordt blootgesteld in de build logs. Als het geheim in platte tekst wordt opgeslagen, wordt het blootgesteld in de build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om geheimen op te slaan in Azure Key Vault en ze te refereren in de variabele diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md index 1addf52..19b8e39 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md @@ -23,6 +23,8 @@ U kunt het vereiste aantal goedkeurders voor deze regel configureren door de `releaseMinimumProductionApproverCount` configuratiewaarde in PSRule in te stellen. De standaardwaarde is `1`. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een menselijke goedkeuring toe te voegen aan de Azure DevOps diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md index 888cb39..82d6f55 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md @@ -15,6 +15,8 @@ Een release stage die is beperkt tot productie mag geen zelfgoedkeuring toestaan Een release stage die is beperkt tot productie mag geen zelfgoedkeuring toestaan. Deze regel controleert of een release stage die is beperkt tot productie zelfgoedkeuring heeft ingeschakeld. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om zelfgoedkeuring voor de omgeving uit te schakelen. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md index 9120783..77122c4 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md @@ -14,6 +14,8 @@ De projectinstellingen moeten de machtigingsomvang van de taak beperken tot de h Het beperken van de machtigingsomvang van de taak tot het huidige project voorkomt dat de taak toegang krijgt tot resources in andere projecten. Dit kan helpen voorkomen dat er per ongeluk toegang wordt verkregen tot resources in andere projecten. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de machtigingsomvang van de taak voor release-pipelines te beperken tot het huidige project in de projectinstellingen. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md index cabdaa6..677f380 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md @@ -18,6 +18,8 @@ machtigingsomvang van de taak te beperken tot het huidige project, kan de taak g toegang krijgen tot resources in andere projecten. Dit kan helpen voorkomen dat er per ongeluk toegang wordt verkregen tot resources in andere projecten. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de machtigingsomvang van de taak voor release-pipelines te beperken tot het huidige project in de projectinstellingen. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md index c24a714..dc73a70 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md @@ -18,6 +18,8 @@ machtigingsomvang van de taak te beperken tot het huidige project, kan de taak g toegang krijgen tot resources in andere projecten. Dit kan helpen voorkomen dat er per ongeluk toegang wordt verkregen tot resources in andere projecten. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de machtigingsomvang van de taak voor release-pipelines te beperken tot het diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md index 48b459d..0d9a112 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md @@ -17,6 +17,8 @@ pipeline zijn gedefinieerd te overschrijven. Dit kan handig zijn voor testen of Dit kan echter ook worden gebruikt om variabelen te overschrijven die worden gebruikt om het gedrag van de pipeline te regelen en kan resulteren in onverwacht gedrag. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om het instellen van variabelen bij het wachtrijen uit te schakelen in de diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md index d8c6e29..09d2813 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md @@ -16,6 +16,8 @@ Voordat een fork wordt gebouwd, moet een lid van het project de wijzigingen beki pull-aanvraag goedkeuren. Dit kan helpen voorkomen dat er kwaadaardige code in het project wordt geïntroduceerd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een opmerking te vereisen voor pull-aanvragen van een fork in de diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md index dfe81ef..9edf02f 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md @@ -24,6 +24,8 @@ pull-aanvraag van een fork maken en de geheimen in de pipeline openen. Dit kan d kwaadwillende gebruiker in staat stellen om gevoelige informatie zoals wachtwoorden en toegangstokens te openen. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de toegang tot geheimen voor pull-aanvragen van een fork te beperken in de diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md index 4924649..df41e76 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md @@ -17,6 +17,8 @@ Als de argumenten niet worden gesaneerd, is het mogelijk dat een kwaadwillende e opdrachten in de argumenten injecteert. Dit kan leiden tot de uitvoering van kwaadaardige code op de agent. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om het instellen van variabelen bij het wachtrijen uit te schakelen in de diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md index d6544ab..ca080fe 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md @@ -18,6 +18,8 @@ eigen wijzigingen goedkeurt. Dit zal helpen om ervoor te zorgen dat de code in de standaard branch van hoge kwaliteit is en dat de Git workflow van het team wordt gevolgd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de optie om makers hun eigen wijzigingen te laten goedkeuren diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyCommentResolution.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyCommentResolution.md index 345591a..879ac45 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyCommentResolution.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyCommentResolution.md @@ -18,6 +18,8 @@ zorgen dat alle opmerkingen worden aangepakt. Dit helpt om ervoor te zorgen dat alle opmerkingen worden aangepakt en verbetert de kwaliteit van de pull request. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de optie om opmerkingen voor pull requests op te lossen in te diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md index dc49608..876d4e3 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md @@ -17,6 +17,8 @@ Het vereisen van gekoppelde work items voor pull requests helpt om wijzigingen bij te houden en ervoor te zorgen dat wijzigingen zijn gekoppeld aan een work item en dus op de een of andere manier zijn gedocumenteerd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de optie om gekoppelde work items voor pull requests te diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyIsEnabled.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyIsEnabled.md index d627216..5f7c214 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyIsEnabled.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyIsEnabled.md @@ -23,6 +23,8 @@ repository. Dit zal helpen om ervoor te zorgen dat de code in de standaard branch van hoge kwaliteit is en dat de Git workflow van het team wordt gevolgd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Zorg ervoor dat de branch policy is ingeschakeld voor de standaard branch diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md index 3ecc027..6686337 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md @@ -18,6 +18,8 @@ wijzigingen op een consistente manier worden samengevoegd. Dit helpt om ervoor te zorgen dat wijzigingen op een consistente manier worden samengevoegd en vermindert zo het risico op merge conflicten. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de optie om een merge strategie voor pull requests te definiëren diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md index 5e55cdd..eef8d04 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md @@ -20,6 +20,8 @@ is en dat de Git workflow van het team wordt gevolgd. Je kunt het minimum aantal reviewers voor deze regel configureren door de `branchMinimumApproverCount` configuratiewaarde in PSRule in te stellen. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de optie om een minimum aantal reviewers voor een branch policy diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyRequireBuild.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyRequireBuild.md index 5874467..77bf3e0 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyRequireBuild.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyRequireBuild.md @@ -20,6 +20,8 @@ worden samengevoegd in de standaardbranch. Deze regel valideert niet dat de buil of CI-pijplijn correct is geconfigureerd. Het valideert alleen dat een build of CI-pijplijn is geconfigureerd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de branch policy in te schakelen om een build of CI-pijplijn te vereisen. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyResetVotes.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyResetVotes.md index b96bf5c..36546e7 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyResetVotes.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.BranchPolicyResetVotes.md @@ -21,6 +21,8 @@ resetten wanneer wijzigingen worden bijgewerkt. Dit zal helpen om ervoor te zorgen dat de code in de standaard branch van hoge kwaliteit is en dat de Git workflow van het team wordt gevolgd. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de branch policy te configureren om stemmen te resetten wanneer diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md index 31bee4d..bfe2b2c 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md @@ -17,6 +17,8 @@ GitHub Advanced Security biedt een reeks beveiligingsfuncties voor Azure DevOps repositories. Deze regel controleert of GitHub Advanced Security is geconfigureerd om pushes te blokkeren die niet voldoen aan de beveiligingseisen. +Mininum TokenType: `FullAccess` + ## RECOMMENDATION Overweeg om GitHub Advanced Security te configureren om pushes te blokkeren die niet diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md index 30a1050..c5c2346 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md @@ -24,6 +24,7 @@ GitHub Advanced Security voegt de volgende functies toe: - Secret scannen repo scannen - Afhankelijkheid scannen +Mininum TokenType: `FullAccess` ## RECOMMENDATION diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.HasBranchPolicy.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.HasBranchPolicy.md index 7ff7867..0d38811 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.HasBranchPolicy.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.HasBranchPolicy.md @@ -17,6 +17,8 @@ workflow van het team bepalen. Branch policies kunnen de codekwaliteit en de normen voor wijzigingsbeheer van uw team afdwingen. Ze kunnen uw team ook helpen om bugs eerder in de ontwikkelingscyclus te vinden en op te lossen. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een branch policy toe te voegen aan de standaard branch van uw diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.InheritedPermissions.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.InheritedPermissions.md index 88e150f..4984364 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.InheritedPermissions.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.InheritedPermissions.md @@ -15,6 +15,8 @@ Repository permissies mogen niet worden geërfd van het project. Repository permissies mogen niet worden geërfd van het project. Geërfde permissies kunnen leiden tot onverwachte toegang tot repositories en branches. +Mininum TokenType: `FineGrained` + ## RECOMMENDATION Overweeg om geërfde permissies uit de repository te verwijderen en expliciet diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.License.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.License.md index b18814f..e62d326 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.License.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.License.md @@ -20,6 +20,8 @@ source software te delen. Om je project te licenseren, maak je een LICENSE bestand in de repository root. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een LICENSE bestand in de repository root te maken. \ No newline at end of file diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.Readme.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.Readme.md index e77c759..de5cb90 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.Readme.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Repos.Readme.md @@ -17,6 +17,8 @@ Als je een repository maakt, moet je een README.md bestand maken om het project uit te leggen en informatie te verstrekken. Het README.md bestand wordt automatisch weergegeven op de repository homepage. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een README.md bestand in de repository root te maken. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ClassicAzure.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ClassicAzure.md index 0bab903..df7719f 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ClassicAzure.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ClassicAzure.md @@ -20,6 +20,8 @@ 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. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een serviceverbindingstype te gebruiken dat kan worden geschaald naar een diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Description.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Description.md index c7316fd..9ef9751 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Description.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Description.md @@ -17,6 +17,8 @@ Het toevoegen van een beschrijving aan een service connection zal gebruikers helpen het doel van de service connection te begrijpen. Dit zal gebruikers helpen te begrijpen hoe en wanneer het moet worden gebruikt. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een beschrijving toe te voegen aan de service connection. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.GitHubPAT.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.GitHubPAT.md index cdbd6d5..7e43e4e 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.GitHubPAT.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.GitHubPAT.md @@ -20,6 +20,8 @@ getraceerd naar de specifieke verbinding vanuit Azure DevOps. Dit betekent dat e gebruiker met toegang tot de serviceverbinding zich kan voordoen als de gebruiker die de serviceverbinding heeft gemaakt. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg een oauth-gebaseerde serviceverbinding te gebruiken. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md index d329713..d45a65d 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md @@ -16,6 +16,8 @@ Een productieserviceverbinding moet beperkt zijn in de branches waarin deze kan niet-productiebranch. Deze regel controleert of de serviceverbinding is beperkt tot een productiebranch. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om de serviceverbinding te beperken tot een productiebranch. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md index 169d399..d9ba232 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionCheckProtection.md @@ -22,6 +22,8 @@ resources. Bijvoorbeeld, een service connection die is beperkt tot productie zou moeten worden beschermd met een check die een minimum aantal reviewers vereist of een specifieke CI pipeline moet doorlopen. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een service connection die is beperkt tot productie te diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md index 2ae053c..7966574 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.ProductionHumanApproval.md @@ -20,6 +20,8 @@ deze wordt gebruikt voor het wijzigen van resources in andere omgevingen. Bijvoorbeeld, een service connection die is beperkt tot productie zou moeten worden beschermd met een check die een minimum aantal reviewers vereist. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een service connection die is beperkt tot productie te diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Scope.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Scope.md index a64d7d5..c50c6a3 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Scope.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.Scope.md @@ -22,6 +22,8 @@ aangebracht in de productie resources of daarbuiten. Normaal gesproken is het niet wenselijk om een service connection te hebben met toegang tot alle resource groups in een abonnement. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een service connection die is beperkt tot productie te beperken diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md index 27e8e72..bf9b8e9 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md @@ -18,6 +18,8 @@ naar Azure services in plaats van een service principal beheerd door Azure DevOps. Dit is veiliger omdat de service principal niet wordt opgeslagen in Azure DevOps. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om Workload Identity Federation te gebruiken voor je service connections. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.Description.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.Description.md index 35b8369..31dc4eb 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.Description.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.Description.md @@ -17,6 +17,8 @@ Het toevoegen van een beschrijving aan een variabele groep zal gebruikers helpen het doel van de variabele groep te begrijpen. Dit zal gebruikers helpen te begrijpen hoe en wanneer het moet worden gebruikt. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om een beschrijving toe te voegen aan de variabele groep. diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md index 2b01c15..cbb457f 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoKeyVaultNoSecrets.md @@ -18,6 +18,8 @@ gekoppeld aan een key vault. Dit komt omdat de geheimen in platte tekst worden opgeslagen in de variabele groep en kunnen worden bekeken door iedereen met toegang tot de variabele groep. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om alle geheimen uit de variabele groep te verwijderen of te diff --git a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md index 049aa4e..5b4ccbc 100644 --- a/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md +++ b/src/PSRule.Rules.AzureDevOps/nl/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md @@ -17,6 +17,8 @@ worden opgeslagen in Azure Key Vault en worden gerefereerd in de variabele groep voorkomt dat het geheim wordt blootgesteld in de build logs. Als het geheim in platte tekst wordt opgeslagen, wordt het blootgesteld in de build logs. +Mininum TokenType: `ReadOnly` + ## RECOMMENDATION Overweeg om geheimen op te slaan in Azure Key Vault en ze te refereren in de variabele diff --git a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Core.Rule.ps1 b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Core.Rule.ps1 index 015cb43..be99fa2 100644 --- a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Core.Rule.ps1 +++ b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Core.Rule.ps1 @@ -21,6 +21,7 @@ Rule 'Azure.DevOps.Pipelines.Core.InheritedPermissions' ` -Ref 'ADO-PL-002' ` -Type 'Azure.DevOps.Pipeline' ` -Tag @{ release = 'GA'} ` + -If { "Acls" -in $TargetObject.psobject.Properties.Name } ` -Level Warning { # Description "Pipelines should not have inherited permissions" Reason "The pipeline is using inherited permissions" diff --git a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Releases.Rule.ps1 b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Releases.Rule.ps1 index 9b58b61..7768114 100644 --- a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Releases.Rule.ps1 +++ b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Pipelines.Releases.Rule.ps1 @@ -42,6 +42,7 @@ Rule 'Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions' ` -Ref 'ADO-RD-003' ` -Type 'Azure.DevOps.Pipelines.Releases.Definition' ` -Tag @{ release = 'GA'} ` + -If { "Acls" -in $TargetObject.psobject.Properties.Name } ` -Level Error { # Description 'Release pipeline should not inherit permissions from the project.' Reason 'The release pipeline inherits permissions from the project.' diff --git a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Repos.Rule.ps1 b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Repos.Rule.ps1 index de6006c..97d3f42 100644 --- a/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Repos.Rule.ps1 +++ b/src/PSRule.Rules.AzureDevOps/rules/AzureDevOps.Repos.Rule.ps1 @@ -142,6 +142,7 @@ Rule 'Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled' ` -Ref 'ADO-RP-010' ` -Type 'Azure.DevOps.Repo' ` -Tag @{ release = 'GA'} ` + -If { "Ghas" -in $TargetObject.psobject.Properties.Name } ` -Level Warning { # Description 'GitHub Advanced Security should be enabled' Reason 'GitHub Advanced Security is not enabled' @@ -156,6 +157,7 @@ Rule 'Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes' ` -Ref 'ADO-RP-011' ` -Type 'Azure.DevOps.Repo' ` -Tag @{ release = 'GA'} ` + -If { "Ghas" -in $TargetObject.psobject.Properties.Name } ` -Level Warning { # Description 'GitHub Advanced Security should block pushes' Reason 'GitHub Advanced Security does not block pushes' @@ -170,6 +172,7 @@ Rule 'Azure.DevOps.Repos.InheritedPermissions' ` -Ref 'ADO-RP-012' ` -Type 'Azure.DevOps.Repo' ` -Tag @{ release = 'GA'} ` + -If { "Acls" -in $TargetObject.psobject.Properties.Name } ` -Level Warning { # Description 'Repository should not have inherited permissions' Reason 'Repository has inherited permissions' diff --git a/tests/PSRule.Rules.AzureDevOps.Tests.ps1 b/tests/PSRule.Rules.AzureDevOps.Tests.ps1 index 72668a5..994d689 100644 --- a/tests/PSRule.Rules.AzureDevOps.Tests.ps1 +++ b/tests/PSRule.Rules.AzureDevOps.Tests.ps1 @@ -53,6 +53,42 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context "When running Get-AzDevOpsProjects with a ReadOnly PAT" { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $projects = Get-AzDevOpsProjects -PAT $PAT -Organization $Organization -TokenType ReadOnly + } + + It 'Should return a list of projects' { + $projects | Should -Not -BeNullOrEmpty + $projects[0] | Should -BeOfType [PSCustomObject] + } + + It 'Should return a list of projects with a name' { + $projects[0].name | Should -Not -BeNullOrEmpty + $projects[0].name | Should -BeOfType [System.String] + } + } + + Context "When running Get-AzDevOpsProjects with a FineGrained PAT" { + BeforeAll { + $PAT = $env:ADO_PAT_FINEGRAINED + $Organization = $env:ADO_ORGANIZATION + $projects = Get-AzDevOpsProjects -PAT $PAT -Organization $Organization -TokenType FineGrained + } + + It 'Should return a list of projects' { + $projects | Should -Not -BeNullOrEmpty + $projects[0] | Should -BeOfType [PSCustomObject] + } + + It 'Should return a list of projects with a name' { + $projects[0].name | Should -Not -BeNullOrEmpty + $projects[0].name | Should -BeOfType [System.String] + } + } + Context "When running Get-AzDevOpsRepos" { BeforeAll { $PAT = $env:ADO_PAT @@ -151,11 +187,31 @@ Describe 'PSRule.Rules.AzureDevOps' { Context 'When running Get-AzDevOpsRepositoryAcls with wrong parameters' { It 'Should throw an 404 error when all parameters are wrong' { - { Get-AzDevOpsRepositoryAcls -PAT 'FaultyPAT' -Organization 'faulty-org' -RepositoryId 'FaultyRepositoryId' -ErrorAction Stop } | Should -Throw "Response status code does not indicate success: 404 (Not Found)." + { Get-AzDevOpsRepositoryAcls -PAT 'FaultyPAT' -ProjectId 'wrongId' -Organization 'faulty-org' -RepositoryId 'FaultyRepositoryId' -ErrorAction Stop } | Should -Throw "Response status code does not indicate success: 404 (Not Found)." } It 'Should throw a authentication error when the PAT is wrong' { - { Get-AzDevOpsRepositoryAcls -PAT 'FaultyPAT' -Organization $env:ADO_ORGANIZATION -RepositoryId 'FaultyRepositoryId' -ErrorAction Stop } | Should -Throw "Authentication failed or project not found" + { Get-AzDevOpsRepositoryAcls -PAT 'FaultyPAT' -ProjectId "1fa185aa-ce58-4732-8700-8964802ea538" -Organization $env:ADO_ORGANIZATION -RepositoryId 'FaultyRepositoryId' -ErrorAction Stop } | Should -Throw "Authentication failed or project not found" + } + } + + Context 'When running Get-AzDevOpsRepositoryAcls with a ReadOnly PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $Project = $env:ADO_PROJECT + $ProjectId = "1fa185aa-ce58-4732-8700-8964802ea538" + $repos = Get-AzDevOpsRepos -PAT $PAT -TokenType ReadOnly -Organization $Organization -Project $Project + $RepositoryId = ($repos | Where-Object { $_.name -eq 'repository-success'})[0].id + $repositoryAcls = Get-AzDevOpsRepositoryAcls -PAT $PAT -TokenType ReadOnly -Organization $Organization -RepositoryId $RepositoryId -ProjectId $ProjectId -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $repositoryAcls | Should -BeNullOrEmpty } } @@ -210,6 +266,29 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context 'When running Get-AzDevOpsRepositoryGhas with a FineGrained PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_FINEGRAINED + $Organization = $env:ADO_ORGANIZATION + $ProjectId = "1fa185aa-ce58-4732-8700-8964802ea538" + $repositoryName = 'repository-success' + $repoId = "befaaf13-3966-45c0-b481-6387e860d915" + $repoGhas = Get-AzDevOpsRepositoryGhas -PAT $PAT -TokenType FineGrained ` + -Organization $Organization ` + -ProjectId $ProjectId ` + -RepositoryId "befaaf13-3966-45c0-b481-6387e860d915" ` + -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $repoGhas | Should -BeNullOrEmpty + } + } + Context 'When running Get-AzDevOpsRepositoryPipelinePermissions' { BeforeAll { $PAT = $env:ADO_PAT @@ -490,11 +569,29 @@ Describe 'PSRule.Rules.AzureDevOps' { Context 'When running Get-AzDevOpsPipelineAcls with wrong parameters' { It 'Should throw an 404 error when all parameters are wrong' { - { Get-AzDevOpsPipelineAcls -PAT 'FaultyPAT' -Organization 'faulty-org' -PipelineId 'FaultyPipelineId' -ErrorAction Stop } | Should -Throw "Response status code does not indicate success: 404 (Not Found)." + { Get-AzDevOpsPipelineAcls -PAT 'FaultyPAT' -Organization 'faulty-org' -ProjectId 'faulty-prj-id' -PipelineId 'FaultyPipelineId' -ErrorAction Stop } | Should -Throw "Response status code does not indicate success: 404 (Not Found)." } It 'Should throw a authentication error when the PAT is wrong' { - { Get-AzDevOpsPipelineAcls -PAT 'FaultyPAT' -Organization $env:ADO_ORGANIZATION -PipelineId 'FaultyPipelineId' -ErrorAction Stop } | Should -Throw "Authentication failed or project not found" + { Get-AzDevOpsPipelineAcls -PAT 'FaultyPAT' -Organization $env:ADO_ORGANIZATION -ProjectId "1fa185aa-ce58-4732-8700-8964802ea538" -PipelineId 'FaultyPipelineId' -ErrorAction Stop } | Should -Throw "Authentication failed or project not found" + } + } + + Context 'When running Get-AzDevOpsPipelineAcls with a ReadOnly PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $pipelineId = 7 + $ProjectId = "1fa185aa-ce58-4732-8700-8964802ea538" + $pipelineAcls = Get-AzDevOpsPipelineAcls -PAT $PAT -TokenType ReadOnly -Organization $Organization -PipelineId $PipelineId -ProjectId $ProjectId -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $pipelineAcls | Should -BeNullOrEmpty } } @@ -662,6 +759,24 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context "When running Get-AzDevOpsReleaseDefinitionAcls with a ReadOnly PAT" { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $releaseDefinitionId = 2 + $ProjectId = "1fa185aa-ce58-4732-8700-8964802ea538" + $releaseDefinitionAcls = Get-AzDevOpsReleaseDefinitionAcls -PAT $PAT -TokenType ReadOnly -Organization $Organization -ReleaseDefinitionId $releaseDefinitionId -ProjectId $ProjectId -Folder '' -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $releaseDefinitionAcls | Should -BeNullOrEmpty + } + } + Context "When running Export-AzDevOpsReleaseDefinitions" { It 'Should export all JSON files with an ObjectType property set as Azure.DevOps.Releases.Definition' { $PAT = $env:ADO_PAT @@ -720,6 +835,23 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context 'When running Get-AzDevOpsEnvironments with a ReadOnly PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $Project = $env:ADO_PROJECT + $environments = Get-AzDevOpsEnvironments -PAT $PAT -TokenType ReadOnly -Organization $Organization -Project $Project -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $environments | Should -BeNullOrEmpty + } + } + Context "When running Get-AzDevOpsEnvironmentChecks on a protected environment" { BeforeAll { $PAT = $env:ADO_PAT @@ -763,6 +895,25 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context 'When running Get-AzDevOpsEnvironmentChecks with a ReadOnly PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $Project = $env:ADO_PROJECT + $environments = Get-AzDevOpsEnvironments -PAT $PAT -TokenType ReadOnly -Organization $Organization -Project $Project + $environmentId = 7 + $environmentChecks = Get-AzDevOpsEnvironmentChecks -PAT $PAT -TokenType ReadOnly -Organization $Organization -Project $Project -Environment $environmentId -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + + It 'Should return null or empty' { + $environmentChecks | Should -BeNullOrEmpty + } + } + Context "When running Export-AzDevOpsEnvironmentChecks" { It 'Should export all JSON files with an ObjectType property set as Azure.DevOps.Pipelines.Environment' { $PAT = $env:ADO_PAT @@ -778,7 +929,7 @@ Describe 'PSRule.Rules.AzureDevOps' { } } - Context 'When running Export-AzDevOpsRuleData' { + Context 'When running Export-AzDevOpsRuleData with a Full Access PAT' { It 'Should export all JSON files' { $PAT = $env:ADO_PAT $Organization = $env:ADO_ORGANIZATION @@ -790,6 +941,34 @@ Describe 'PSRule.Rules.AzureDevOps' { } } + Context 'When running Export-AzDevOpsRuleData with a ReadOnly PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_READONLY + $Organization = $env:ADO_ORGANIZATION + $Project = $env:ADO_PROJECT + $OutputPath = $env:ADO_EXPORT_DIR + Export-AzDevOpsRuleData -PAT $PAT -TokenType ReadOnly -Organization $Organization -Project $Project -OutputPath $OutputPath -WarningVariable warning + } + + It "Should write warnings" { + $warning | Should -Not -BeNullOrEmpty + } + } + + Context 'When running Export-AzDevOpsRuleData with a FineGrained PAT' { + BeforeAll { + $PAT = $env:ADO_PAT_FINEGRAINED + $Organization = $env:ADO_ORGANIZATION + $Project = $env:ADO_PROJECT + $OutputPath = $env:ADO_EXPORT_DIR + Export-AzDevOpsRuleData -PAT $PAT -TokenType FineGrained -Organization $Organization -Project $Project -OutputPath $OutputPath -WarningVariable warning + } + + It "Should write a warning" { + $warning | Should -Not -BeNullOrEmpty + } + } + Context 'When running Export-AzDevOpsOrganizationRuleData' { It 'Should export all JSON files' { diff --git a/tests/Rules.Tests.ps1 b/tests/Rules.Tests.ps1 index 4750e7d..c08108d 100644 --- a/tests/Rules.Tests.ps1 +++ b/tests/Rules.Tests.ps1 @@ -26,6 +26,22 @@ BeforeAll { Export-AzDevOpsRuleData -PAT $env:ADO_PAT -Project $env:ADO_PROJECT -Organization $env:ADO_ORGANIZATION -OutputPath $outPath $ruleResult = Invoke-PSRule -InputPath "$($outPath)/" -Module PSRule.Rules.AzureDevOps -Format Detect -Culture en $noExtraLicenseBaselineResult = Invoke-PSRule -InputPath "$($outPath)/" -Module PSRule.Rules.AzureDevOps -Format Detect -Culture en -Baseline Baseline.NoExtraLicense + + # Create a temporary test output folder for tests with the ReadOnly TokenType + $outPathReadOnly = New-Item -Path (Join-Path -Path $here -ChildPath 'outReadOnly') -ItemType Directory -Force; + $outPathReadOnly = $outPathReadOnly.FullName; + + # Export all Azure DevOps rule data for project 'psrule-fail-project' to ReadOnly output folder + Export-AzDevOpsRuleData -PAT $env:ADO_PAT_READONLY -TokenType ReadOnly -Project $env:ADO_PROJECT -Organization $env:ADO_ORGANIZATION -OutputPath $outPathReadOnly + $ruleResultReadOnly = Invoke-PSRule -InputPath "$($outPathReadOnly)/" -Module PSRule.Rules.AzureDevOps -Format Detect -Culture en + + # Create a temporary test output folder for tests with the FineGrained TokenType + $outPathFineGrained = New-Item -Path (Join-Path -Path $here -ChildPath 'outFineGrained') -ItemType Directory -Force; + $outPathFineGrained = $outPathFineGrained.FullName; + + # Export all Azure DevOps rule data for project 'psrule-fail-project' to FineGrained output folder + Export-AzDevOpsRuleData -PAT $env:ADO_PAT_FINEGRAINED -TokenType FineGrained -Project $env:ADO_PROJECT -Organization $env:ADO_ORGANIZATION -OutputPath $outPathFineGrained + $ruleResultFineGrained = Invoke-PSRule -InputPath "$($outPathFineGrained)/" -Module PSRule.Rules.AzureDevOps -Format Detect -Culture en } Describe 'AzureDevOps ' { @@ -62,6 +78,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should have the same results with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.Description' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.Description' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should have the same results with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.Description' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.Description' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Tasks.VariableGroup.Description.md'); $fileExists | Should -Be $true; @@ -81,6 +117,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should have the same results with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should have the same results with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Tasks.VariableGroup.NoPlainTextSecrets.md'); $fileExists | Should -Be $true; @@ -100,6 +156,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should have the same results with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest' -and $_.Outcome -eq 'Fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest' -and $_.Outcome -eq 'Pass' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should have the same results with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest' -and $_.Outcome -eq 'Fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest' -and $_.Outcome -eq 'Pass' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.PipelineYaml.AgentPoolVersionNotLatest.md'); $fileExists | Should -Be $true; @@ -119,6 +195,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should have the same results with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName' -and $_.Outcome -eq 'Fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName' -and $_.Outcome -eq 'Pass' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should have the same results with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName' -and $_.Outcome -eq 'Fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName' -and $_.Outcome -eq 'Pass' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.PipelineYaml.StepDisplayName.md'); $fileExists | Should -Be $true; @@ -138,6 +234,24 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be in the output for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionCheckProtection' -and $_.TargetName -match 'fail' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionCheckProtection' -and $_.TargetName -match 'success' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should have the same result as default for FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionCheckProtection' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionCheckProtection' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Environments.ProductionCheckProtection.md'); $fileExists | Should -Be $true; @@ -157,6 +271,24 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be in the output for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionHumanApproval' -and $_.TargetName -match 'fail' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionHumanApproval' -and $_.TargetName -match 'success' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should have the same result as default for FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionHumanApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionHumanApproval' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Environments.ProductionHumanApproval.md'); $fileExists | Should -Be $true; @@ -176,6 +308,24 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be in the output for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.Description' -and $_.TargetName -match 'fail' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.Description' -and $_.TargetName -match 'success' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should have the same result as default for FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.Description' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.Description' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Environments.Description.md'); $fileExists | Should -Be $true; @@ -195,6 +345,24 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be in the output for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionBranchLimit' -and $_.TargetName -match 'fail' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionBranchLimit' -and $_.TargetName -match 'success' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should have the same result as default for FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionBranchLimit' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Environments.ProductionBranchLimit' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Environments.ProductionBranchLimit.md'); $fileExists | Should -Be $true; @@ -204,6 +372,7 @@ Describe 'AzureDevOps ' { Context 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' { It 'Should fail for targets named fail' { $ruleHits = @($ruleResult | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; $ruleHits.Count | Should -Be 2; } @@ -213,6 +382,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 2; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 2; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.UseYamlDefinition' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Core.UseYamlDefinition.md'); $fileExists | Should -Be $true; @@ -222,6 +411,7 @@ Describe 'AzureDevOps ' { Context 'Azure.DevOps.Pipelines.Core.InheritedPermissions' { It 'Should fail for targets named fail' { $ruleHits = @($ruleResult | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.InheritedPermissions' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; $ruleHits.Count | Should -Be 2; } @@ -231,6 +421,21 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be present for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.InheritedPermissions' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.InheritedPermissions' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 2; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.InheritedPermissions' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Core.InheritedPermissions.md'); $fileExists | Should -Be $true; @@ -240,6 +445,19 @@ Describe 'AzureDevOps ' { Context 'Azure.DevOps.Pipelines.Core.NoPlainTextSecrets' { It 'Should fail for targets named fail' { $ruleHits = @($ruleResult | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Core.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; $ruleHits.Count | Should -Be 1; } @@ -256,6 +474,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.LimitSetVariablesAtQueueTime.md'); $fileExists | Should -Be $true; @@ -269,6 +499,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScope.md'); $fileExists | Should -Be $true; @@ -282,6 +524,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForReleasePipelines.md'); $fileExists | Should -Be $true; @@ -295,6 +549,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.LimitJobAuthorizationScopeForYamlPipelines.md'); $fileExists | Should -Be $true; @@ -308,6 +574,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.RequireCommentForPullRequestFromFork.md'); $fileExists | Should -Be $true; @@ -321,6 +599,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.RestrictSecretsForPullRequestFromFork.md'); $fileExists | Should -Be $true; @@ -334,6 +624,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Settings.SanitizeShellTaskArguments.md'); $fileExists | Should -Be $true; @@ -353,6 +655,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval' -and $_.TargetName -match 'Success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval' -and $_.TargetName -match 'Success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Releases.Definition.ProductionApproval.md'); $fileExists | Should -Be $true; @@ -372,6 +694,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same for ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.SelfApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.SelfApproval' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same for the FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.SelfApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.SelfApproval' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Releases.Definition.SelfApproval.md'); $fileExists | Should -Be $true; @@ -391,6 +733,21 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be present with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should be the same as default with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Releases.Definition.InheritedPermissions.md'); $fileExists | Should -Be $true; @@ -410,6 +767,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Pipelines.Releases.Definition.NoPlainTextSecrets.md'); $fileExists | Should -Be $true; @@ -429,6 +806,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.HasBranchPolicy' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.HasBranchPolicy' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.HasBranchPolicy' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.HasBranchPolicy' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.HasBranchPolicy.md'); $fileExists | Should -Be $true; @@ -448,6 +845,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyIsEnabled' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyIsEnabled' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyIsEnabled' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyIsEnabled' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyIsEnabled.md'); $fileExists | Should -Be $true; @@ -467,6 +884,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMinimumReviewers' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMinimumReviewers' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMinimumReviewers' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMinimumReviewers' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyMinimumReviewers.md'); $fileExists | Should -Be $true; @@ -486,6 +923,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyAllowSelfApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyAllowSelfApproval' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyAllowSelfApproval' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyAllowSelfApproval' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyAllowSelfApproval.md'); $fileExists | Should -Be $true; @@ -505,6 +962,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyResetVotes' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyResetVotes' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyResetVotes' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyResetVotes' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyResetVotes.md'); $fileExists | Should -Be $true; @@ -524,6 +1001,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.Readme' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.Readme' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.Readme' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.Readme' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.Readme.md'); $fileExists | Should -Be $true; @@ -543,6 +1040,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.License' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.License' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.License' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.License' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.License.md'); $fileExists | Should -Be $true; @@ -562,6 +1079,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyEnforceLinkedWorkItems.md'); $fileExists | Should -Be $true; @@ -581,6 +1118,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyCommentResolution' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyCommentResolution' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyCommentResolution' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyCommentResolution' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyCommentResolution.md'); $fileExists | Should -Be $true; @@ -600,6 +1157,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMergeStrategy' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMergeStrategy' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMergeStrategy' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyMergeStrategy' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyMergeStrategy.md'); $fileExists | Should -Be $true; @@ -624,6 +1201,16 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 0; } + It 'Should not be present with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should not be present with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled' }) + $ruleHits.Count | Should -Be 0; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.GitHubAdvancedSecurityEnabled.md'); $fileExists | Should -Be $true; @@ -648,6 +1235,16 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 0; } + It 'Should not be present with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should not be present with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes' }) + $ruleHits.Count | Should -Be 0; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.GitHubAdvancedSecurityBlockPushes.md'); $fileExists | Should -Be $true; @@ -667,6 +1264,21 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should not be present with the ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.InheritedPermissions' }) + $ruleHits.Count | Should -Be 0; + } + + It 'Should be the same as default with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.InheritedPermissions' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.InheritedPermissions' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.InheritedPermissions.md'); $fileExists | Should -Be $true; @@ -686,6 +1298,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyRequireBuild' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyRequireBuild' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyRequireBuild' -and $_.TargetName -match 'fail' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.Repos.BranchPolicyRequireBuild' -and $_.TargetName -match 'success' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.Repos.BranchPolicyRequireBuild.md'); $fileExists | Should -Be $true; @@ -705,6 +1337,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Description' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 3; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Description' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Description' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 3; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Description' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.Description.md'); $fileExists | Should -Be $true; @@ -724,6 +1376,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Scope' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Scope' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Scope' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.Scope' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.Scope.md'); $fileExists | Should -Be $true; @@ -743,6 +1415,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.WorkloadIdentityFederation' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.WorkloadIdentityFederation' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.WorkloadIdentityFederation' -and $_.TargetName -like '*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.WorkloadIdentityFederation' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an English markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.WorkloadIdentityFederation.md'); $fileExists | Should -Be $true; @@ -761,6 +1453,24 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ProductionBranchLimit' -and $_.TargetName -like '*fail*' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ProductionBranchLimit' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ProductionBranchLimit' -and $_.TargetName -like '*fail*' }) + $ruleHits.Count | Should -Be 0; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ProductionBranchLimit' -and $_.TargetName -like '*success*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.ProductionBranchLimit.md'); $fileExists | Should -Be $true; @@ -780,6 +1490,26 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 2; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ClassicAzure' -and $_.TargetName -like '*Classic*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ClassicAzure' -and $_.TargetName -notlike '*Classic*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 2; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ClassicAzure' -and $_.TargetName -like '*Classic*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.ClassicAzure' -and $_.TargetName -notlike '*Classic*' }) + $ruleHits[0].Outcome | Should -Be 'Pass'; + $ruleHits.Count | Should -Be 2; + } + It 'Should have a markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.ClassicAzure.md'); $fileExists | Should -Be $true; @@ -793,6 +1523,18 @@ Describe 'AzureDevOps ' { $ruleHits.Count | Should -Be 1; } + It 'Should be the same with a ReadOnly TokenType' { + $ruleHits = @($ruleResultReadOnly | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.GitHubPAT' -and $_.TargetName -like '*GitHub*PAT*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + } + + It 'Should be the same with a FineGrained TokenType' { + $ruleHits = @($ruleResultFineGrained | Where-Object { $_.RuleName -eq 'Azure.DevOps.ServiceConnections.GitHubPAT' -and $_.TargetName -like '*GitHub*PAT*fail*' }) + $ruleHits[0].Outcome | Should -Be 'Fail'; + $ruleHits.Count | Should -Be 1; + } + It 'Should have an english markdown help file' { $fileExists = Test-Path -Path (Join-Path -Path $ourModule -ChildPath 'en/Azure.DevOps.ServiceConnections.GitHubPAT.md'); $fileExists | Should -Be $true;