Skip to content

Commit

Permalink
Add security note to rule documentation (#3151)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Oct 26, 2024
1 parent e480938 commit 5a5c401
Show file tree
Hide file tree
Showing 16 changed files with 314 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ updates:
patterns:
- System.Management.Automation
- Microsoft.PowerShell.SDK
ignore:
- dependency-name: gitversion.tool

# Maintain dependencies for GitHub Actions
- package-ecosystem: github-actions
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ dist/
**/bin/
**/obj/
**/__pycache__/
**/*.egg-info/
**/build/
BenchmarkDotNet.Artifacts/
results/
.venv/
Expand Down
20 changes: 20 additions & 0 deletions docs/assets/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
--md-admonition-icon--experimental: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M8 8.807V3.5h-.563a.75.75 0 0 1 0-1.5h9.125a.75.75 0 0 1 0 1.5H16v5.307l5.125 9.301c.964 1.75-.302 3.892-2.299 3.892H5.174c-1.998 0-3.263-2.142-2.3-3.892L8 8.807zM14.5 3.5h-5V9a.75.75 0 0 1-.093.362L7.127 13.5h9.746l-2.28-4.138A.75.75 0 0 1 14.5 9V3.5zM4.189 18.832 6.3 15h11.4l2.111 3.832a1.125 1.125 0 0 1-.985 1.668H5.174a1.125 1.125 0 0 1-.985-1.668z"/></svg>');
--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>');
}

/* experimental */
Expand Down Expand Up @@ -90,6 +91,25 @@
mask-image: var(--md-admonition-icon--message);
}

/* security */
.md-typeset .admonition.security,
.md-typeset details.security {
border-color: rgb(32, 148, 243)
}

.md-typeset .security>.admonition-title,
.md-typeset .security>summary {
background-color: rgba(32, 148, 243, .1);
border-color: rgb(32, 148, 243)
}

.md-typeset .security>.admonition-title::before,
.md-typeset .security>summary::before {
background-color: rgb(32, 148, 243);
-webkit-mask-image: var(--md-admonition-icon--security);
mask-image: var(--md-admonition-icon--security);
}

/* badges */

.badge {
Expand Down
32 changes: 21 additions & 11 deletions docs/en/rules/Azure.Deployment.AdminUsername.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
---
reviewed: 2024-10-26
severity: Awareness
pillar: Security
category: Infrastructure provisioning
category: SE:02 Secured development lifecycle
resource: Deployment
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Deployment.AdminUsername/
---

# Administrator Username Types
# Deployment uses deterministic credential values

## SYNOPSIS

Use secure parameters for sensitive resource properties.
A sensitive property set from deterministic or hardcoded values is not secure.

## DESCRIPTION

Resource properties can be configured using a hardcoded value or Azure Bicep/ template expressions.
When specifying sensitive values use _secure_ parameters such as `secureString` or `secureObject`.
When specifying sensitive values use _secure_ parameters.
Secure parameters use the `@secure` decorator in Bicep or the `secureString` / `secureObject` type.

Sensitive values that use deterministic expressions such as hardcodes string literals or variables are not secure.
Sensitive values that use deterministic expressions such as hardcoded string literals or variables are not secure.
These values can be read by anyone with read access to deployment history or logs.
Logs are often exposed at multiple levels including CI pipeline logs, Azure Activity Logs, and SIEM systems.

<!-- security:note rotate-secret -->

## RECOMMENDATION

Sensitive properties should be passed as parameters.
Avoid using deterministic values for sensitive properties.
Avoid using deterministic or hardcoded values for sensitive properties.

## EXAMPLES

### Configure with Azure template

To deploy resources that pass this rule:
To configure deployments that pass this rule:

- Use secure parameters to specify sensitive properties.
- Set the `type` of parameters used set sensitive resource properties to `secureString` or `secureObject`.

For example:

Expand Down Expand Up @@ -85,9 +91,9 @@ For example:

### Configure with Bicep

To deploy resources that pass this rule:
To configure deployments that pass this rule:

- Use secure parameters to specify sensitive properties.
- Add the `@secure()` decorators on parameters used to set sensitive resource properties.

For example:

Expand Down Expand Up @@ -145,6 +151,10 @@ resource vm1 'Microsoft.Compute/virtualMachines@2022-03-01' = {

## NOTES

### Rule configuration

<!-- module:config rule AZURE_DEPLOYMENT_SENSITIVE_PROPERTY_NAMES -->

Configure `AZURE_DEPLOYMENT_SENSITIVE_PROPERTY_NAMES` to specify sensitive property names.
By default, the following values are used:

Expand All @@ -154,6 +164,6 @@ By default, the following values are used:

## LINKS

- [Infrastructure provisioning considerations in Azure](https://learn.microsoft.com/azure/architecture/framework/security/deploy-infrastructure)
- [SE:02 Secured development lifecycle](https://learn.microsoft.com/azure/well-architected/security/secure-development-lifecycle)
- [Use Azure Key Vault to pass secure parameter value during Bicep deployment](https://learn.microsoft.com/azure/azure-resource-manager/bicep/key-vault-parameter)
- [Integrate Azure Key Vault in your ARM template deployment](https://learn.microsoft.com/azure/azure-resource-manager/templates/template-tutorial-use-key-vault#edit-the-parameters-file)
12 changes: 8 additions & 4 deletions docs/en/rules/Azure.Deployment.OuterSecret.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
reviewed: 2022-11-15
severity: Critical
pillar: Security
category: Infrastructure provisioning
category: SE:02 Secured development lifecycle
resource: Deployment
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Deployment.OuterSecret/
---

# Secret value in deployment output
# Deployment exposes secrets with outer deployment

## SYNOPSIS

Do not use Outer deployments when references SecureString or SecureObject parameters.
Outer evaluation deployments may leak secrets exposed as secure parameters into logs and nested deployments.

## DESCRIPTION

Expand All @@ -22,6 +22,8 @@ templates instead of enforcing `secureString` and `secureObject` types.
When passing secure values to nested deployments always use `inner` scope deployments to ensure secure values are not logging.
Bicep modules always use `inner` scope evaluated deployments.

<!-- security:note rotate-secret -->

## RECOMMENDATION

Consider using `inner` deployments to prevent secure values from being exposed.
Expand Down Expand Up @@ -86,9 +88,11 @@ Nested Deployments within an ARM template need the property `expressionEvaluatio

### Configure with Bicep

Bicep templates will do this by default when performing nested deployments.
This does not apply to Bicep code as under normal circumstances.
If you use the `module` keyword your deployments always use the `inner` evaluation mode.

## LINKS

- [SE:02 Secured development lifecycle](https://learn.microsoft.com/azure/well-architected/security/secure-development-lifecycle)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.resources/deployments?pivots=deployment-language-bicep)
- [Deployment Function Scopes](https://learn.microsoft.com/azure/azure-resource-manager/templates/scope-functions?tabs=azure-powershell#function-resolution-in-scopes)
15 changes: 10 additions & 5 deletions docs/en/rules/Azure.Deployment.OutputSecretValue.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
reviewed: 2022-06-12
severity: Critical
pillar: Security
category: Infrastructure provisioning
category: SE:02 Secured development lifecycle
resource: Deployment
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Deployment.OutputSecretValue/
---

# Secret value in deployment output
# Deployment exposes a secret in output

## SYNOPSIS

Avoid outputting sensitive deployment values.
Outputting a sensitive value from deployment may leak secrets into deployment history or logs.

## DESCRIPTION

Expand All @@ -23,6 +23,11 @@ Examples of secrets are:
- Parameters using the `secureString` or `secureObject` type.
- Output from `list*` functions such as `listKeys`.

Outputs are recorded in clear texts within deployment history and logs.
Logs are often exposed at multiple levels including CI pipeline logs, Azure Activity Logs, and SIEM systems.

<!-- security:note rotate-secret -->

## RECOMMENDATION

Consider removing any output values that return secret values in code.
Expand Down Expand Up @@ -82,7 +87,7 @@ The following example fails because it returns a secret:

To deploy securely pass secrets within Infrastructure as Code:

- Mark secrets with the `@secure()` annotation.
- Add the `@secure()` decorators on sensitive parameters.
- Avoid returning a secret in output values.

Example using `@secure()` annotation:
Expand All @@ -101,7 +106,7 @@ output accountPassword string = adminPassword

## LINKS

- [Pipeline secret management](https://learn.microsoft.com/azure/architecture/framework/security/deploy-infrastructure#pipeline-secret-management)
- [SE:02 Secured development lifecycle](https://learn.microsoft.com/azure/well-architected/security/secure-development-lifecycle)
- [Test cases for ARM templates](https://learn.microsoft.com/azure/azure-resource-manager/templates/template-test-cases#outputs-cant-include-secrets)
- [Outputs should not contain secrets](https://learn.microsoft.com/azure/azure-resource-manager/bicep/linter-rule-outputs-should-not-contain-secrets)
- [List function](https://learn.microsoft.com/azure/azure-resource-manager/bicep/bicep-functions-resource#list)
23 changes: 14 additions & 9 deletions docs/en/rules/Azure.Deployment.SecureValue.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
reviewed: 2022-10-10
reviewed: 2024-10-26
severity: Critical
pillar: Security
category: SE:02 Secured development lifecycle
Expand All @@ -17,22 +17,25 @@ A secret property set from a non-secure value may leak the secret into deploymen

Azure Bicep and Azure Resource Manager (ARM) templates can be used to deploy resources to Azure.
When deploying Azure resources, sensitive values such as passwords, certificates, and keys should be passed as secure parameters.
Secure parameters use the `secureString` or `secureObject` type.
Secure parameters use the `@secure` decorator in Bicep or the `secureString` / `secureObject` type.

Parameters that do not use secure types are recorded in logs and deployment history.
These values can be retrieved by anyone with access to the deployment history.
Parameters that do not use secure types are recorded in deployment history and logs.
These values can be retrieved by anyone with read access to the deployment history and logs.
Logs are often exposed at multiple levels including CI pipeline logs, Azure Activity Logs, and SIEM systems.

<!-- security:note rotate-secret -->

## RECOMMENDATION

Consider using secure parameters for sensitive resource properties.
Consider using secure parameters for setting the value of any sensitive resource properties.

## EXAMPLES

### Configure with Azure template

To configure deployments that pass this rule:

- Set the type of parameters used set sensitive resource properties to `secureString` or `secureObject`.
- Set the `type` of parameters used set sensitive resource properties to `secureString` or `secureObject`.

For example:

Expand Down Expand Up @@ -62,7 +65,7 @@ For example:

To configure deployments that pass this rule:

- Add the `@secure()` attribute on parameters used to set sensitive resource properties.
- Add the `@secure()` decorators on parameters used to set sensitive resource properties.

For example:

Expand All @@ -80,12 +83,14 @@ resource goodSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {

## NOTES

For a list of resource types and properties that are checked by this rule see:
For a list of resource types and properties that are checked by this rule see [secret properties][1].
If you find properties that are missing, please let us know by logging an issue on GitHub.

- https://github.com/Azure/PSRule.Rules.Azure/blob/main/data/secret-property.json
[1]: https://github.com/Azure/PSRule.Rules.Azure/blob/main/data/secret-property.json

## LINKS

- [SE:02 Secured development lifecycle](https://learn.microsoft.com/azure/well-architected/security/secure-development-lifecycle)
- [Secure parameters](https://learn.microsoft.com/azure/azure-resource-manager/bicep/parameters#secure-parameters)
- [Use Azure Key Vault to pass secure parameter value during Bicep deployment](https://learn.microsoft.com/azure/azure-resource-manager/bicep/key-vault-parameter)
- [Integrate Azure Key Vault in your ARM template deployment](https://learn.microsoft.com/azure/azure-resource-manager/templates/template-tutorial-use-key-vault#edit-the-parameters-file)
64 changes: 63 additions & 1 deletion docs/hooks/shortcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import re
import json
import io

from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
Expand All @@ -22,7 +23,7 @@
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files) -> str:
'''Hook on_page_markdown event.'''

return external(module(markdown, page, config, files), page, config, files)
return security_note(external(module(markdown, page, config, files), page, config, files), page, config, files)

#
# Supporting functions
Expand Down Expand Up @@ -68,6 +69,24 @@ def replace(match: re.Match) -> str:
replace, markdown, flags = re.I | re.M
)

def security_note(markdown: str, page: Page, config: MkDocsConfig, files: Files) -> str:
'''Replace security notes shortcodes in markdown.'''

# Callback for regular expression replacement.
def replace(match: re.Match) -> str:
type, args = match.groups()
args = args.strip()
if type == "note":
return _security_note_block(args, page, config)

raise RuntimeError(f"Unknown shortcode security:{type}")

# Replace security note shortcodes.
return re.sub(
r"<!-- security:(\w+)(.*?) -->",
replace, markdown, flags = re.I | re.M
)

def _relative_uri(path: str, page: Page, files: Files) -> str:
'''Get relative URI for a file including anchor.'''

Expand Down Expand Up @@ -210,3 +229,46 @@ def _avm_module_latest_tag(page: Page, name: str) -> str:
latest = data[name]['Latest']

return latest

def _find_include_for_culture(config: MkDocsConfig, culture: str, path: str) -> str:
'''Find the markdown include file for a specific culture.'''
defaultCulture = config.theme.locale
culture = culture.lower()

# Get the repo root path.
repo_root_dir = os.path.join(config.docs_dir, "..")

# Find the include file for the culture.
includeFile = f"{repo_root_dir}/includes/{culture}/{path}"
fallbackFile = f"{repo_root_dir}/includes/{defaultCulture}/{path}"

# If the path exists load the contents from disk.
if os.path.exists(includeFile) and os.path.isfile(includeFile):
return io.open(includeFile, 'r', encoding='utf-8').read()

# If the path does not exist, try the default culture.
if os.path.exists(fallbackFile) and os.path.isfile(fallbackFile):
return io.open(fallbackFile, 'r', encoding='utf-8').read()

raise RuntimeError(f"Unknown include '{path}' not found at '{includeFile}' or '{fallbackFile}'.")

def _get_culture_from_page(page: Page, config: MkDocsConfig) -> str:
'''Get the culture from the page file path.'''

culture = config.theme.locale
if page.file.src_path.startswith('en'):
culture = 'en'

elif page.file.src_path.startswith('es'):
culture = 'es'

return culture


def _security_note_block(text: str, page: Page, config: MkDocsConfig) -> str:
'''Create a security note block.'''

culture = _get_culture_from_page(page, config)
name = text.split(' ')[0]

return _find_include_for_culture(config, culture, f"security-notes/{name}.md")
2 changes: 2 additions & 0 deletions includes/en/abbreviations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

*[SIEM]: Security information and event management
7 changes: 7 additions & 0 deletions includes/en/security-notes/rotate-secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

!!! Security "Secret rotation &mdash; [SE:09 Application secrets](https://learn.microsoft.com/azure/well-architected/security/application-secrets#secret-rotation)"
If a secret has already been exposed by a previous insecure deployment,
rotate it immediately to prevent unauthorized access to your resources.

Rotating a secret involves changing or regenerating the secret value and updating all dependent resources with the new value.
This process should be done in a secure manner to prevent the new secret from being exposed.
Loading

0 comments on commit 5a5c401

Please sign in to comment.