Add Pipelines (#8)
This commit is contained in:
Родитель
fa2f1bcd87
Коммит
ed9da0c38a
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"bewhite.psrule-vscode-preview",
|
||||
"ms-azuretools.vscode-bicep"
|
||||
"ms-azuretools.vscode-bicep",
|
||||
"ms-azure-devops.azure-pipelines"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"**/.pipelines/**/*.yaml": "azure-pipelines",
|
||||
"**/pipelines/ado/**/*.yaml": "azure-pipelines"
|
||||
"**/pipelines/**/*.yaml": "azure-pipelines"
|
||||
},
|
||||
"files.insertFinalNewline": true,
|
||||
"editor.tabSize": 2,
|
||||
|
|
|
@ -68,7 +68,6 @@ or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any addi
|
|||
## Maintainers
|
||||
|
||||
- [Bernie White](https://github.com/BernieWhite)
|
||||
- [Sam Bell](https://github.com/ms-sambell)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
# Unified pipeline
|
||||
|
||||
The unified pipeline is a pipeline template that can be used to create a governed pipeline.
|
||||
Using this template, you can accelerate adoption of governed pipelines used by your organization to deploy to Azure.
|
||||
The template is designed to be used with the [Security through templates][1] feature of Azure Pipelines.
|
||||
|
||||
The unified pipeline is not intended to be used directly.
|
||||
|
||||
While the template provides a default configuration, it can be customized to meet the needs of your organization.
|
||||
For example, enforce third-party DevSecOps tools, or add custom stages to the pipeline.
|
||||
|
||||
[1]: https://learn.microsoft.com/azure/devops/pipelines/security/templates?view=azure-devops
|
||||
|
||||
## Overview
|
||||
|
||||
The unified pipeline is structured to automatically inject in stages and steps that enforce DevSecOps controls.
|
||||
The following features are included:
|
||||
|
||||
- **Prerequisites** — A stage that runs before all other stages to enforce mandatory controls.
|
||||
- This stage can be disabled or configured to not break the pipeline.
|
||||
- Custom or third-party tools can be added to this stage to enforce additional controls.
|
||||
- Several built-in tools can be enabled within this stage to enforce DevSecOps controls for Azure.
|
||||
- **Built-in tools** — Built-in tools that can be used to enforce DevSecOps controls minimizes integration effort.
|
||||
These tools include:
|
||||
- Microsoft Defender for DevOps.
|
||||
- Microsoft PSRule for Azure.
|
||||
- **Customizable stages** — The pipeline can be customized to add additional stages by consuming pipelines.
|
||||
This allows developers and DevOps engineers to develop pipelines to meet their needs.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the unified pipeline, define your governed pipeline YAML by using it as a stage template.
|
||||
The governed pipeline you define will be extended by each consuming pipeline.
|
||||
This approach allows you to define mandatory controls that can not be overriden by consuming pipelines.
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
# Settings are exposed to consuming pipelines to allow customization of options.
|
||||
- name: settings
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Stages are exposed to consuming pipelines to allow customization of stages.
|
||||
- name: stages
|
||||
type: stageList
|
||||
default: []
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: AzureGovernedPipelines
|
||||
type: github
|
||||
name: Azure/AzureGovernedPipelines
|
||||
ref: refs/tags/v1.0.0
|
||||
|
||||
stages:
|
||||
- template: pipelines/unified.yml@AzureGovernedPipelines
|
||||
parameters:
|
||||
# Define mandatory options here.
|
||||
global: {}
|
||||
|
||||
# Define option defaults here.
|
||||
defaults: {}
|
||||
|
||||
# Allow consuming pipelines to override.
|
||||
settings: ${{ parameters.settings }}
|
||||
|
||||
# Allow consuming pipelines to customize stages.
|
||||
stages: ${{ parameters.stages }}
|
||||
```
|
||||
|
||||
Continue reading for more information on the avilaible parameters for customization.
|
||||
|
||||
## Parameters
|
||||
|
||||
The unified pipeline supports the following parameters for customization.
|
||||
|
||||
### `global`
|
||||
|
||||
Allows configuration of options within the governed pipeline that are enforced to all pipelines.
|
||||
Options configured here will override options specified in `defaults` and `settings`.
|
||||
|
||||
To default a configuration option but allow it to be overridden, specify the option in `defaults` instead.
|
||||
|
||||
For a list of configuration options see [Options](#options).
|
||||
|
||||
### `defaults`
|
||||
|
||||
Allows configuration of option defaults for the governed pipeline.
|
||||
Options configured here will be the default for all consuming pipelines.
|
||||
Consuming pipelines can override the default by specifying the option in `settings`.
|
||||
|
||||
Any options specified here will always be overriden by options specified in `global`.
|
||||
|
||||
For a list of configuration options see [Options](#options).
|
||||
|
||||
### `settings`
|
||||
|
||||
Allows configuration of options within the governed pipeline by consuming pipelines.
|
||||
Options configured here can be overriden by consuming pipelines.
|
||||
For example, you may want to allow a pipeline turn on or off a feature.
|
||||
|
||||
When not specified, the effective configuration will be inherited from `defaults` unless the option is specified in `global`.
|
||||
|
||||
For a list of configuration options see [Options](#options).
|
||||
|
||||
When defining your governed pipeline, expose this parameter to allow consuming pipelines to override options.
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
# Settings are exposed to consuming pipelines to allow customization of options.
|
||||
- name: settings
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Stages are exposed to consuming pipelines to allow customization of stages.
|
||||
- name: stages
|
||||
type: stageList
|
||||
default: []
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: AzureGovernedPipelines
|
||||
type: github
|
||||
name: Azure/AzureGovernedPipelines
|
||||
ref: refs/tags/v1.0.0
|
||||
|
||||
extends:
|
||||
- template: pipelines/unified.yml@AzureGovernedPipelines
|
||||
parameters:
|
||||
# Define mandatory options here.
|
||||
global: {}
|
||||
|
||||
# Define option defaults here.
|
||||
defaults: {}
|
||||
|
||||
# Allow consuming pipelines to override.
|
||||
settings: ${{ parameters.settings }}
|
||||
|
||||
# Allow consuming pipelines to customize stages.
|
||||
stages: ${{ parameters.stages }}
|
||||
```
|
||||
|
||||
### `stages`
|
||||
|
||||
Allows consuming pipelines to add additional stages to the pipeline.
|
||||
To configure pipeline stages, the consuming pipeline will specify a list of stages to add.
|
||||
|
||||
For example, to add a stage named `build`:
|
||||
|
||||
```yaml
|
||||
extends:
|
||||
template: your-template.yml@GovernedPipelines
|
||||
parameters:
|
||||
stages:
|
||||
- stage: build_stage
|
||||
displayName: Build
|
||||
jobs:
|
||||
- job: build_job
|
||||
displayName: Build
|
||||
steps:
|
||||
- script: echo Hello, world!
|
||||
displayName: 'Run an example script'
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
The following options can be configured for customization of the governed pipeline.
|
||||
These options can be set by configuring `global`, or `defaults`.
|
||||
Consuming pipelines can override options specified in `defaults` by configuring the options in `settings`.
|
||||
|
||||
If the option is not set, the effective configuration will be inherited from the pipeline defaults described in this section.
|
||||
|
||||
```yaml
|
||||
prereqs:
|
||||
enabled: boolean
|
||||
break: boolean
|
||||
|
||||
tools:
|
||||
psrule:
|
||||
enabled: boolean
|
||||
modules: string
|
||||
minimumVersion: string
|
||||
```
|
||||
|
||||
For example, setting a default value for `tools.psrule.enabled`:
|
||||
|
||||
```yaml
|
||||
extends:
|
||||
template: your-template.yml@GovernedPipelines
|
||||
parameters:
|
||||
# Customize the pipeline here by specifying parameters
|
||||
stages: []
|
||||
defaults:
|
||||
tools:
|
||||
psrule:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
### `prereqs.enabled`
|
||||
|
||||
Determines if the prerequisite (_Prereqs_) stage is enabled.
|
||||
By default, this stage is enabled and will run before all other stages.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
prereqs:
|
||||
enabled: boolean
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
prereqs:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```yaml
|
||||
global:
|
||||
prereqs:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
### `prereqs.break`
|
||||
|
||||
Determines if a prerequisite (_Prereqs_) stage failure breaks the pipeline.
|
||||
By default, a failure in the prereqs stage will halt the pipeline and fail.
|
||||
Subsequent stages will not be run.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
prereqs:
|
||||
break: boolean
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
prereqs:
|
||||
break: true
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```yaml
|
||||
global:
|
||||
prereqs:
|
||||
break: false
|
||||
```
|
||||
|
||||
### `tools.psrule.enabled`
|
||||
|
||||
Enables or disables scanning of the source repository using PSRule.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
enabled: boolean
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```yaml
|
||||
global:
|
||||
tools:
|
||||
psrule:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
### `tools.psrule.modules`
|
||||
|
||||
Configures the PSRule modules that will be used to during scanning.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
modules: string
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
modules: false
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```yaml
|
||||
global:
|
||||
tools:
|
||||
psrule:
|
||||
modules: 'PSRule.Rules.Azure'
|
||||
```
|
||||
|
||||
### `tools.psrule.minimumVersion`
|
||||
|
||||
Configures the minimum version of PSRule that may be used.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
minimumVersion: string
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
psrule:
|
||||
minimumVersion: 2.7.0
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```yaml
|
||||
global:
|
||||
tools:
|
||||
psrule:
|
||||
minimumVersion: 2.7.0
|
||||
```
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Azure DevOps test deployment pipeline
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This pipeline consumes the standard governed pipeline.
|
||||
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
parameters:
|
||||
|
||||
# Determine if the deployment is tested with what if instead
|
||||
- name: whatif
|
||||
displayName: What If
|
||||
type: 'boolean'
|
||||
default: false
|
||||
|
||||
extends:
|
||||
template: ../offical.yaml
|
||||
parameters:
|
||||
azure:
|
||||
|
||||
# Default to true if not specified
|
||||
whatif: ${{ parameters.whatif }}
|
||||
|
||||
jobs:
|
||||
|
||||
- path: nnn/deploy.bicep
|
||||
name: ''
|
|
@ -0,0 +1,46 @@
|
|||
#
|
||||
# Azure DevOps pipeline template
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This standard template tests Bicep code.
|
||||
|
||||
parameters:
|
||||
|
||||
# The name of the baseline to use for tests
|
||||
- name: baseline
|
||||
type: string
|
||||
default: 'latest'
|
||||
|
||||
# The agent image to used for the job
|
||||
- name: vmImage
|
||||
type: 'string'
|
||||
default: 'ubuntu-latest'
|
||||
|
||||
jobs:
|
||||
- job: 'test_bicep_modules'
|
||||
displayName: 'Test modules'
|
||||
pool:
|
||||
vmImage: ${{ parameters.vmImage }}
|
||||
steps:
|
||||
|
||||
# Analyze Azure resources using PSRule for Azure
|
||||
- task: ps-rule-assert@2
|
||||
displayName: Analyze Azure Bicep modules
|
||||
inputs:
|
||||
modules: 'PSRule.Rules.Azure'
|
||||
outputFormat: Sarif # Save results using SARIF
|
||||
outputPath: reports/code-analysis/ps-rule-results.sarif # Save results to reports/code-analysis/ps-rule-results.sarif
|
||||
conventions: 'Monitor.LogAnalytics.Import'
|
||||
prerelease: true
|
||||
${{ if ne(parameters.baseline, 'latest') }}:
|
||||
baseline: ${{ parameters.baseline }}
|
||||
|
||||
env:
|
||||
PSRULE_CONFIGURATION_MONITOR_WORKSPACE_KEY: $(MONITORWORKSPACEKEY)
|
||||
|
||||
# Upload to scans tab
|
||||
- publish: $(System.DefaultWorkingDirectory)/reports/code-analysis/
|
||||
displayName: Upload results to scans tabs
|
||||
artifact: CodeAnalysisLogs
|
||||
condition: succeededOrFailed()
|
|
@ -0,0 +1,118 @@
|
|||
#
|
||||
# Azure DevOps pipeline template
|
||||
#
|
||||
|
||||
# Notes:
|
||||
# This standard template deploys Bicep code.
|
||||
|
||||
parameters:
|
||||
|
||||
# Name of the deployment job.
|
||||
- name: name
|
||||
type: 'string'
|
||||
|
||||
# The path to a .bicep file.
|
||||
- name: path
|
||||
type: 'string'
|
||||
|
||||
# Configures the location to run the deployment.
|
||||
- name: location
|
||||
displayName: Location
|
||||
type: 'string'
|
||||
default: 'australiaeast'
|
||||
|
||||
# The Service Connection to use.
|
||||
- name: serviceConnectionName
|
||||
type: 'string'
|
||||
|
||||
# Configures the environment to deploy to.
|
||||
- name: environment
|
||||
type: 'string'
|
||||
|
||||
# The agent image to used for the job.
|
||||
- name: vmImage
|
||||
type: 'string'
|
||||
default: 'ubuntu-latest'
|
||||
|
||||
# Determine if the deployment is tested with what if instead.
|
||||
- name: whatif
|
||||
displayName: What If
|
||||
type: 'boolean'
|
||||
default: false
|
||||
|
||||
# Configures additional retries on the deployment. This can be used by exception for certain deployments such as policy.
|
||||
- name: retry
|
||||
displayName: Retry on failure
|
||||
type: 'number'
|
||||
default: 0
|
||||
|
||||
# Configures dependencies on other jobs.
|
||||
- name: dependsOn
|
||||
displayName: Dependencies
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
# Deploy only if the conditions are met.
|
||||
- name: condition
|
||||
displayName: Conditions
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
|
||||
# Deploy to an environment.
|
||||
- ${{ if and(eq(parameters.whatif, false), or(eq(variables['Build.SourceBranchName'], 'main'), contains(parameters.path, 'deployments/nnn/'))) }}:
|
||||
|
||||
- deployment: ${{ parameters.name }}
|
||||
displayName: 'Deploy ${{ parameters.name }}'
|
||||
environment: ${{ parameters.environment }}
|
||||
pool:
|
||||
vmImage: ${{ parameters.vmImage }}
|
||||
variables:
|
||||
deployParams: '--location ''${{ parameters.location }}'''
|
||||
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
|
||||
# Deploy at subscription scope
|
||||
- task: AzureCLI@2
|
||||
displayName: 🚀 Deploy to ${{ parameters.serviceConnectionName }}
|
||||
retryCountOnTaskFailure: ${{ parameters.retry }}
|
||||
inputs:
|
||||
azureSubscription: ${{ parameters.serviceConnectionName }}
|
||||
scriptType: 'bash'
|
||||
scriptLocation: 'inlineScript'
|
||||
inlineScript: |
|
||||
az bicep install
|
||||
az deployment sub create \
|
||||
--name '${{ parameters.name }}-$(Build.BuildNumber)' \
|
||||
--template-file ${{ parameters.path }} $(deployParams)
|
||||
|
||||
# Test deployment to an environment
|
||||
- ${{ else }}:
|
||||
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: 'Checking ${{ parameters.name }}'
|
||||
pool:
|
||||
vmImage: ${{ parameters.vmImage }}
|
||||
variables:
|
||||
deployParams: '--location ''${{ parameters.location }}'''
|
||||
|
||||
steps:
|
||||
|
||||
# Deploy at subscription scope
|
||||
- task: AzureCLI@2
|
||||
displayName: 🧪 Checking deploy to ${{ parameters.serviceConnectionName }}
|
||||
|
||||
retryCountOnTaskFailure: ${{ parameters.retry }}
|
||||
inputs:
|
||||
azureSubscription: ${{ parameters.serviceConnectionName }}
|
||||
scriptType: 'bash'
|
||||
scriptLocation: 'inlineScript'
|
||||
inlineScript: |
|
||||
az bicep install
|
||||
az deployment sub create \
|
||||
--name '${{ parameters.name }}-$(Build.BuildNumber)' \
|
||||
--template-file ${{ parameters.path }} $(deployParams) --what-if
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Sample Azure DevOps governed pipeline
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This is an example pipeline to demonstrate customizing the unified pipeline.
|
||||
|
||||
parameters:
|
||||
|
||||
# Defined a global configuration for the pipeline.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defined azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
stages:
|
||||
|
||||
- template: unified.yaml
|
||||
parameters:
|
||||
global: ${{ parameters.global }}
|
||||
azure: ${{ parameters.azure }}
|
||||
defaults:
|
||||
azure:
|
||||
whatif: false
|
||||
location: 'eastus'
|
||||
offical: false
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Sample Azure DevOps governed pipeline
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This is an example pipeline to demonstrate customizing the unified pipeline.
|
||||
|
||||
parameters:
|
||||
|
||||
# Defined a global configuration for the pipeline.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defined azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: AzureGovernedPipelines
|
||||
type: git
|
||||
name: GovernedPipelines/GovernedPipelines
|
||||
ref: refs/tags/v1
|
||||
|
||||
extends:
|
||||
template: pipelines/unified@AzureGovernedPipelines
|
||||
parameters:
|
||||
global: ${{ parameters.global }}
|
||||
azure: ${{ parameters.azure }}
|
||||
defaults:
|
||||
azure:
|
||||
whatif: false
|
||||
location: 'eastus'
|
||||
offical: true
|
|
@ -0,0 +1,136 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Core governed pipeline stages
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This template defines the core pipeline structure.
|
||||
|
||||
parameters:
|
||||
|
||||
# Allows configuration of options within the governed pipeline that are enforced to all pipelines.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of option defaults for the governed pipeline.
|
||||
- name: defaults
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of options within the governed pipeline by consuming pipelines.
|
||||
- name: settings
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defined azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Determines if the pipeline is deploying to production.
|
||||
- name: offical
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Defines the required build pipeline stages.
|
||||
- name: stages
|
||||
type: stageList
|
||||
displayName: Stages
|
||||
|
||||
# Preflight checks that are required to run before everything.
|
||||
- name: preflight
|
||||
type: jobList
|
||||
default: []
|
||||
|
||||
# Defines the jobs which will run in the prereqs stage.
|
||||
- name: prereqs
|
||||
type: jobList
|
||||
default: []
|
||||
|
||||
stages:
|
||||
|
||||
# Run prereq configuration and checks.
|
||||
- ${{ if coalesce(parameters.global.prereqs.enabled, parameters.settings.prereqs.enabled, parameters.defaults.prereqs.enabled, false) }}:
|
||||
- template: prereqs.yaml
|
||||
parameters:
|
||||
global: ${{ parameters.global }}
|
||||
settings: ${{ parameters.settings }}
|
||||
defaults: ${{ parameters.defaults }}
|
||||
azure: ${{ parameters.azure }}
|
||||
offical: ${{ parameters.offical }}
|
||||
prereqs: ${{ parameters.prereqs }}
|
||||
|
||||
# Inject in user defined stages
|
||||
- ${{ each userStage in parameters.stages }}:
|
||||
- stage: ${{ userStage.stage }}
|
||||
# Remap top level properties to keep
|
||||
${{ if ne(userStage.displayName, '') }}:
|
||||
displayName: ${{ userStage.displayName }}
|
||||
${{ if ne(userStage.variables, '') }}:
|
||||
variables: ${{ userStage.variables }}
|
||||
${{ if ne(userStage.pool, '') }}:
|
||||
pool: ${{ userStage.pool }}
|
||||
${{ if ne(userStage.lockBehavior, '') }}:
|
||||
lockBehavior: ${{ userStage.lockBehavior }}
|
||||
${{ if ne(userStage.templateContext, '') }}:
|
||||
templateContext: ${{ userStage.templateContext }}
|
||||
|
||||
# Force prereq stage, if enabled to restrict skipping
|
||||
${{ if coalesce(parameters.global.prereqs.enabled, parameters.settings.prereqs.enabled, parameters.defaults.prereqs.enabled, false) }}:
|
||||
${{ if ne(userStage.condition, '') }}:
|
||||
condition: and(eq(dependencies.gov_prereqs.result, 'Succeeded'), ${{ userStage.condition }})
|
||||
${{ else }}:
|
||||
condition: eq(dependencies.gov_prereqs.result, 'Succeeded')
|
||||
${{ else }}:
|
||||
${{ if ne(userStage.condition, '') }}:
|
||||
condition: ${{ userStage.condition }}
|
||||
|
||||
# Inject dependencies
|
||||
${{ if coalesce(parameters.global.prereqs.enabled, parameters.settings.prereqs.enabled, parameters.defaults.prereqs.enabled, false) }}:
|
||||
${{ if ne(userStage.dependsOn, '') }}:
|
||||
dependsOn:
|
||||
- gov_prereqs
|
||||
- ${{ each dependency in userStage.dependsOn }}:
|
||||
- ${{ dependency }}
|
||||
${{ else }}:
|
||||
dependsOn:
|
||||
- gov_prereqs
|
||||
${{ else }}:
|
||||
${{ if ne(userStage.dependsOn, '') }}:
|
||||
dependsOn: ${{ userStage.dependsOn }}
|
||||
|
||||
jobs: ${{ userStage.jobs }}
|
||||
# - ${{ stage }}
|
||||
# ${{ if and(coalesce(parameters.settings.prereqs.enabled, parameters.defaults.prereqs.enabled, true)) }}:
|
||||
# condition: in(dependencies.A.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
|
||||
|
||||
# Complete preflight testing of everything before deployment.
|
||||
- ${{ if ge(length(parameters.preflight), 1) }}:
|
||||
- stage: preflight
|
||||
displayName: Preflight
|
||||
|
||||
${{ if coalesce(parameters.settings.pool, parameters.settings.pool) }}:
|
||||
pool: ${{ coalesce(parameters.settings.pool, parameters.settings.pool) }}
|
||||
|
||||
${{ if and(ge(length(parameters.prereqs), 1), coalesce(parameters.settings.prereqs.enabled, parameters.defaults.prereqs.enabled, true)) }}:
|
||||
dependsOn: [ prereqs ]
|
||||
|
||||
jobs:
|
||||
|
||||
- ${{ each job in parameters.preflight }}:
|
||||
- ${{ job }}
|
||||
|
||||
# Continue with Azure IaC stages if defined.
|
||||
- ${{ if parameters.azure.jobs }}:
|
||||
- template: deploy.azure.yaml
|
||||
parameters:
|
||||
global: ${{ parameters.global }}
|
||||
defaults: ${{ parameters.defaults }}
|
||||
azure: ${{ parameters.azure }}
|
||||
offical: ${{ parameters.offical }}
|
||||
|
||||
${{ if ge(length(parameters.preflight), 1) }}:
|
||||
dependsOn: preflight
|
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# Governed pipeline stage for Azure deployments
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This pipeline stage can be used to deploy to Azure using Bicep.
|
||||
|
||||
parameters:
|
||||
|
||||
# Defined a global configuration for the pipeline.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Set fallback defaults for the pipeline.
|
||||
- name: defaults
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defined azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Determines if the pipeline is deploying to production.
|
||||
- name: offical
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Sets the stages that must run prior to these stages.
|
||||
- name: dependsOn
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
stages:
|
||||
|
||||
- stage: Azure_DEV_Stage
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
jobs:
|
||||
|
||||
- ${{ each job in parameters.azure.jobs }}:
|
||||
- template: ../jobs/deploy.bicep.yaml
|
||||
parameters:
|
||||
name: ${{ job.name }}
|
||||
path: ${{ job.path }}
|
||||
location: ${{ coalesce(job.location, parameters.defaults.azure.location) }}
|
||||
whatif: ${{ coalesce(parameters.azure.whatif, parameters.defaults.azure.whatif, false) }}
|
||||
environment: ${{ coalesce(job.environment, parameters.defaults.azure.environment) }}
|
||||
serviceConnectionName: ${{ coalesce(job.serviceConnectionName, parameters.defaults.azure.serviceConnectionName) }}
|
||||
|
||||
${{ if ne(coalesce(job.dependsOn, 'none'), 'none') }}:
|
||||
dependsOn: ${{ job.dependsOn }}
|
||||
${{ if ne(coalesce(job.condition, 'none'), 'none') }}:
|
||||
condition: ${{ job.condition }}
|
|
@ -0,0 +1,108 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Prereqs stage
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This template runs an prereq jobs that need to be defined.
|
||||
|
||||
parameters:
|
||||
|
||||
# Allows configuration of options within the governed pipeline that are enforced to all pipelines.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of option defaults for the governed pipeline.
|
||||
- name: defaults
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of options within the governed pipeline by consuming pipelines.
|
||||
- name: settings
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defined azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Determines if the pipeline is deploying to production.
|
||||
- name: offical
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Defines the jobs which will run in the prereqs stage.
|
||||
- name: prereqs
|
||||
type: jobList
|
||||
default: []
|
||||
|
||||
stages:
|
||||
|
||||
# Define a prereq stage that the pipeline must execute before all other stages
|
||||
- stage: gov_prereqs
|
||||
displayName: 🔒 Prereqs
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: gov_prereqs_devsecops
|
||||
displayName: 🔒 Prereqs - DevSecOps
|
||||
variables:
|
||||
- name: GOV_PREREQS_RESULTS_PATH
|
||||
value: $(Build.ArtifactStagingDirectory)/code-scanning-results/
|
||||
readonly: true
|
||||
steps:
|
||||
# Checkout the repository
|
||||
- checkout: self
|
||||
fetchDepth: 0
|
||||
displayName: Checkout repository
|
||||
|
||||
- checkout: AzureGovernedPipelines
|
||||
displayName: Checkout governed pipelines repository
|
||||
|
||||
# Output diagnostic information to the logs.
|
||||
- ${{ if eq(coalesce(parameters.global.diag.enabled, parameters.settings.diag.enabled, parameters.defaults.diag.enabled, false), true) }}:
|
||||
- script: |
|
||||
echo "Global -- ${GLOBAL_VAR_JSON}"
|
||||
echo "Defaults -- ${DEFAULT_VAR_JSON}"
|
||||
echo "Settings -- ${SETTINGS_VAR_JSON}"
|
||||
displayName: 'Output pipeline configuration'
|
||||
env:
|
||||
GLOBAL_VAR_JSON: ${{ convertToJson(parameters.global) }}
|
||||
DEFAULTS_VAR_JSON: ${{ convertToJson(parameters.defaults) }}
|
||||
SETTINGS_VAR_JSON: ${{ convertToJson(parameters.settings) }}
|
||||
|
||||
# Create directory for code scanning results.
|
||||
- ${{ if eq(coalesce(parameters.global.prereqs.codeAnalysisLogs, parameters.settings.prereqs.codeAnalysisLogs, parameters.defaults.prereqs.codeAnalysisLogs, true), true) }}:
|
||||
- pwsh: |
|
||||
$Null = New-Item -Path $(GOV_PREREQS_RESULTS_PATH) -ItemType Directory -Force;
|
||||
displayName: Create results directory
|
||||
|
||||
# Run Defender for DevOps tool scan if enabled.
|
||||
- ${{ if eq(coalesce(parameters.global.tools.dfd.enabled, parameters.settings.tools.dfd.enabled, parameters.defaults.tools.dfd.enabled, false), true) }}:
|
||||
- template: ../steps/tools.microsoft.dfd.yaml
|
||||
parameters:
|
||||
codeAnalysisLogs: ${{ eq(coalesce(parameters.global.prereqs.codeAnalysisLogs, parameters.settings.prereqs.codeAnalysisLogs, parameters.defaults.prereqs.codeAnalysisLogs, true), true) }}
|
||||
break: ${{ coalesce(parameters.global.tools.dfd.break, parameters.settings.tools.dfd.break, parameters.defaults.tools.dfd.break, false) }}
|
||||
|
||||
# Run PSRule for Azure tool scan if enabled.
|
||||
- ${{ if eq(coalesce(parameters.global.tools.psrule.enabled, parameters.settings.tools.psrule.enabled, parameters.defaults.tools.psrule.enabled, false), true) }}:
|
||||
- template: ../steps/tools.microsoft.ps-rule.yaml
|
||||
parameters:
|
||||
codeAnalysisLogs: ${{ eq(coalesce(parameters.global.prereqs.codeAnalysisLogs, parameters.settings.prereqs.codeAnalysisLogs, parameters.defaults.prereqs.codeAnalysisLogs, true), true) }}
|
||||
modules: ${{ coalesce(parameters.global.tools.psrule.modules, parameters.settings.tools.psrule.modules, parameters.defaults.tools.psrule.modules, '') }}
|
||||
baseline: ${{ coalesce(parameters.global.tools.psrule.baseline, parameters.settings.tools.psrule.baseline, parameters.defaults.tools.psrule.baseline, '') }}
|
||||
conventions: ${{ coalesce(parameters.global.tools.psrule.conventions, parameters.settings.tools.psrule.conventions, parameters.defaults.tools.psrule.conventions, '') }}
|
||||
|
||||
- ${{ if eq(coalesce(parameters.global.prereqs.codeAnalysisLogs, parameters.settings.prereqs.codeAnalysisLogs, parameters.defaults.prereqs.codeAnalysisLogs, true), true) }}:
|
||||
# Upload to scans tab
|
||||
- publish: $(GOV_PREREQS_RESULTS_PATH)
|
||||
displayName: Upload results to scans tabs
|
||||
artifact: CodeAnalysisLogs
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- ${{ if ge(length(parameters.prereqs), 1) }}:
|
||||
- ${{ each job in parameters.prereqs }}:
|
||||
- ${{ job }}
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Tool configuration for Defender for DevOps.
|
||||
#
|
||||
|
||||
parameters:
|
||||
|
||||
# Set the break parameter to true to fail the pipeline if any of the checks fail.
|
||||
- name: break
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Enable or disable upload of code analysis logs.
|
||||
- name: codeAnalysisLogs
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
steps:
|
||||
|
||||
# Add the Defender for DevOps task into the pipeline.
|
||||
- task: MicrosoftSecurityDevOps@1
|
||||
displayName: Run Defender for DevOps scan
|
||||
inputs:
|
||||
break: ${{ parameters.break }}
|
||||
publish: false
|
||||
|
||||
# Copy SARIF results for upload to the pipeline artifacts.
|
||||
- ${{ if parameters.codeAnalysisLogs }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy Defender for DevOps results
|
||||
inputs:
|
||||
TargetFolder: $(GOV_PREREQS_RESULTS_PATH)
|
||||
SourceFolder: $(Build.ArtifactStagingDirectory)/.gdn/
|
||||
Contents: |
|
||||
**/*.sarif
|
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
# Tool configuration for PSRule for Azure.
|
||||
#
|
||||
|
||||
parameters:
|
||||
|
||||
- name: modules
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
- name: minimum
|
||||
displayName: The minimum version of PSRule to use.
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
- name: baseline
|
||||
type: string
|
||||
default: 'latest'
|
||||
|
||||
- name: conventions
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
- name: prerelease
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
- name: summary
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
- name: codeAnalysisLogs
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
steps:
|
||||
|
||||
# Add the PSRule for Azure task into the pipeline.
|
||||
- task: ps-rule-assert@2
|
||||
displayName: Run PSRule for Azure scan
|
||||
inputs:
|
||||
${{ if ne(parameters.modules, '') }}:
|
||||
modules: ${{ parameters.modules }}
|
||||
|
||||
# Save SARIF results
|
||||
outputFormat: Sarif
|
||||
outputPath: $(GOV_PREREQS_RESULTS_PATH)ps-rule-results.sarif
|
||||
|
||||
# Support pre-release
|
||||
prerelease: ${{ parameters.prerelease }}
|
||||
|
||||
${{ if ne(parameters.baseline, 'latest') }}:
|
||||
baseline: ${{ parameters.baseline }}
|
||||
|
||||
${{ if ne(parameters.conventions, '') }}:
|
||||
conventions: ${{ parameters.conventions }}
|
||||
|
||||
env:
|
||||
${{ if ne(parameters.minimum, '') }}:
|
||||
PSRULE_REQUIRES_PSRULE: '@pre >=${{ parameters.minimum }}'
|
||||
|
||||
${{ if ne(variables['BICEPREGISTRYCLIENTID'], 'BICEPREGISTRYCLIENTID') }}:
|
||||
AZURE_CLIENT_ID: $(BICEPREGISTRYCLIENTID)
|
||||
|
||||
${{ if ne(variables['BICEPREGISTRYTENANTID'], 'BICEPREGISTRYTENANTID') }}:
|
||||
AZURE_TENANT_ID: $(BICEPREGISTRYTENANTID)
|
||||
|
||||
${{ if ne(variables['BICEPREGISTRYCLIENTSECRET'], 'BICEPREGISTRYCLIENTSECRET') }}:
|
||||
AZURE_CLIENT_SECRET: $(BICEPREGISTRYCLIENTSECRET)
|
|
@ -0,0 +1,59 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Unified Pipeline - Azure Governed Pipeline for Azure Pipelines
|
||||
#
|
||||
|
||||
# NOTE:
|
||||
# This unified pipeline is used to test then deploy infrastructure and application code.
|
||||
|
||||
parameters:
|
||||
|
||||
# Allows configuration of options within the governed pipeline that are enforced to all pipelines.
|
||||
- name: global
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of option defaults for the governed pipeline.
|
||||
- name: defaults
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Allows configuration of options within the governed pipeline by consuming pipelines.
|
||||
- name: settings
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Defines azure configuration for the pipeline.
|
||||
- name: azure
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
# Determines if the pipeline is deploying to production.
|
||||
- name: offical
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Defines the required build pipeline stages.
|
||||
- name: stages
|
||||
type: stageList
|
||||
displayName: Stages
|
||||
|
||||
# Defines the jobs which will run in the prereqs stage.
|
||||
- name: prereqs
|
||||
type: jobList
|
||||
default: []
|
||||
|
||||
stages:
|
||||
|
||||
# Link to the core template where all stages will be defined.
|
||||
- template: stages/core.yaml
|
||||
parameters:
|
||||
global: ${{ parameters.global }}
|
||||
settings: ${{ parameters.settings }}
|
||||
defaults: ${{ parameters.defaults }}
|
||||
azure: ${{ parameters.azure }}
|
||||
offical: ${{ parameters.offical }}
|
||||
prereqs: ${{ parameters.prereqs }}
|
||||
stages: ${{ parameters.stages }}
|
Загрузка…
Ссылка в новой задаче