From 2a190d4a7776b88962b50090255b60c79c9feeb5 Mon Sep 17 00:00:00 2001 From: Bernie White Date: Fri, 3 Jan 2020 10:43:06 +1000 Subject: [PATCH] Updated and renamed baselines #27 (#28) --- CHANGELOG.md | 6 ++++++ README.md | 20 ++++++++++++++++--- pipeline.build.ps1 | 14 ++++++------- .../PSRule.Rules.Kubernetes.psd1 | 4 ++-- .../rules/Baseline.Rule.yaml | 10 ++++++++-- .../rules/Kubernetes.AKS.Rule.ps1 | 2 +- .../rules/Kubernetes.API.Rule.ps1 | 2 +- .../rules/Kubernetes.Metadata.Rule.ps1 | 2 +- .../rules/Kubernetes.Pod.Rule.ps1 | 12 +++++------ .../Kubernetes.AKS.Tests.ps1 | 2 +- .../Rule.Common.Tests.ps1 | 2 +- 11 files changed, 51 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf1ba0c..4ad069b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +- **Breaking change**: Updated and renamed baselines make them easier to use. [#27](https://github.com/BernieWhite/PSRule.Rules.Kubernetes/issues/27) + - `KubeBaseline` is now `Kubernetes`, the default baseline. + - `AKSBaseline` is now `AKS`. + - The `Kubernetes` baseline include common Kubernetes rules. + - The `AKS` baseline include all of `Kubernetes` plus additional AKS specific rules. + ## v0.1.0-B1912003 (pre-release) - Fixed `Kubernetes.AKS.PublicLB` handling of internal LB annotation. [#17](https://github.com/BernieWhite/PSRule.Rules.Kubernetes/issues/17) diff --git a/README.md b/README.md index d12b0a5..3d553c6 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,6 @@ Kubernetes.Pod.Resources Fail Resource requirements are set for Kubernetes.Pod.Secrets Pass Use Kubernetes secrets to store information such as passwords or connec… Kubernetes.Pod.Health Fail Containers should use liveness and readiness probes. Kubernetes.Pod.Replicas Fail Consider increasing replicas to two or more to provide high availabilit… -Kubernetes.AKS.PublicLB Pass Consider creating services with an internal load balancer instead of a … Kubernetes.Metadata Fail Consider applying recommended labels defined by Kubernetes.… TargetName: azure-vote-front @@ -78,7 +77,6 @@ Kubernetes.Pod.Resources Fail Resource requirements are set for Kubernetes.Pod.Secrets Pass Use Kubernetes secrets to store information such as passwords or connec… Kubernetes.Pod.Health Fail Containers should use liveness and readiness probes. Kubernetes.Pod.Replicas Fail Consider increasing replicas to two or more to provide high availabilit… -Kubernetes.AKS.PublicLB Fail Consider creating services with an internal load balancer instead of a … Kubernetes.Metadata Fail Consider applying recommended labels defined by Kubernetes.… ``` @@ -99,6 +97,23 @@ In the example above: - `-Format Yaml` - indicates that the input is YAML. - `-ObjectPath items` - indicates that the input nests objects to evaluate under the `items` property. +### Using baselines + +PSRule for Kubernetes comes with the following baselines: + +- `Kubernetes` - Includes common Kubernetes rules. This is the default. +- `AKS` - Includes all the rules from `Kubernetes` plus additional Azure Kubernetes Service (AKS) specific rules. + +To use the `AKS` baseline instead of the default use `Invoke-PSRule -Baseline AKS`. + +For example: + +```powershell +Invoke-PSRule -f $sourceUrl -Module 'PSRule.Rules.Kubernetes' -Baseline AKS; +``` + +If `-Baseline AKS` is not specified, the default baseline `Kubernetes` will be used. + ### Additional options To filter results to only failed rules, use `Invoke-PSRule -Outcome Fail`. @@ -125,7 +140,6 @@ The output of this example is: ```text RuleName Pass Fail Outcome -------- ---- ---- ------- -Kubernetes.AKS.PublicLB 1 1 Fail Kubernetes.API.Removal 0 2 Fail Kubernetes.Metadata 0 4 Fail Kubernetes.Pod.PrivilegeEscalation 0 2 Fail diff --git a/pipeline.build.ps1 b/pipeline.build.ps1 index 9c60151..caf64ab 100644 --- a/pipeline.build.ps1 +++ b/pipeline.build.ps1 @@ -100,7 +100,7 @@ task VersionModule ModuleDependencies, { $manifest = Test-ModuleManifest -Path $manifestPath; $requiredModules = $manifest.RequiredModules | ForEach-Object -Process { if ($_.Name -eq 'PSRule' -and $Configuration -eq 'Release') { - @{ ModuleName = 'PSRule'; ModuleVersion = '0.11.0' } + @{ ModuleName = 'PSRule'; ModuleVersion = '0.12.0' } } else { @{ ModuleName = $_.Name; ModuleVersion = $_.Version } @@ -108,7 +108,7 @@ task VersionModule ModuleDependencies, { }; Update-ModuleManifest -Path $manifestPath -RequiredModules $requiredModules; $manifestContent = Get-Content -Path $manifestPath -Raw; - $manifestContent = $manifestContent -replace 'PSRule = ''System.Collections.Hashtable''', 'PSRule = @{ Baseline = ''KubeBaseline'' }'; + $manifestContent = $manifestContent -replace 'PSRule = ''System.Collections.Hashtable''', 'PSRule = @{ Baseline = ''Kubernetes'' }'; $manifestContent | Set-Content -Path $manifestPath; } @@ -150,8 +150,8 @@ task PSScriptAnalyzer NuGet, { # Synopsis: Install PSRule task PSRule NuGet, { - if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.11.0 -ErrorAction Ignore)) { - Install-Module -Name PSRule -MinimumVersion 0.11.0 -Scope CurrentUser -Force; + if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.12.0 -ErrorAction Ignore)) { + Install-Module -Name PSRule -MinimumVersion 0.12.0 -Scope CurrentUser -Force; } Import-Module -Name PSRule -Verbose:$False; } @@ -238,9 +238,9 @@ task BuildHelp BuildModule, PlatyPS, { } # Copy generated help into module out path - # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/ -Destination out/modules/PSRule.Rules.Kubernetes/en-US/ -Recurse; - # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/ -Destination out/modules/PSRule.Rules.Kubernetes/en-AU/ -Recurse; - # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/ -Destination out/modules/PSRule.Rules.Kubernetes/en-GB/ -Recurse; + # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/* -Destination out/modules/PSRule.Rules.Kubernetes/en-US/ -Recurse; + # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/* -Destination out/modules/PSRule.Rules.Kubernetes/en-AU/ -Recurse; + # $Null = Copy-Item -Path out/docs/PSRule.Rules.Kubernetes/* -Destination out/modules/PSRule.Rules.Kubernetes/en-GB/ -Recurse; $Null = Copy-Item -Path docs/rules/en-US/*.md -Destination out/modules/PSRule.Rules.Kubernetes/en-US/; $Null = Copy-Item -Path docs/rules/en-US/*.md -Destination out/modules/PSRule.Rules.Kubernetes/en-AU/; $Null = Copy-Item -Path docs/rules/en-US/*.md -Destination out/modules/PSRule.Rules.Kubernetes/en-GB/; diff --git a/src/PSRule.Rules.Kubernetes/PSRule.Rules.Kubernetes.psd1 b/src/PSRule.Rules.Kubernetes/PSRule.Rules.Kubernetes.psd1 index c40f007..813b009 100644 --- a/src/PSRule.Rules.Kubernetes/PSRule.Rules.Kubernetes.psd1 +++ b/src/PSRule.Rules.Kubernetes/PSRule.Rules.Kubernetes.psd1 @@ -75,7 +75,7 @@ FunctionsToExport = @() CmdletsToExport = @() # Variables to export from this module -VariablesToExport = '*' +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 = @() @@ -108,7 +108,7 @@ PrivateData = @{ ReleaseNotes = 'https://github.com/BernieWhite/PSRule.Rules.Kubernetes/blob/master/CHANGELOG.md' } # End of PSData hashtable PSRule = @{ - Baseline = 'KubeBaseline' + Baseline = 'Kubernetes' } } # End of PrivateData hashtable diff --git a/src/PSRule.Rules.Kubernetes/rules/Baseline.Rule.yaml b/src/PSRule.Rules.Kubernetes/rules/Baseline.Rule.yaml index ec1fe26..fe1d144 100644 --- a/src/PSRule.Rules.Kubernetes/rules/Baseline.Rule.yaml +++ b/src/PSRule.Rules.Kubernetes/rules/Baseline.Rule.yaml @@ -3,7 +3,7 @@ # Synopsis: A baseline for Kubernetes. kind: Baseline metadata: - name: KubeBaseline + name: Kubernetes spec: binding: targetName: @@ -12,12 +12,15 @@ spec: - kind field: namespace: [ 'metadata.namespace' ] + rule: + tag: + group: core --- # Synopsis: A baseline for Azure Kubernetes Service (AKS). kind: Baseline metadata: - name: AKSBaseline + name: AKS spec: binding: targetName: @@ -26,3 +29,6 @@ spec: - kind field: namespace: [ 'metadata.namespace' ] + rule: + tag: + group: [ 'core', 'AKS' ] diff --git a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.AKS.Rule.ps1 b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.AKS.Rule.ps1 index a254361..43ffc9f 100644 --- a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.AKS.Rule.ps1 +++ b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.AKS.Rule.ps1 @@ -3,7 +3,7 @@ # # Synopsis: Services should not include a public load balancer -Rule 'Kubernetes.AKS.PublicLB' -Type Service -Tag @{ category = 'Pod security' } -If { $PSRule.TargetName -ne 'addon-http-application-routing-nginx-ingress' } { +Rule 'Kubernetes.AKS.PublicLB' -Type Service -If { $PSRule.TargetName -ne 'addon-http-application-routing-nginx-ingress' } -Tag @{ group = 'AKS' } { if ($Assert.HasFieldValue($TargetObject, 'spec.type', 'LoadBalancer').Result) { Within 'metadata.annotations.''service.beta.kubernetes.io/azure-load-balancer-internal''' 'true' } diff --git a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.API.Rule.ps1 b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.API.Rule.ps1 index b4c6f96..2ebc1e3 100644 --- a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.API.Rule.ps1 +++ b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.API.Rule.ps1 @@ -3,7 +3,7 @@ # # Synopsis: Avoid using legacy API endpoints -Rule 'Kubernetes.API.Removal' -Type DaemonSet, Deployment, StatefulSet, ReplicaSet, NetworkPolicy, PodSecurityPolicy -Tag @{ category = 'API' } { +Rule 'Kubernetes.API.Removal' -Type DaemonSet, Deployment, StatefulSet, ReplicaSet, NetworkPolicy, PodSecurityPolicy -Tag @{ group = 'core' } { if ($PSRule.TargetType -in 'DaemonSet', 'Deployment', 'StatefulSet', 'ReplicaSet') { $TargetObject.apiVersion -eq 'apps/v1' } diff --git a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Metadata.Rule.ps1 b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Metadata.Rule.ps1 index 3e1610a..4aead88 100644 --- a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Metadata.Rule.ps1 +++ b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Metadata.Rule.ps1 @@ -3,7 +3,7 @@ # # Synopsis: Use recommended labels -Rule 'Kubernetes.Metadata' -Type 'Deployment', 'Service', 'ReplicaSet', 'Pod' -Tag @{ category = 'Resource management'; } { +Rule 'Kubernetes.Metadata' -Type 'Deployment', 'Service', 'ReplicaSet', 'Pod' -Tag @{ group = 'core' } { Exists 'metadata.labels.''app.kubernetes.io/name''' -Reason ($LocalizedData.RecommendLabel -f 'app.kubernetes.io/name') Exists 'metadata.labels.''app.kubernetes.io/instance''' -Reason ($LocalizedData.RecommendLabel -f 'app.kubernetes.io/instance') Exists 'metadata.labels.''app.kubernetes.io/version''' -Reason ($LocalizedData.RecommendLabel -f 'app.kubernetes.io/version') diff --git a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Pod.Rule.ps1 b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Pod.Rule.ps1 index 0ff226e..a7af053 100644 --- a/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Pod.Rule.ps1 +++ b/src/PSRule.Rules.Kubernetes/rules/Kubernetes.Pod.Rule.ps1 @@ -3,7 +3,7 @@ # # Synopsis: Containers should deny privilege escalation -Rule 'Kubernetes.Pod.PrivilegeEscalation' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ category = 'Pod security'; } { +Rule 'Kubernetes.Pod.PrivilegeEscalation' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ group = 'core' } { foreach ($container in (GetContainerSpec)) { $container | Exists 'securityContext.allowPrivilegeEscalation' $container.securityContext.allowPrivilegeEscalation -eq $False @@ -11,7 +11,7 @@ Rule 'Kubernetes.Pod.PrivilegeEscalation' -Type Deployment, Pod, ReplicaSet -If } # Synopsis: Containers should use specific tags instead of latest -Rule 'Kubernetes.Pod.Latest' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ category = 'Pod security'; } { +Rule 'Kubernetes.Pod.Latest' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ group = 'core' } { foreach ($container in (GetContainerSpec)) { $container.image -like '*:*' -and $container.image -notlike '*:latest' @@ -19,7 +19,7 @@ Rule 'Kubernetes.Pod.Latest' -Type Deployment, Pod, ReplicaSet -If { (HasContain } # Synopsis: Resource requirements are set for each container -Rule 'Kubernetes.Pod.Resources' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ category = 'Resource management'; } { +Rule 'Kubernetes.Pod.Resources' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ group = 'core' } { foreach ($container in (GetContainerSpec)) { $container | Exists 'resources.requests.cpu' -Reason $LocalizedData.PodCPURequest $container | Exists 'resources.requests.memory' -Reason $LocalizedData.PodMemRequest @@ -29,7 +29,7 @@ Rule 'Kubernetes.Pod.Resources' -Type Deployment, Pod, ReplicaSet -If { (HasCont } # Synopsis: Sensitive environment variables should be secured -Rule 'Kubernetes.Pod.Secrets' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ category = 'Pod security'; } { +Rule 'Kubernetes.Pod.Secrets' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ group = 'core' } { foreach ($container in (GetContainerSpec)) { if ($Assert.HasField($container, 'env').Result) { foreach ($variable in $container.env) { @@ -48,7 +48,7 @@ Rule 'Kubernetes.Pod.Secrets' -Type Deployment, Pod, ReplicaSet -If { (HasContai } # Synopsis: Containers should use liveness and readiness probes -Rule 'Kubernetes.Pod.Health' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ category = 'Reliability'; } { +Rule 'Kubernetes.Pod.Health' -Type Deployment, Pod, ReplicaSet -If { (HasContainerSpec) } -Tag @{ group = 'core' } { foreach ($container in (GetContainerSpec)) { $container | Exists 'livenessProbe' -Reason ($LocalizedData.LivenessProbe -f $container.name) } @@ -58,7 +58,7 @@ Rule 'Kubernetes.Pod.Health' -Type Deployment, Pod, ReplicaSet -If { (HasContain } # Synopsis: Use two or more replicas -Rule 'Kubernetes.Pod.Replicas' -Type Deployment, ReplicaSet, StatefulSet -Tag @{ category = 'Reliability'; } { +Rule 'Kubernetes.Pod.Replicas' -Type Deployment, ReplicaSet, StatefulSet -Tag @{ group = 'core' } { Exists 'spec.replicas' $TargetObject.spec.replicas -ge 2 } diff --git a/tests/PSRule.Rules.Kubernetes.Tests/Kubernetes.AKS.Tests.ps1 b/tests/PSRule.Rules.Kubernetes.Tests/Kubernetes.AKS.Tests.ps1 index a71aedb..cc8445c 100644 --- a/tests/PSRule.Rules.Kubernetes.Tests/Kubernetes.AKS.Tests.ps1 +++ b/tests/PSRule.Rules.Kubernetes.Tests/Kubernetes.AKS.Tests.ps1 @@ -23,8 +23,8 @@ $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 + Baseline = 'AKS' } $result = Invoke-PSRule @testParams -WarningAction Ignore; diff --git a/tests/PSRule.Rules.Kubernetes.Tests/Rule.Common.Tests.ps1 b/tests/PSRule.Rules.Kubernetes.Tests/Rule.Common.Tests.ps1 index b738bcd..a1309b1 100644 --- a/tests/PSRule.Rules.Kubernetes.Tests/Rule.Common.Tests.ps1 +++ b/tests/PSRule.Rules.Kubernetes.Tests/Rule.Common.Tests.ps1 @@ -36,7 +36,7 @@ Describe 'Rule quality' { It $rule.RuleName { $rule.Synopsis | Should -Not -BeNullOrEmpty; $rule.Description | Should -Not -BeNullOrEmpty; - $rule.Tag.category | Should -Not -BeNullOrEmpty; + $rule.Info.Annotations.category | Should -Not -BeNullOrEmpty; $rule.Info.Annotations.severity | Should -Not -BeNullOrEmpty; $rule.Info.GetOnlineHelpUri() | Should -Not -BeNullOrEmpty; }