Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/assets/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
--md-admonition-icon--learn: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M12.292 2.06v-.001l11.25 4.75a.749.749 0 0 1 0 1.382L19 10.108V15a.75.75 0 0 1-.11.391h-.001a2.84 2.84 0 0 1-.392.482c-.249.256-.625.58-1.163.896-1.08.638-2.776 1.23-5.334 1.23-.673 0-1.286-.041-1.846-.113a.75.75 0 0 1 .192-1.487c.492.063 1.042.1 1.654.1 2.317 0 3.746-.533 4.572-1.021.31-.178.596-.397.849-.65l.079-.085V10.74l-5.208 2.2a.75.75 0 0 1-.584 0L5.75 10.424v3.17c.502.129.96.391 1.327.758.579.578.923 1.41.923 2.428v4.5a.761.761 0 0 1-.345.634 2.157 2.157 0 0 1-.21.117 3.923 3.923 0 0 1-.52.213A6.121 6.121 0 0 1 5 22.532a6.092 6.092 0 0 1-1.925-.288 4.065 4.065 0 0 1-.52-.213 1.816 1.816 0 0 1-.22-.124.757.757 0 0 1-.335-.624v-4.5c0-1.02.344-1.85.923-2.43a2.904 2.904 0 0 1 1.327-.757V9.793L.458 8.19a.75.75 0 0 1 0-1.38l11.25-4.75a.75.75 0 0 1 .584 0ZM12 11.436 21.322 7.5 12 3.564 2.678 7.5ZM5 15c-.377 0-.745.141-1.017.413-.265.265-.483.7-.483 1.368v4.022c.299.105.797.228 1.5.228s1.201-.123 1.5-.228V16.78c0-.669-.218-1.103-.483-1.368A1.433 1.433 0 0 0 5 15Z"></path></svg>');
--md-admonition-icon--message: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 4.75C0 3.784.784 3 1.75 3h20.5c.966 0 1.75.784 1.75 1.75v14.5A1.75 1.75 0 0 1 22.25 21H1.75A1.75 1.75 0 0 1 0 19.25Zm1.75-.25a.25.25 0 0 0-.25.25v14.5c0 .138.112.25.25.25h20.5a.25.25 0 0 0 .25-.25V4.75a.25.25 0 0 0-.25-.25Z"/><path d="M5 8.75A.75.75 0 0 1 5.75 8h11.5a.75.75 0 0 1 0 1.5H5.75A.75.75 0 0 1 5 8.75Zm0 4a.75.75 0 0 1 .75-.75h5.5a.75.75 0 0 1 0 1.5h-5.5a.75.75 0 0 1-.75-.75Z"/></svg>');
--md-admonition-icon--security: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 15.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0m-.25-8.25a.75.75 0 0 0-1.5 0v4.5a.75.75 0 0 0 1.5 0z"/><path d="M11.46.637a1.75 1.75 0 0 1 1.08 0l8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.77 10.705-9.401 12.83a1.7 1.7 0 0 1-1.198 0C5.771 20.704 2 16.19 2 10V4.976c0-.76.49-1.43 1.21-1.664Zm.617 1.426a.25.25 0 0 0-.154 0L3.673 4.74a.25.25 0 0 0-.173.237V10c0 5.461 3.28 9.483 8.43 11.426a.2.2 0 0 0 .14 0C17.22 19.483 20.5 15.46 20.5 10V4.976a.25.25 0 0 0-.173-.237Z"/></svg>');
--md-admonition-icon--diamond: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M1.527 13.237a1.75 1.75 0 0 1 0-2.474l9.272-9.273a1.75 1.75 0 0 1 2.475 0l9.272 9.273a1.75 1.75 0 0 1 0 2.474l-9.272 9.272a1.75 1.75 0 0 1-2.475 0Zm1.06-1.414a.25.25 0 0 0 0 .354l9.273 9.272a.25.25 0 0 0 .353 0l9.272-9.272a.25.25 0 0 0 0-.354l-9.272-9.272a.25.25 0 0 0-.353 0Z"/></svg>');
}

/* experimental */
Expand Down Expand Up @@ -110,6 +111,25 @@
mask-image: var(--md-admonition-icon--security);
}

/* implementation reference */
.md-typeset .admonition.implementation,
.md-typeset details.implementation {
border-color: rgb(124, 77, 255)
}

.md-typeset .implementation>.admonition-title,
.md-typeset .implementation>summary {
background-color: rgba(124, 77, 255, .1);
border-color: rgb(124, 77, 255);
}

.md-typeset .implementation>.admonition-title::before,
.md-typeset .implementation>summary::before {
background-color: rgb(124, 77, 255);
-webkit-mask-image: var(--md-admonition-icon--diamond);
mask-image: var(--md-admonition-icon--diamond);
}

/* badges */

.badge {
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ What's changed since v1.47.0:
- Azure Kubernetes Service:
- Updated `Azure.AKS.Version` to use `1.33.7` as the minimum version by @BernieWhite.
[#3708](https://github.com/Azure/PSRule.Rules.Azure/issues/3708)
- Improved documentation for expansion internals with a high-level flow diagram and code references by @Copilot.
[#3715](https://github.com/Azure/PSRule.Rules.Azure/issues/3715)

## v1.47.0

Expand Down
2 changes: 1 addition & 1 deletion docs/en/rules/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ Name | Synopsis | Severity | Level
---- | -------- | -------- | -----
[Azure.VNET.FirewallSubnet](Azure.VNET.FirewallSubnet.md) | Use Azure Firewall to filter network traffic to and from Azure resources. | Important | Error

### SE:01 Security baseline
### SE:01 Security Baseline

Name | Synopsis | Severity | Level
---- | -------- | -------- | -----
Expand Down
2 changes: 1 addition & 1 deletion docs/es/rules/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ Name | Synopsis | Severity | Level
---- | -------- | -------- | -----
[Azure.VNET.FirewallSubnet](Azure.VNET.FirewallSubnet.md) | Use Azure Firewall to filter network traffic to and from Azure resources. | Important | Error

### SE:01 Security baseline
### SE:01 Security Baseline

Name | Synopsis | Severity | Level
---- | -------- | -------- | -----
Expand Down
66 changes: 66 additions & 0 deletions docs/license-contributing/expansion-internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,46 @@ The main components of the expansion process are:
- **Materialized properties** &mdash; Some resources types have properties that are affected by multiple deployments or
child resources. These must be calculated to determine the final state value of the property.

### High-level flow

The following diagram shows the high-level flow of the expansion process from source file to expanded resources.

```mermaid
flowchart TD
A["Input file (.bicep / .bicepparam / .json)"] --> B{Is Bicep source?}
B -->|Yes| C["Build with Bicep CLI\n(bicep build / bicep build-params)"]
B -->|No| D[Read ARM template JSON]
C --> D
D --> E["Load parameters\n(parameter file + AZURE_PARAMETER_DEFAULTS)"]
E --> F["Visit deployment\n(DeploymentVisitor)"]
F --> G["Process definitions\n(parameters, variables, functions, types)"]
G --> H["Build dependency graph\n(ResourceDependencyGraph)"]
H --> I[Visit each resource in dependency order]
I --> J{Is nested deployment?}
J -->|Yes| K["Visit nested deployment recursively\n(inner / outer scope)"]
J -->|No| L["Evaluate condition\nExpand copy loops"]
L --> M["Resolve property expressions\n(ExpressionBuilder)"]
M --> N[Emit resource to context]
K --> N
N --> O{More resources?}
O -->|Yes| I
O -->|No| P["Post-process\n(MaterializedDeploymentVisitor)\nNest children, materialize properties"]
P --> Q[Output expanded resources]
```

### Key components

The key source code components involved in the expansion process are:

Component | Source file | Description
---------- | ----------- | -----------
`BicepHelper` | `src/PSRule.Rules.Azure/Data/Bicep/BicepHelper.cs` | Invokes the Bicep CLI and coordinates expansion of Bicep and ARM files.
`DeploymentVisitor` | `src/PSRule.Rules.Azure/Arm/Deployments/DeploymentVisitor.cs` | The core visitor that walks the ARM deployment structure.
`MaterializedDeploymentVisitor` | `src/PSRule.Rules.Azure/Arm/Deployments/MaterializedDeploymentVisitor.cs` | Extends `DeploymentVisitor` to handle post-processing of emitted resources.
`ResourceDependencyGraph` | `src/PSRule.Rules.Azure/Arm/Deployments/ResourceDependencyGraph.cs` | Builds and resolves the dependency graph for resources in a deployment.
`ExpressionBuilder` | `src/PSRule.Rules.Azure/Arm/Expressions/ExpressionBuilder.cs` | Parses and evaluates ARM template expressions.
`Functions` | `src/PSRule.Rules.Azure/Arm/Expressions/Functions.cs` | Implementations of ARM template built-in functions used during expression evaluation.

## Building Bicep

Azure Bicep code syntax is a domain specific language provides a higher level of abstraction over ARM deployments.
Expand All @@ -55,6 +95,14 @@ As a result, the Bicep CLI must be installed and available prior to running the

To build a Bicep file, the Bicep CLI is invoked with `bicep build` or `bicep build-params` command.

!!! Implementation
The `BicepHelper` class (`src/PSRule.Rules.Azure/Data/Bicep/BicepHelper.cs`) is responsible for:

- Discovering the Bicep CLI.
- Spawning the Bicep CLI process.
- Calling `ProcessFile` for a `.bicep` file or `ProcessParamFile` for a `.bicepparam` file.
- Passing the resulting ARM template JSON to the deployment visitor for expansion.

### CLI discovery

To find an instance of the Bicep CLI, PSRule for Azure probes several paths, and uses the first instance found.
Expand Down Expand Up @@ -94,6 +142,10 @@ Secrets are a good example of this, as they should not be specified in the param
Definitions are the building blocks of the ARM deployment and may be reference by resources or other definitions.
For most cases, definitions are lazy loaded into the context of the deployment during expansion.

!!! Implementation
The `LazyParameter`, `LazyVariable`, and `LazyOutput` classes (in `src/PSRule.Rules.Azure/Arm/Deployments/`) implement this lazy loading pattern,
deferring evaluation of each definition until it is first referenced.

Exceptions to this are when copy loops are used to define variables and parameters.
Otherwise the definitions are not resolved until they are referenced by a resource.

Expand All @@ -107,6 +159,10 @@ Similarly, a deployment may return outputs that are used in the parent deploymen
As a result, each resource must be visited based on a dependency graph so that dependencies are resolved
before dependant resources.

!!! Implementation
The `ResourceDependencyGraph` class (`src/PSRule.Rules.Azure/Arm/Deployments/ResourceDependencyGraph.cs`) builds this graph
from the `dependsOn` properties declared in the template, and performs a topological sort to produce the correct visit order.

## Visiting each resource

When a resource is visited:
Expand Down Expand Up @@ -146,6 +202,16 @@ For each function to be understood by the expansion process, it must be implemen

When an expression is called, context about the deployment is passed into the root function of the expression.

!!! Implementation
The key classes for expression evaluation are:

- `ExpressionParser` (`src/PSRule.Rules.Azure/Arm/Expressions/ExpressionParser.cs`) &mdash;
Tokenizes and parses ARM expression strings into an `ExpressionStream`.
- `ExpressionBuilder` (`src/PSRule.Rules.Azure/Arm/Expressions/ExpressionBuilder.cs`) &mdash;
Builds a callable expression tree from the parsed tokens.
- `Functions` (`src/PSRule.Rules.Azure/Arm/Expressions/Functions.cs`) &mdash;
Contains implementations of all supported ARM template built-in functions.

### Context properties

During deployment to Azure, ARM maintains several context objects that are used to evaluate expressions.
Expand Down
1 change: 1 addition & 0 deletions docs/license-contributing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Please read our [contributing guidelines][2] and [code of conduct][3] to learn h
- [Writing documentation](writing-documentation.md) &mdash; Guidelines for writing and improving documentation.
- [Getting started with documentation](getting-started-with-documentation.md) &mdash; How to get started contributing to documentation.
- [Get started contributing](get-started-contributing.md) &mdash; How to get started contributing to the project.
- [Expansion internals](expansion-internals.md) &mdash; Internals of the expansion process for developers and contributors.

[1]: https://github.com/Azure/PSRule.Rules.Azure/blob/main/LICENSE
[2]: https://github.com/Azure/PSRule.Rules.Azure/blob/main/CONTRIBUTING.md
Expand Down
6 changes: 5 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ markdown_extensions:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.superfences
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.pathconverter
- pymdownx.tabbed:
alternate_style: true
Expand Down
Loading