-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
d8a5b8f
commit 1a221af
Showing
15 changed files
with
339 additions
and
71 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: Sample proposal | ||
description: Make a proposal for the community to add a new sample | ||
title: '[Sample]: ' | ||
type: Feature | ||
labels: ['sample', 'Needs: Triage :mag:'] | ||
body: | ||
- type: markdown | ||
attributes: | ||
value: | | ||
Fill out this form below to suggest a new sample to be added by the community. | ||
- type: dropdown | ||
id: exiting-sample-check | ||
attributes: | ||
label: | | ||
Have you checked this sample does not already exist in the repository? | ||
Samples are stored in `samples/` in the root of the repository. | ||
options: | ||
- 'Yes' | ||
- 'No' | ||
validations: | ||
required: true | ||
- type: textarea | ||
id: why-the-sample | ||
attributes: | ||
label: Why is the sample needed? | ||
description: Explain why the sample is needed. If there is a existing sample, explain why it cannot be updated to meet your needs and why a new one must be created. | ||
validations: | ||
required: true | ||
- type: input | ||
id: sample-path | ||
attributes: | ||
label: Sample path | ||
description: The path to the new sample. | ||
placeholder: samples/rules/name | ||
validations: | ||
required: true | ||
- type: textarea | ||
id: sample-description | ||
attributes: | ||
label: Describe the sample | ||
description: A clear and concise description of the sample. | ||
validations: | ||
required: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# Licensed under the MIT License. | ||
|
||
# NOTES: | ||
# This file implements generation of samples TOC. | ||
|
||
import logging | ||
import os | ||
import re | ||
|
||
from mkdocs.config.defaults import MkDocsConfig | ||
from mkdocs.structure.files import Files | ||
from mkdocs.structure.pages import Page | ||
|
||
log = logging.getLogger(f"mkdocs") | ||
|
||
# | ||
# Hooks | ||
# | ||
|
||
def on_pre_build(config: MkDocsConfig): | ||
'''Hook on_pre_build event.''' | ||
|
||
return generate_samples_toc_fragment(config) | ||
|
||
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files) -> str: | ||
'''Hook on_page_markdown event.''' | ||
|
||
return samples_shortcode(markdown, page, config, files) | ||
|
||
# | ||
# Supporting functions | ||
# | ||
|
||
def generate_samples_toc_fragment(config: MkDocsConfig): | ||
'''Generate a markdown fragment that will be injected into files containing a short code.''' | ||
|
||
# Get the samples directory which is in a parent directory. | ||
repo_root_dir = os.path.join(config.docs_dir, "..") | ||
samples_dir = os.path.join(repo_root_dir, "samples", "rules") | ||
|
||
# Get the base repo URI. | ||
base_repo_uri = config.repo_url | ||
samples_repo_uri = f"{base_repo_uri}tree/main/samples/rules" | ||
|
||
# Generate the TOC fragment, each sample exists as a README.md file in a subdirectory. | ||
toc = [] | ||
for root, dirs, _ in os.walk(samples_dir): | ||
for dir in dirs: | ||
if dir == "common": | ||
continue | ||
|
||
current_sample_dir = os.path.join(root, dir) | ||
title = "" | ||
description = [] | ||
author = "" | ||
block = "none" | ||
|
||
# Read the file to get the title and lines until the first empty line. | ||
with open(os.path.join(current_sample_dir, "README.md"), "r") as f: | ||
|
||
# Read annotations and header. | ||
for line in f: | ||
if (block == "none" or block == "metadata") and line.strip() == "---": | ||
if block == "none": | ||
block = "metadata" | ||
elif block == "metadata": | ||
block = "header" | ||
|
||
continue | ||
|
||
if block == "metadata" and line.startswith("author:") and line.strip("author:").strip() != "": | ||
author = line.strip("author:").strip() | ||
author = f"@{author}" | ||
continue | ||
|
||
if block == "metadata": | ||
continue | ||
|
||
if block == "header" or line.startswith("# "): | ||
if line.startswith("# "): | ||
title = line.strip("# ").strip() | ||
block = "header" | ||
continue | ||
|
||
if line.strip() == "": | ||
continue | ||
|
||
# Keep reading until the first H2 heading. | ||
if line.startswith("## "): | ||
break | ||
|
||
description.append(line.strip()) | ||
|
||
# Write the TOC entry as a row in a markdown table. | ||
toc.append(f"| [{title}]({'/'.join([samples_repo_uri, dir])}) | {' '.join(description)} | {author} |") | ||
|
||
# Write the TOC to a markdown file in a table with title and description. | ||
toc_file = os.path.join(repo_root_dir, "out", "samples_toc.md") | ||
with open(toc_file, "w") as f: | ||
f.write("| Title | Description | Author |\n") | ||
f.write("| ----- | ----------- | ------ |\n") | ||
for entry in toc: | ||
f.write(f"{entry}\n") | ||
|
||
def samples_shortcode(markdown: str, page: Page, config: MkDocsConfig, files: Files) -> str: | ||
'''Replace samples shortcodes in markdown.''' | ||
|
||
# Callback for regular expression replacement. | ||
def replace(match: re.Match) -> str: | ||
type, args = match.groups() | ||
args = args.strip() | ||
if type == "rules": | ||
return _samples_rules_fragment(args, page, config, files) | ||
|
||
raise RuntimeError(f"Unknown shortcode samples:{type}") | ||
|
||
# Replace samples shortcodes. | ||
return re.sub( | ||
r"<!-- samples:(\w+)(.*?) -->", | ||
replace, markdown, flags = re.I | re.M | ||
) | ||
|
||
def _samples_rules_fragment(args: str, page: Page, config: MkDocsConfig, files: Files) -> str: | ||
'''Replace samples shortcode with rules fragment.''' | ||
|
||
# Get the TOC fragment from the file. | ||
toc_file = os.path.join(config.docs_dir, "..", "out", "samples_toc.md") | ||
with open(toc_file, "r") as f: | ||
return f.read() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Samples | ||
|
||
You have reached the Azure community samples for PSRule. | ||
If you have a question about these samples, please start a discussion on GitHub. | ||
|
||
These samples are broken into the following categories: | ||
|
||
- `rules/` - Sample rules not shipped with PSRule for Azure. | ||
These samples do no align to Azure Well-Architected Framework (WAF), | ||
and should be considered as a starting point for custom rules. | ||
|
||
## Contributing samples | ||
|
||
Additional samples can be contributed. | ||
Please use the following structure for your `README.md`. | ||
Replace the comment placeholders with details about your sample. | ||
|
||
```markdown | ||
--- | ||
author: <github_username> | ||
--- | ||
|
||
# <title> | ||
|
||
<!-- a short one line description which will be included in table of contents --> | ||
|
||
## Summary | ||
|
||
<!-- describe what your sample does --> | ||
|
||
## Usage | ||
|
||
<!-- how to use your sample --> | ||
|
||
## References | ||
|
||
<!-- references to docs that help explain the detail. here is a few to get started, but remove if they are not relevant. --> | ||
|
||
- [Using custom rules](https://azure.github.io/PSRule.Rules.Azure/customization/using-custom-rules/) | ||
- [Conventions](https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Conventions/#including-with-options) | ||
``` | ||
|
||
When contributing a sample: | ||
|
||
- README.md: | ||
- Please update `author:` with your GitHub username to be credited in the table of contents. | ||
- Please give the sample a title. | ||
- Store each sample in a unique folder. i.e. `samples/<category>/<your_sample>`. | ||
- Prefix your sample rule or convention files with your folder name. i.e. `<your_sample>.Rule.ps1`. |
22 changes: 22 additions & 0 deletions
22
samples/rules/APIManagementPolicy/APIManagementPolicy.Rule.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# Licensed under the MIT License. | ||
|
||
# Synopsis: Imports API Management policy XML files in for analysis. | ||
Export-PSRuleConvention 'APIManagementPolicy.Import' -Initialize { | ||
$policies = @(Get-ChildItem -Path 'policies/' -Include '*.xml' -Recurse -File | ForEach-Object { | ||
$name = $_.Name | ||
[PSCustomObject]@{ | ||
Name = $name | ||
Content = [Xml](Get-Content -Path $_.FullName -Raw) | ||
} | ||
}) | ||
$PSRule.ImportWithType('Azure.APIM.PolicyContent', $policies) | ||
} | ||
|
||
# Synopsis: Checks that validate-jwt element exists in the policy. | ||
Rule 'APIManagementPolicy.ValidateJwt' -Type 'Azure.APIM.PolicyContent' { | ||
$policy = @([Xml]$TargetObject.Content.SelectNodes('//validate-jwt')) | ||
|
||
# Check that validate-jwt is used in the policy. | ||
$Assert.Greater($policy, '.', 1) | ||
} |
Oops, something went wrong.