Add initial rules and tests (#3)
- Add initial rules and tests - Add GitHub templates
This commit is contained in:
Родитель
9360a1e554
Коммит
70295c1836
|
@ -0,0 +1,2 @@
|
|||
# https://help.github.com/articles/about-codeowners/
|
||||
* @BernieWhite
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Report errors or unexpected behaviour
|
||||
---
|
||||
|
||||
**Description of the issue**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
Steps to reproduce the issue:
|
||||
|
||||
```powershell
|
||||
|
||||
```
|
||||
|
||||
**Expected behaviour**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Error output**
|
||||
|
||||
Capture any error messages and or verbose messages with `-Verbose`.
|
||||
|
||||
```text
|
||||
|
||||
```
|
||||
|
||||
**Module in use and version:**
|
||||
|
||||
- Module: PSRule.Rules.Kubernetes
|
||||
- Version: **[e.g. 0.1.0]**
|
||||
|
||||
Captured output from `$PSVersionTable`:
|
||||
|
||||
```text
|
||||
|
||||
```
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context about the problem here.
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
|
@ -0,0 +1,14 @@
|
|||
## PR Summary
|
||||
|
||||
<!-- summarize your PR between here and the checklist -->
|
||||
|
||||
## PR Checklist
|
||||
|
||||
- [ ] PR has a meaningful title
|
||||
- [ ] Summarized changes
|
||||
- [ ] Change is not breaking
|
||||
- [ ] This PR is ready to merge and is not **Work in Progress**
|
||||
- **Code changes**
|
||||
- [ ] Have unit tests created/ updated
|
||||
- [ ] Link to a filed issue
|
||||
- [ ] [Change log](https://github.com/BernieWhite/PSRule.Rules.Kubernetes/blob/master/CHANGELOG.md) has been updated with change under unreleased section
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"files.exclude": {
|
||||
"**/.git": true,
|
||||
"**/reports": true,
|
||||
"**/out": true
|
||||
}
|
||||
"reports/": true,
|
||||
"out/": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"out/": true
|
||||
},
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 4
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "test",
|
||||
"type": "shell",
|
||||
"command": "Invoke-Build Test",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [ "$pester" ],
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
## Unreleased
|
|
@ -0,0 +1,58 @@
|
|||
# PSRule for Kubernetes
|
||||
|
||||
A suite of rules to validate Kubernetes resources using PSRule.
|
||||
|
||||
![ci-badge]
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This project is to be considered a **proof-of-concept** and **not a supported product**.
|
||||
|
||||
For issues with rules and documentation please check our GitHub [issues](https://github.com/BernieWhite/PSRule.Rules.Kubernetes/issues) page. If you do not see your problem captured, please file a new issue and follow the provided template.
|
||||
|
||||
If you have any problems with the [PSRule][project] engine, please check the project GitHub [issues](https://github.com/BernieWhite/PSRule/issues) page instead.
|
||||
|
||||
## Getting the modules
|
||||
|
||||
This project requires the PowerShell module PSRule.
|
||||
|
||||
You can download and install these modules from the PowerShell Gallery.
|
||||
|
||||
Module | Description | Downloads / instructions
|
||||
------ | ----------- | ------------------------
|
||||
PSRule.Rules.Kubernetes | Validate Kubernetes resources | [latest][module] / [instructions][install]
|
||||
|
||||
## Getting started
|
||||
|
||||
### Offline with a manifest
|
||||
|
||||
Kubernetes resources can be evaluated within a YAML manifest file.
|
||||
|
||||
```powershell
|
||||
Invoke-PSRule -Module PSRule.Rules.Kubernetes -InputPath .\service.yaml;
|
||||
```
|
||||
|
||||
### Online with kubectl
|
||||
|
||||
```powershell
|
||||
Invoke-PSRule -Module PSRule.Rules.Kubernetes -InputObject (kubectl get services -o yaml | Out-String) -Format Yaml -ObjectPath items;
|
||||
```
|
||||
|
||||
## Changes and versioning
|
||||
|
||||
Modules in this repository will use the [semantic versioning](http://semver.org/) model to declare breaking changes from v1.0.0. Prior to v1.0.0, breaking changes may be introduced in minor (0.x.0) version increments. For a list of module changes please see the [change log](CHANGELOG.md).
|
||||
|
||||
> Pre-release module versions are created on major commits and can be installed from the PowerShell Gallery. Pre-release versions should be considered experimental. Modules and change log details for pre-releases will be removed as standard releases are made available.
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [Bernie White](https://github.com/BernieWhite)
|
||||
|
||||
## License
|
||||
|
||||
This project is [licensed under the MIT License](LICENSE).
|
||||
|
||||
[install]: docs/scenarios/install-instructions.md
|
||||
[ci-badge]: https://dev.azure.com/bewhite/PSRule.Rules.Kubernetes/_apis/build/status/PSRule.Rules.Kubernetes-CI?branchName=master
|
||||
[module]: https://www.powershellgallery.com/packages/PSRule.Rules.Kubernetes
|
||||
[project]: https://github.com/BernieWhite/PSRule
|
|
@ -0,0 +1,37 @@
|
|||
# Install instructions
|
||||
|
||||
## Prerequisites
|
||||
|
||||
A separate `PSRule` module is required for `PSRule.Rules.Kubernetes` to work. The required version will automatically be installed along-side `PSRule.Rules.Kubernetes` when using `Install-Module` or `Update-Module` cmdlets.
|
||||
|
||||
- Windows PowerShell 5.1 with .NET Framework 4.7.2+ or
|
||||
- PowerShell Core 6.0 or greater on Windows, macOS and Linux
|
||||
|
||||
For a list of platforms that PowerShell Core is supported on [see](https://github.com/PowerShell/PowerShell#get-powershell).
|
||||
|
||||
## Getting the modules
|
||||
|
||||
Install from [PowerShell Gallery][psg] for all users (requires permissions)
|
||||
|
||||
```powershell
|
||||
# Install PSRule module
|
||||
Install-Module -Name 'PSRule.Rules.Kubernetes';
|
||||
```
|
||||
|
||||
Install from [PowerShell Gallery][psg] for current user only
|
||||
|
||||
```powershell
|
||||
# Install PSRule module
|
||||
Install-Module -Name 'PSRule.Rules.Kubernetes' -Scope CurrentUser;
|
||||
```
|
||||
|
||||
Save for offline use from PowerShell Gallery
|
||||
|
||||
```powershell
|
||||
# Save PSRule module, in the .\modules directory
|
||||
Save-Module -Name 'PSRule', 'PSRule.Rules.Kubernetes' -Path '.\modules';
|
||||
```
|
||||
|
||||
> For pre-release versions the `-AllowPrerelease` switch must be added when calling `Install-Module` or `Save-Module`.
|
||||
|
||||
[psg]: https://www.powershellgallery.com/packages/PSRule.Rules.Kubernetes
|
|
@ -0,0 +1,107 @@
|
|||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Copy the PowerShell modules files to the destination path
|
||||
function CopyModuleFiles {
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $True)]
|
||||
[String]$Path,
|
||||
|
||||
[Parameter(Mandatory = $True)]
|
||||
[String]$DestinationPath
|
||||
)
|
||||
|
||||
process {
|
||||
$sourcePath = Resolve-Path -Path $Path;
|
||||
|
||||
Get-ChildItem -Path $sourcePath -Recurse -File -Include *.ps1,*.psm1,*.psd1,*.ps1xml | Where-Object -FilterScript {
|
||||
($_.FullName -notmatch '(\.(cs|csproj)|(\\|\/)(obj|bin))')
|
||||
} | ForEach-Object -Process {
|
||||
$filePath = $_.FullName.Replace($sourcePath, $destinationPath);
|
||||
|
||||
$parentPath = Split-Path -Path $filePath -Parent;
|
||||
|
||||
if (!(Test-Path -Path $parentPath)) {
|
||||
$Null = New-Item -Path $parentPath -ItemType Directory -Force;
|
||||
}
|
||||
|
||||
Copy-Item -Path $_.FullName -Destination $filePath -Force;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# Synopsis: Install NuGet provider
|
||||
task NuGet {
|
||||
if ($Null -eq (Get-PackageProvider -Name NuGet -ErrorAction Ignore)) {
|
||||
Install-PackageProvider -Name NuGet -Force -Scope CurrentUser;
|
||||
}
|
||||
}
|
||||
|
||||
# Synopsis: Install Pester module
|
||||
task Pester NuGet, {
|
||||
if ($Null -eq (Get-InstalledModule -Name Pester -MinimumVersion 4.0.0 -ErrorAction Ignore)) {
|
||||
Install-Module -Name Pester -MinimumVersion 4.0.0 -Scope CurrentUser -Force -SkipPublisherCheck;
|
||||
}
|
||||
Import-Module -Name Pester -Verbose:$False;
|
||||
}
|
||||
|
||||
# Synopsis: Install PSScriptAnalyzer module
|
||||
task PSScriptAnalyzer NuGet, {
|
||||
if ($Null -eq (Get-InstalledModule -Name PSScriptAnalyzer -MinimumVersion 1.17.0 -ErrorAction Ignore)) {
|
||||
Install-Module -Name PSScriptAnalyzer -MinimumVersion 1.17.0 -Scope CurrentUser -Force;
|
||||
}
|
||||
Import-Module -Name PSScriptAnalyzer -Verbose:$False;
|
||||
}
|
||||
|
||||
# Synopsis: Install PSRule
|
||||
task PSRule NuGet, {
|
||||
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.5.0 -ErrorAction Ignore)) {
|
||||
Install-Module -Name PSRule -MinimumVersion 0.5.0 -Scope CurrentUser -Force;
|
||||
}
|
||||
Import-Module -Name PSRule -Verbose:$False;
|
||||
}
|
||||
|
||||
task CopyModule {
|
||||
CopyModuleFiles -Path src/PSRule.Rules.Kubernetes -DestinationPath out/modules/PSRule.Rules.Kubernetes;
|
||||
|
||||
# Copy generated help into module out path
|
||||
# $Null = Copy-Item -Path docs/rules/en-US/* -Destination out/modules/PSrule.Rules.Kubernetes/en-US;
|
||||
# $Null = Copy-Item -Path docs/rules/en-US/* -Destination out/modules/PSrule.Rules.Kubernetes/en-AU;
|
||||
}
|
||||
|
||||
# Synopsis: Build modules only
|
||||
task BuildModule CopyModule
|
||||
|
||||
task TestRules PSRule, Pester, PSScriptAnalyzer, {
|
||||
# Run Pester tests
|
||||
$pesterParams = @{ Path = $PWD; OutputFile = 'reports/Pester.xml'; OutputFormat = 'NUnitXml'; PesterOption = @{ IncludeVSCodeMarker = $True }; PassThru = $True; };
|
||||
|
||||
if (!(Test-Path -Path reports)) {
|
||||
$Null = New-Item -Path reports -ItemType Directory -Force;
|
||||
}
|
||||
|
||||
$results = Invoke-Pester @pesterParams;
|
||||
|
||||
# Throw an error if pester tests failed
|
||||
if ($Null -eq $results) {
|
||||
throw 'Failed to get Pester test results.';
|
||||
}
|
||||
elseif ($results.FailedCount -gt 0) {
|
||||
throw "$($results.FailedCount) tests failed.";
|
||||
}
|
||||
}
|
||||
|
||||
# Synopsis: Remove temp files.
|
||||
task Clean {
|
||||
Remove-Item -Path out,reports -Recurse -Force -ErrorAction SilentlyContinue;
|
||||
}
|
||||
|
||||
task Build Clean, BuildModule
|
||||
|
||||
task Test Build, TestRules
|
||||
|
||||
task . Build
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# CI script for integration with Azure DevOps
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $True)]
|
||||
[String]$File,
|
||||
|
||||
[Parameter(Mandatory = $False)]
|
||||
[String]$Task
|
||||
)
|
||||
|
||||
if ($Null -eq (Get-PackageProvider -Name NuGet -ErrorAction Ignore)) {
|
||||
Install-PackageProvider -Name NuGet -Force -Scope CurrentUser;
|
||||
}
|
||||
|
||||
if ($Null -eq (Get-InstalledModule -Name InvokeBuild -MinimumVersion 5.4.0 -ErrorAction Ignore)) {
|
||||
Install-Module InvokeBuild -MinimumVersion 5.4.0 -Scope CurrentUser -Force;
|
||||
}
|
||||
|
||||
Invoke-Build @PSBoundParameters
|
|
@ -0,0 +1,123 @@
|
|||
#
|
||||
# PSRule.Rules.Kubernetes
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
# RootModule = ''
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.0.1'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = 'Core', 'Desktop'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'efaacb4d-b447-4de3-96b9-93860fd87a8c'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Bernie White'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'Bernie White'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = '(c) Bernie White. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Validate Kubernetes resources using PSRule.
|
||||
|
||||
This project is to be considered a proof-of-concept and not a supported product.'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '5.1'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
DotNetFrameworkVersion = '4.7.2'
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
RequiredModules = @(
|
||||
@{ ModuleName = 'PSRule'; ModuleVersion = '0.5.0' }
|
||||
)
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @()
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
Tags = @('PSRule', 'Rule', 'Kubernetes')
|
||||
|
||||
# A URL to the license for this module.
|
||||
LicenseUri = 'https://github.com/BernieWhite/PSRule.Rules.Kubernetes/blob/master/LICENSE'
|
||||
|
||||
# A URL to the main website for this project.
|
||||
ProjectUri = 'https://github.com/BernieWhite/PSRule.Rules.Kubernetes'
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
ReleaseNotes = 'https://github.com/BernieWhite/PSRule.Rules.Kubernetes/blob/master/CHANGELOG.md'
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Validation rules for Azure Kubernetes Service (AKS)
|
||||
#
|
||||
|
||||
# Description: Services should not include a public load balancer
|
||||
Rule 'Kubernetes.AKS.PublicLoadBalancer' -Type Service -Tag @{ category = 'Service exposure'; severity = 'Critical'; } -If { $Rule.TargetName -ne 'addon-http-application-routing-nginx-ingress' } {
|
||||
AnyOf {
|
||||
Exists 'spec.type' -Not
|
||||
$TargetObject.spec.type -ne 'LoadBalancer'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Validation rules for Kubernetes deployments
|
||||
#
|
||||
|
||||
# Description: Containers should deny privilege escalation
|
||||
Rule 'Kubernetes.Deployment.PrivilegeEscalation' -Type Deployment -Tag @{ category = 'Pod security'; severity = 'Critical'; } {
|
||||
foreach ($container in $TargetObject.spec.template.spec.containers) {
|
||||
$container | Exists 'securityContext.allowPrivilegeEscalation'
|
||||
$container.securityContext.allowPrivilegeEscalation -eq $False
|
||||
}
|
||||
}
|
||||
|
||||
# Description: Containers should use specific tags instead of latest
|
||||
Rule 'Kubernetes.Deployment.NotLatestImage' -Type Deployment -Tag @{ category = 'Pod security'; severity = 'Important' } {
|
||||
foreach ($container in $TargetObject.spec.template.spec.containers) {
|
||||
$container.image -like '*:*' -and
|
||||
$container.image -notlike '*:latest'
|
||||
}
|
||||
}
|
||||
|
||||
# Description: Resource requirements are set for each container
|
||||
Rule 'Kubernetes.Deployment.ResourcesSet' -Type Deployment -Tag @{ category = 'Resource management'; severity = 'Important' } {
|
||||
foreach ($container in $TargetObject.spec.template.spec.containers) {
|
||||
$container | Exists 'resources.requests.cpu'
|
||||
$container | Exists 'resources.requests.memory'
|
||||
$container | Exists 'resources.limits.cpu'
|
||||
$container | Exists 'resources.limits.memory'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# Validation rules for Kubernetes metadata requirements
|
||||
#
|
||||
|
||||
# Description: Must have the app.kubernetes.io/name label
|
||||
Rule 'Kubernetes.Metadata' -Type 'Deployment', 'Service' -Tag @{ category = 'Resource management'; severity = 'Important' } {
|
||||
Exists 'metadata.labels.''app.kubernetes.io/name'''
|
||||
Exists 'metadata.labels.''app.kubernetes.io/version'''
|
||||
Exists 'metadata.labels.''app.kubernetes.io/component'''
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#
|
||||
# Unit tests for Kubernetes AKS rules
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Kubernetes) -Force;
|
||||
$here = (Resolve-Path $PSScriptRoot).Path;
|
||||
|
||||
Describe 'Kubernetes.AKS' {
|
||||
$testParams = @{
|
||||
Module = 'PSRule.Rules.Kubernetes'
|
||||
Option = Join-Path -Path $here -ChildPath ps-rule.yaml
|
||||
InputPath = Join-Path -Path $here -ChildPath Resources.AKS.yaml
|
||||
}
|
||||
|
||||
$result = Invoke-PSRule @testParams -WarningAction Ignore;
|
||||
|
||||
Context 'Security' {
|
||||
It 'Kubernetes.AKS.PublicLoadBalancer' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Kubernetes.AKS.PublicLoadBalancer' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'service-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'service-A';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#
|
||||
# Unit tests for Kubernetes deployment rules
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Kubernetes) -Force;
|
||||
$here = (Resolve-Path $PSScriptRoot).Path;
|
||||
|
||||
Describe 'Kubernetes.Deployment' {
|
||||
$testParams = @{
|
||||
Module = 'PSRule.Rules.Kubernetes'
|
||||
Option = Join-Path -Path $here -ChildPath ps-rule.yaml
|
||||
InputPath = Join-Path -Path $here -ChildPath Resources.Deployment.yaml
|
||||
}
|
||||
|
||||
$result = Invoke-PSRule @testParams -WarningAction Ignore;
|
||||
|
||||
Context 'Security' {
|
||||
It 'Kubernetes.Deployment.PrivilegeEscalation' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Kubernetes.Deployment.PrivilegeEscalation' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-A';
|
||||
}
|
||||
|
||||
It 'Kubernetes.Deployment.NotLatestImage' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Kubernetes.Deployment.NotLatestImage' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-A';
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Resource management' {
|
||||
It 'Kubernetes.Deployment.ResourcesSet' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Kubernetes.Deployment.ResourcesSet' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'deployment-A';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#
|
||||
# Unit tests for Kubernetes metadata rules
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Kubernetes) -Force;
|
||||
$here = (Resolve-Path $PSScriptRoot).Path;
|
||||
|
||||
Describe 'Kubernetes.Metadata' {
|
||||
$testParams = @{
|
||||
Module = 'PSRule.Rules.Kubernetes'
|
||||
Option = Join-Path -Path $here -ChildPath ps-rule.yaml
|
||||
InputPath = Join-Path -Path $here -ChildPath Resources.Metadata.yaml
|
||||
}
|
||||
|
||||
$result = Invoke-PSRule @testParams -WarningAction Ignore;
|
||||
|
||||
Context 'Resource metadata' {
|
||||
It 'Kubernetes.Metadata' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Kubernetes.Metadata' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 2;
|
||||
$ruleResult.TargetName | Should -BeIn 'deployment-B', 'service-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 2;
|
||||
$ruleResult.TargetName | Should -BeIn 'deployment-A', 'service-A';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# Unit tests for validating module for publishing
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
$modulePath = Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Kubernetes;
|
||||
|
||||
Describe 'PSRule.Rules.Kubernetes' -Tag 'PowerShellGallery' {
|
||||
Context 'Module' {
|
||||
It 'Can be imported' {
|
||||
Import-Module $modulePath -Force;
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Manifest' {
|
||||
$manifestPath = (Join-Path -Path $modulePath -ChildPath PSRule.Rules.Kubernetes.psd1);
|
||||
$result = Test-ModuleManifest -Path $manifestPath;
|
||||
|
||||
It 'Has required fields' {
|
||||
$result.Name | Should -Be 'PSRule.Rules.Kubernetes';
|
||||
$result.Description | Should -Not -BeNullOrEmpty;
|
||||
$result.LicenseUri | Should -Not -BeNullOrEmpty;
|
||||
$result.ReleaseNotes | Should -Not -BeNullOrEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Static analysis' {
|
||||
$result = Invoke-ScriptAnalyzer -Path $modulePath;
|
||||
|
||||
$warningCount = ($result | Where-Object { $_.Severity -eq 'Warning' } | Measure-Object).Count;
|
||||
$errorCount = ($result | Where-Object { $_.Severity -eq 'Error' } | Measure-Object).Count;
|
||||
|
||||
if ($warningCount -gt 0) {
|
||||
Write-Warning -Message "PSScriptAnalyzer reports $warningCount warnings.";
|
||||
}
|
||||
|
||||
It 'Has no quality errors' {
|
||||
$errorCount | Should -BeLessOrEqual 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Kubernetes Service resources for unit tests
|
||||
#
|
||||
|
||||
---
|
||||
# An example service that should pass all rules.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-A
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
name: http
|
||||
selector:
|
||||
app: app-A
|
||||
|
||||
---
|
||||
# This service should fail kubernetes.AKS.PublicLoadBalancer
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-B
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 6379
|
||||
selector:
|
||||
app: app-B
|
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# Kubernetes Deployment resources for unit tests
|
||||
#
|
||||
|
||||
---
|
||||
# An example deployment that should pass all rules.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-A
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: app-A
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: app-A
|
||||
spec:
|
||||
containers:
|
||||
- name: app-a
|
||||
image: app-a-image:v1
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-B
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: app-B
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: app-B
|
||||
spec:
|
||||
containers:
|
||||
- name: app-b
|
||||
image: app-b-image
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
# An example deployment that should pass all rules.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-A
|
||||
labels:
|
||||
app.kubernetes.io/name: solution-A
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
app.kubernetes.io/component: unit-test
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: app-A
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: app-A
|
||||
spec:
|
||||
containers:
|
||||
- name: green-app
|
||||
image: green-image:v1
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-B
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: unconstrained-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: unconstrained-app
|
||||
spec:
|
||||
containers:
|
||||
- name: unconstrained-app
|
||||
image: unconstrained-image
|
||||
|
||||
|
||||
---
|
||||
# An example service that should pass all rules.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-A
|
||||
labels:
|
||||
app.kubernetes.io/name: solution-A
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
app.kubernetes.io/component: unit-test
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
name: http
|
||||
selector:
|
||||
app: app-A
|
||||
|
||||
---
|
||||
# This service should fail kubernetes.AKS.PublicLoadBalancer
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-B
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 6379
|
||||
selector:
|
||||
app: red-app
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Unit tests for PSRule rule quality
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Kubernetes) -Force;
|
||||
$here = (Resolve-Path $PSScriptRoot).Path;
|
||||
|
||||
Describe 'Rule quality' {
|
||||
Context 'Metadata' {
|
||||
$result = Get-PSRule -Module PSRule.Rules.Kubernetes -WarningAction Ignore;
|
||||
|
||||
foreach ($rule in $result) {
|
||||
It $rule.RuleName {
|
||||
$rule.Description | Should -Not -BeNullOrEmpty;
|
||||
$rule.Tag.severity | Should -Not -BeNullOrEmpty;
|
||||
$rule.Tag.category | Should -Not -BeNullOrEmpty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
binding:
|
||||
targetName:
|
||||
- metadata.name
|
||||
targetType:
|
||||
- kind
|
||||
|
||||
execution:
|
||||
notProcessedWarning: false
|
Загрузка…
Ссылка в новой задаче