├── .gitignore ├── CustomRules ├── CustomRules.psm1 ├── PSScriptAnalyzer.Tests.ps1 ├── PSScriptAnalyzerSettings.psd1 ├── ast.ps1 ├── public │ ├── AvoidUninitializedVariableInModule.ps1 │ ├── AvoidUninitializedVariableInPolicy.ps1 │ ├── UseCamelCase.ps1 │ └── helper │ │ └── Invoke-CustomScriptAnalyzer.ps1 ├── rulesLib.ps1 └── tests │ └── AvoidUninitializedVariable.Tests.ps1 ├── Jenkinsfile ├── LICENSE ├── LICENSES └── gpl-3.0-or-later.txt ├── Makefile ├── PSScriptAnalyzerSettingsPolicy.psd1 ├── README.adoc ├── bootstrap-promises └── failsafe.cf ├── ci ├── cf-promises.Dockerfile ├── common.Dockerfile └── linter.Dockerfile ├── contrib └── NTPConfiguration.txz ├── generate_initial_policies.py ├── maintained-techniques ├── properties.json ├── qa-test ├── rudderVariables.psd1 ├── scripts ├── check-techniques.sh ├── ordering.pl └── xval.pl ├── technique-metadata-sample.xml ├── techniques ├── applications │ ├── aptPackageManagerSettings │ │ ├── 3.1 │ │ │ ├── aptPackageManagerSettings.st │ │ │ ├── changelog │ │ │ └── metadata.xml │ │ └── 3.2 │ │ │ ├── aptPackageManagerSettings.st │ │ │ ├── changelog │ │ │ └── metadata.xml │ ├── category.xml │ ├── packageManagement │ │ └── 1.3 │ │ │ ├── changelog │ │ │ ├── metadata.xml │ │ │ └── packageManagement.st │ ├── repoGpgKeyManagement │ │ └── 1.1 │ │ │ ├── changelog │ │ │ ├── metadata.xml │ │ │ └── repoGpgKeyManagement.st │ ├── snmp │ │ └── 1.0 │ │ │ ├── metadata.xml │ │ │ ├── snmp.ps1.st │ │ │ ├── snmp.st │ │ │ ├── snmp_communities.ps1 │ │ │ └── snmp_sources.ps1 │ ├── zypperPackageManagerRepositories │ │ └── 1.0 │ │ │ ├── changelog │ │ │ ├── metadata.xml │ │ │ ├── zypper-repo.tml │ │ │ └── zypper-repositories-management.st │ └── zypperPackageManagerSetup │ │ └── 1.0 │ │ ├── changelog │ │ ├── metadata.xml │ │ └── zypper-package-manager-setup.st ├── category.xml ├── default-directive-names.conf ├── fileConfiguration │ ├── category.xml │ ├── fileManagement │ │ └── 4.1 │ │ │ ├── changelog │ │ │ ├── manageFilesAndFolders.st │ │ │ └── metadata.xml │ └── fileSecurity │ │ ├── category.xml │ │ └── filesPermissions │ │ └── 2.2 │ │ ├── changelog │ │ ├── filesPermissions.st │ │ ├── metadata.xml │ │ └── permlist.st ├── fileDistribution │ ├── category.xml │ ├── checkGenericFileContent │ │ └── 8.0 │ │ │ ├── changelog │ │ │ ├── checkGenericFileContent.st │ │ │ ├── metadata.xml │ │ │ └── tests │ │ │ ├── simple_content_enforce.json │ │ │ ├── simple_content_enforce.metadata │ │ │ ├── simple_content_enforce.rb │ │ │ ├── simple_content_replace.cf │ │ │ ├── simple_content_replace.json │ │ │ ├── simple_content_replace.metadata │ │ │ └── simple_content_replace.rb │ ├── copyGitFile │ │ └── 2.3 │ │ │ ├── changelog │ │ │ ├── copyFileFromSharedFolder.ps1.st │ │ │ ├── copyFileFromSharedFolder.st │ │ │ └── metadata.xml │ ├── downloadFile │ │ └── 4.0 │ │ │ ├── changelog │ │ │ ├── downloadFile.st │ │ │ └── metadata.xml │ ├── fileTemplate │ │ └── 1.0 │ │ │ ├── fileTemplate.ps1.st │ │ │ ├── fileTemplate.st │ │ │ ├── metadata.xml │ │ │ └── tests │ │ │ ├── loadVars.json │ │ │ ├── template1 │ │ │ ├── test_error_fileTemplate │ │ │ ├── test_error_fileTemplate.cf │ │ │ ├── test_error_fileTemplate.json │ │ │ ├── test_error_fileTemplate.metadata │ │ │ └── test_error_fileTemplate.rb │ │ │ ├── test_fileTemplate │ │ │ ├── test_fileTemplate.json │ │ │ ├── test_fileTemplate.metadata │ │ │ └── test_fileTemplate.rb │ │ │ └── test_posthook │ │ │ ├── test_posthook.cf │ │ │ ├── test_posthook.json │ │ │ ├── test_posthook.metadata │ │ │ └── test_posthook.rb │ └── manageKeyValueFile │ │ └── 1.3 │ │ ├── changelog │ │ ├── manage-key-value-file.st │ │ ├── metadata.xml │ │ └── tests │ │ ├── simple_key_create.cf │ │ ├── simple_key_create.metadata │ │ ├── simple_key_replace.cf │ │ ├── simple_key_replace.json │ │ ├── simple_key_replace.metadata │ │ └── simple_key_replace.rb ├── jobScheduling │ ├── category.xml │ └── jobScheduler │ │ └── 3.0 │ │ ├── changelog │ │ ├── job_scheduler.st │ │ └── metadata.xml ├── ncf_techniques │ └── category.xml ├── system │ ├── category.xml │ ├── common │ │ └── 1.0 │ │ │ ├── cf-serverd.st │ │ │ ├── common.st │ │ │ ├── cron-setup.cf │ │ │ ├── environment-variables.cf │ │ │ ├── failsafe.st │ │ │ ├── hooks.cf │ │ │ ├── internal-security.cf │ │ │ ├── metadata.xml │ │ │ ├── monitoring.cf │ │ │ ├── promises.st │ │ │ ├── properties.cf │ │ │ ├── reporting-http.cf │ │ │ ├── rpm-key.cf │ │ │ ├── rudder-agent-community-cron │ │ │ ├── rudder-directives.st │ │ │ ├── rudder-groups.st │ │ │ ├── rudder-parameters.st │ │ │ ├── rudder-promises-generated.st │ │ │ ├── rudder-system-directives.st │ │ │ ├── rudder-vars.st │ │ │ ├── rudder_promises_generated.st │ │ │ ├── rudder_release_key.pub │ │ │ ├── run_interval.st │ │ │ ├── site.cf │ │ │ └── update.st │ ├── inventory │ │ └── 1.0 │ │ │ ├── fusionAgent.st │ │ │ ├── metadata.xml │ │ │ └── test-inventory.pl.st │ ├── rudder-service-apache │ │ └── 1.0 │ │ │ ├── apache │ │ │ ├── apache-certificate.cf │ │ │ ├── apache-logrotate.mustache │ │ │ ├── logrotate.cf │ │ │ ├── main.st │ │ │ ├── nodescerts.pem.st │ │ │ ├── system_rudder_apache_networks_configuration.cf │ │ │ └── system_rudder_apache_webdav_configuration.cf │ │ │ └── metadata.xml │ ├── rudder-service-postgresql │ │ └── 1.0 │ │ │ ├── main.st │ │ │ ├── metadata.xml │ │ │ └── password-check.st │ ├── rudder-service-relayd │ │ └── 1.0 │ │ │ ├── common │ │ │ ├── logrotate.cf │ │ │ ├── relayd.cf │ │ │ └── relayd.conf.tpl │ │ │ ├── main.st │ │ │ ├── metadata.xml │ │ │ ├── relay │ │ │ ├── nodeslist.json.st │ │ │ └── propagatePromises.cf │ │ │ └── root │ │ │ └── rudderRelayRootNa.cf │ ├── rudder-service-slapd │ │ └── 1.0 │ │ │ ├── logrotate.cf │ │ │ ├── main.st │ │ │ └── metadata.xml │ ├── rudder-service-webapp │ │ └── 1.0 │ │ │ ├── alive-check.cf │ │ │ ├── bootstrapRudderServer.cf │ │ │ ├── compress-webapp-log.cf │ │ │ ├── integrity-check.cf │ │ │ ├── main.st │ │ │ ├── metadata.xml │ │ │ ├── password-check.cf │ │ │ └── updateNcfHash.cf │ └── server-common │ │ └── 1.0 │ │ ├── metadata.xml │ │ ├── reloadRudderServices.st │ │ └── rudder_syslog.cf └── systemSettings │ ├── category.xml │ ├── misc │ ├── category.xml │ ├── genericCommandVariableDefinition │ │ └── 3.0 │ │ │ ├── changelog │ │ │ ├── genericCommandVariableDefinition.st │ │ │ └── metadata.xml │ ├── partitionSizeMonitoring │ │ └── 3.1 │ │ │ ├── changelog │ │ │ ├── metadata.xml │ │ │ └── monitorPartitionSize.st │ └── rudderSNMP │ │ └── 1.0 │ │ ├── metadata.xml │ │ ├── rudderSNMP.st │ │ └── rudder_health.sh │ ├── networking │ ├── category.xml │ ├── dnsConfiguration │ │ └── 3.0 │ │ │ ├── changelog │ │ │ ├── check_dns_configuration.st │ │ │ └── metadata.xml │ ├── firewall │ │ └── 1.0 │ │ │ ├── changelog │ │ │ ├── firewall.st │ │ │ └── metadata.xml │ └── hostsConfiguration │ │ └── 2.0 │ │ ├── changelog │ │ ├── hostsConfiguration.st │ │ └── metadata.xml │ ├── process │ ├── category.xml │ ├── services │ │ └── 1.1 │ │ │ ├── changelog │ │ │ ├── metadata.xml │ │ │ ├── services.st │ │ │ └── tests │ │ │ ├── test_service.cf │ │ │ ├── test_service.json │ │ │ ├── test_service.metadata │ │ │ ├── test_service.rb │ │ │ └── test_service_cron.json │ └── servicesManagement │ │ └── 3.0 │ │ ├── changelog │ │ ├── metadata.xml │ │ └── servicesManagement.st │ ├── remoteAccess │ ├── category.xml │ ├── sshConfiguration │ │ └── 5.0 │ │ │ ├── bodies.st │ │ │ ├── changelog │ │ │ ├── config.st │ │ │ ├── installation.st │ │ │ ├── main.st │ │ │ └── metadata.xml │ └── sshKeyDistribution │ │ └── 4.0 │ │ ├── changelog │ │ ├── metadata.xml │ │ ├── sshKeyDistribution.st │ │ └── tests │ │ ├── FlushKey_TestSSHKeyDistribution.sh │ │ ├── TestSSHKeyDistribution.json │ │ ├── TestSSHKeyDistribution.metadata │ │ ├── TestSSHKeyDistribution.rb │ │ ├── TestSSHKeyDistributionCleanSSHKeyFile.sh │ │ ├── TestSSHKeyDistributionExisting.metadata │ │ ├── TestSSHKeyDistributionExisting.rb │ │ ├── TestSSHKeyDistributionExisting.sh │ │ ├── common_sshKeyDistribution_test.rb │ │ ├── flush_key.json │ │ ├── flush_key.metadata │ │ └── flush_key.rb │ ├── security │ ├── category.xml │ └── fileAlterationMonitoring │ │ └── 2.2 │ │ ├── changelog │ │ ├── fileAlterationMonitoring.st │ │ └── metadata.xml │ ├── systemManagement │ ├── category.xml │ ├── cronManagement │ │ └── 3.2 │ │ │ ├── changelog │ │ │ ├── cronConfiguration.st │ │ │ └── metadata.xml │ ├── motdConfiguration │ │ └── 3.3 │ │ │ ├── changelog │ │ │ ├── config.st │ │ │ ├── main.st │ │ │ ├── metadata.xml │ │ │ └── motd.ps1.st │ └── userCronManagement │ │ └── 1.0 │ │ ├── metadata.xml │ │ └── userCronConfiguration.st │ └── userManagement │ ├── category.xml │ ├── groupManagement │ └── 5.1 │ │ ├── changelog │ │ ├── groupManagement.st │ │ └── metadata.xml │ ├── sudoParameters │ └── 3.2 │ │ ├── changelog │ │ ├── metadata.xml │ │ └── sudoParameters.st │ └── userManagement │ ├── 10 │ ├── changelog │ ├── metadata.xml │ ├── userManagement.ps1.st │ └── userManagement.st │ ├── 9.0 │ ├── changelog │ ├── metadata.xml │ ├── userManagement.ps1.st │ └── userManagement.st │ └── 9.1 │ ├── changelog │ ├── metadata.xml │ ├── userManagement.ps1.st │ └── userManagement.st ├── typos.toml └── variables.json /.gitignore: -------------------------------------------------------------------------------- 1 | scripts/technique-files 2 | rudder-templates-cli.jar 3 | initial-promises/ 4 | bootstrap-promises/promises.cf 5 | bootstrap-promises/rudder.json 6 | -------------------------------------------------------------------------------- /CustomRules/CustomRules.psm1: -------------------------------------------------------------------------------- 1 | # Module defining the Rudder custom PSSA rules. It exposes the rules and 2 | # some helper cmdlet such as Invoke-CustomScriptAnalyzer used to debug, dev 3 | # and test the custom rules. 4 | $public = Get-ChildItem $psScriptRoot\public -Filter *.ps1 -Recurse 5 | foreach ($item in $public) { 6 | . $item.FullName 7 | } 8 | Export-ModuleMember -Function AvoidUninitializedVariableInPolicy, AvoidUninitializedVariableInModule, UseCamelCase, Invoke-CustomScriptAnalyzerRule 9 | -------------------------------------------------------------------------------- /CustomRules/PSScriptAnalyzer.Tests.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Taken from https://github.com/indented-automation/Indented.ScriptAnalyzerRules 3 | Import the settings and custom rules from PSScriptAnalyzer in the repo to make 4 | them usable by the Invoke-CustomScriptAnalyzerRule cmdlet. 5 | #> 6 | Describe PSScriptAnalyzer { 7 | BeforeDiscovery { 8 | $moduleRoot = $PSScriptRoot.Substring(0, $PSScriptRoot.IndexOf('\tests')) 9 | $projectRoot = $moduleRoot | Split-Path -Parent 10 | $settings = Join-Path $projectRoot -ChildPath 'PSScriptAnalyzerSettings.psd1' 11 | 12 | $rules = Get-ChildItem -Path $moduleRoot -File -Recurse -Include *.ps1 -Exclude *.tests.ps1 | 13 | ForEach-Object { 14 | Invoke-ScriptAnalyzer -Path $_.FullName -Settings $settings 15 | } | 16 | Where-Object RuleName -NE 'TypeNotFound' | 17 | ForEach-Object { 18 | @{ 19 | Rule = [PSCustomObject]@{ 20 | RuleName = $_.RuleName 21 | Message = $_.Message -replace '(.{50,90}) ', "`n `$1" -replace '^\n ' 22 | ScriptName = $_.ScriptName 23 | Line = $_.Line 24 | ScriptPath = $_.ScriptPath 25 | } 26 | } 27 | } 28 | } 29 | 30 | It ( 31 | @( 32 | '' 33 | ' ' 34 | ' in line ' 35 | ) | Out-String 36 | ) -TestCases $rules { 37 | $rule.ScriptPath | Should -BeNullOrEmpty 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CustomRules/PSScriptAnalyzerSettings.psd1: -------------------------------------------------------------------------------- 1 | # Only used for testing 2 | @{ 3 | IncludeDefaultRules = $false 4 | CustomRulePath = @( 5 | 'CustomRules/CustomRules.psm1' 6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /CustomRules/ast.ps1: -------------------------------------------------------------------------------- 1 | # Taken from https://powershell.one/powershell-internals/parsing-and-tokenization/abstract-syntax-tree 2 | function Convert-CodeToAst 3 | { 4 | param 5 | ( 6 | [Parameter(Mandatory)] 7 | [ScriptBlock] 8 | $code 9 | ) 10 | 11 | 12 | # build a hashtable for parents 13 | $hierarchy = @{} 14 | 15 | $code.Ast.FindAll( { $true }, $true) | 16 | ForEach-Object { 17 | # take unique object hash as key 18 | $id = $_.Parent.GetHashCode() 19 | if ($hierarchy.ContainsKey($id) -eq $false) 20 | { 21 | $hierarchy[$id] = [System.Collections.ArrayList]@() 22 | } 23 | $null = $hierarchy[$id].Add($_) 24 | # add ast object to parent 25 | 26 | } 27 | 28 | # visualize tree recursively 29 | function Visualize-Tree { 30 | param( 31 | $id, 32 | $indent = 0 33 | ) 34 | # use this as indent per level: 35 | $space = '--' * $indent 36 | $hierarchy[$id] | ForEach-Object { 37 | # output current ast object with appropriate 38 | # indentation: 39 | '{0}[{1}]: {2}' -f $space, $_.GetType().Name, $_.Extent 40 | 41 | # take id of current ast object 42 | $newid = $_.GetHashCode() 43 | # recursively look at its children (if any): 44 | if ($hierarchy.ContainsKey($newid)) 45 | { 46 | Visualize-Tree -id $newid -indent ($indent + 1) 47 | } 48 | } 49 | } 50 | 51 | # start visualization with ast root object: 52 | Visualize-Tree -id $code.Ast.GetHashCode() 53 | } 54 | 55 | Convert-CodeToAst -Code { 56 | #### Write your code to render in ast type here #### 57 | $private:bob = "oui" 58 | } 59 | -------------------------------------------------------------------------------- /CustomRules/public/AvoidUninitializedVariableInModule.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Avoid using undefined variables. 4 | .DESCRIPTION 5 | Avoid using undefined variables. 6 | .EXAMPLE 7 | Test-VariablbeAssignment -ScriptBlockAst $ScriptBlockAst 8 | .INPUTS 9 | [System.Management.Automation.Language.ScriptBlockAst] 10 | .OUTPUTS 11 | [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]] 12 | #> 13 | . $psScriptroot/../rulesLib.ps1 14 | 15 | function AvoidUninitializedVariableInModule { 16 | [CmdletBinding()] 17 | [OutputType([PSCustomObject[]])] 18 | Param ( 19 | [Parameter(Mandatory)] 20 | [ValidateNotNullOrEmpty()] 21 | [System.Management.Automation.Language.ScriptBlockAst]$ast 22 | ) 23 | 24 | process { 25 | try { 26 | # Since we are doing a recursive lookup to pass variable context to 27 | # children, we need to only trigger the rule on the root block 28 | if ($null -eq $ast.parent) { 29 | $context = New-Object System.Collections.ArrayList 30 | return FindUninitializedVariables -ScriptBlockAst $ast -Context $context -Target Module 31 | } 32 | } catch { 33 | $psCmdlet.ThrowTerminatingError( $_ ) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CustomRules/public/AvoidUninitializedVariableInPolicy.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Avoid using undefined variables. 4 | .DESCRIPTION 5 | Avoid using undefined variables. 6 | .EXAMPLE 7 | Test-VariablbeAssignment -ScriptBlockAst $ScriptBlockAst 8 | .INPUTS 9 | [System.Management.Automation.Language.ScriptBlockAst] 10 | .OUTPUTS 11 | [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]] 12 | #> 13 | . $psScriptroot/../rulesLib.ps1 14 | 15 | function AvoidUninitializedVariableInPolicy { 16 | [CmdletBinding()] 17 | [OutputType([PSCustomObject[]])] 18 | Param ( 19 | [Parameter(Mandatory)] 20 | [ValidateNotNullOrEmpty()] 21 | [System.Management.Automation.Language.ScriptBlockAst]$ast 22 | ) 23 | 24 | process { 25 | try { 26 | # Since we are doing a recursive lookup to pass variable context to 27 | # children, we need to only trigger the rule on the root block 28 | if ($null -eq $ast.parent) { 29 | $context = New-Object System.Collections.ArrayList 30 | return FindUninitializedVariables -ScriptBlockAst $ast -Context $context -Target Policy 31 | } 32 | } catch { 33 | $psCmdlet.ThrowTerminatingError( $_ ) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CustomRules/public/UseCamelCase.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | The variables names should be in camelCase. 4 | .DESCRIPTION 5 | Variable names should use camelCase style 6 | The rule verify that each variable assignment use camelCase. It does not 7 | currently check each variable expressions, only assignments. 8 | .EXAMPLE 9 | UseCamelCase -ScriptBlockAst $ScriptBlockAst 10 | .INPUTS 11 | [System.Management.Automation.Language.ScriptBlockAst] 12 | .OUTPUTS 13 | [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]] 14 | .NOTES 15 | https://msdn.microsoft.com/en-us/library/dd878270(v=vs.85).aspx 16 | https://msdn.microsoft.com/en-us/library/ms229043(v=vs.110).aspx 17 | #> 18 | Function UseCamelCase { 19 | [CmdletBinding()] 20 | [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])] 21 | Param ( 22 | [Parameter(Mandatory = $true)] 23 | [ValidateNotNullOrEmpty()] 24 | [System.Management.Automation.Language.ScriptBlockAst] 25 | $ScriptBlockAst 26 | ) 27 | 28 | Process { 29 | $results = @() 30 | try { 31 | [ScriptBlock]$predicate = { 32 | Param ([System.Management.Automation.Language.Ast]$Ast) 33 | [bool]$returnValue = $false 34 | 35 | # Look for an AssignmentStatementAst, and inside it, for VariableExpressionAst in its left part 36 | if (Is-variable-Assignment $ast) { 37 | [System.Management.Automation.Language.AssignmentStatementAst]$assignmentAst = $Ast 38 | $variableName = Get-Variable-Name $assignmentAst 39 | $returnValue = $variableName -cnotmatch '^(env:.*)|((global:|private:|local:)?[a-z]+([A-Z0-9]{1,3}|([A-Z][a-z0-9]+)*))$' 40 | } 41 | return $returnValue 42 | } 43 | 44 | [System.Management.Automation.Language.Ast[]]$violations = $ScriptBlockAst.FindAll($predicate, $True) 45 | If ($violations.Count -ne 0) { 46 | Foreach ($violation in $violations) { 47 | [System.Management.Automation.Language.AssignmentStatementAst]$violationAst = $violation 48 | $resultArgs = @{ 49 | TypeName = "Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord" 50 | ArgumentList = "$((Get-Help $MyInvocation.MyCommand.Name).Description.Text): $($violationAst.Left)", $violationAst.Extent, $PSCmdlet.MyInvocation.InvocationName, "Information", $null 51 | } 52 | $result = New-Object @resultArgs 53 | $results += $result 54 | } 55 | } 56 | return $results 57 | } catch { 58 | Write-Host $_ 59 | $PSCmdlet.ThrowTerminatingError($_) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CustomRules/tests/AvoidUninitializedVariable.Tests.ps1: -------------------------------------------------------------------------------- 1 | # This does not work correctly atm, due to the invoke-customscriptAnalyzeRule 2 | # which is used with the scriptblock type instead of file type. 3 | Describe AvoidUninitializedVariable { 4 | BeforeAll { 5 | $settings = Join-Path -Path $PSScriptRoot -ChildPath "../PSScriptAnalyzerSettings.psd1" 6 | } 7 | 8 | It 'Triggers when some variables are undefined: ' -TestCases @( 9 | @{ Script = 'return $b'; Name = "Undefined"} 10 | @{ Script = '$b = 0; foreach ($a in @("1", "2", "3")) { $b += $i }'; Name = "Undefined in foreach" } 11 | ) { 12 | Invoke-ScriptAnalyzer -ScriptDefinition $script -Settings $settings | Should -Not -BeNullOrEmpty 13 | } 14 | 15 | It 'Does not trigger when every variables are defined prior to their usage: ' -TestCases @( 16 | @{ 17 | Name = "trivial case 1" 18 | Script = '$a = "ping"; $b = $a + "pong"' 19 | } 20 | @{ 21 | Name = "Foreach" 22 | Script = '$b = 0; foreach ($a in @("1", "2", "3")) { $b += $a}' 23 | } 24 | @{ 25 | Name = "Function parameters" 26 | Script = 'function f { param($a, $b) return $a + $b }' 27 | } 28 | @{ 29 | Name = "Nested scriptblock" 30 | Script = '$tmpKey = Get-Item -Path .; $tmpValue = @{ Name = "Value"; Expression = { $tmpKey.GetValue($_) } }' 31 | } 32 | @{ 33 | Name = "Real life block" 34 | Script = @' 35 | $tempProperties = @{} 36 | $currentFile = $_.FullName 37 | $content = ConvertPSObjectToHashtable -InputObject $(ConvertFrom-Json "$(Get-Content $_.FullName)") 38 | 39 | foreach ($key in $content.keys) { 40 | $tempProperties[$key] = $content[$key] 41 | } 42 | '@ 43 | } 44 | @{ 45 | Name = "Scoped variable" 46 | Script = '$private:a = "ping"; $b = $a + "pong"' 47 | } 48 | ) { 49 | $a = Invoke-ScriptAnalyzer -ScriptDefinition $script -Settings $settings 50 | if ($null -ne $a) { 51 | Write-Host $a.message 52 | } 53 | $a | Should -BeNullOrEmpty 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Autodetect wget or curl or curl usage and proxy configuration 2 | PROXY_ENV = $(if $(PROXY), http_proxy=$(PROXY) ftp_proxy=$(PROXY)) 3 | WGET = wget -q -O 4 | CURL = curl -s -o 5 | FETCH = fetch -q -o 6 | ifneq (,$(wildcard /usr/bin/curl)) 7 | GET = $(PROXY_ENV) $(CURL) 8 | else 9 | ifneq (,$(wildcard /usr/bin/fetch)) 10 | GET = $(PROXY_ENV) $(FETCH) 11 | else 12 | GET = $(PROXY_ENV) $(WGET) 13 | endif 14 | endif 15 | 16 | 17 | all: initial-promises bootstrap-promises/rudder.json bootstrap-promises/promises.cf 18 | 19 | initial-promises: rudder-templates-cli.jar 20 | python3 generate_initial_policies.py 21 | mkdir -p initial-promises/node-server/common/cron 22 | mkdir -p initial-promises/node-server/common/utilities 23 | cp variables.json initial-promises/node-server/rudder.json 24 | echo '{ "parameters":{ "rudder_file_edit_header":"### Managed by Rudder, edit with care ###" } }' > initial-promises/node-server/rudder-parameters.json 25 | # Provide default properties for the node 26 | mkdir -p initial-promises/node-server/properties.d 27 | cp properties.json initial-promises/node-server/properties.d/properties.json 28 | 29 | bootstrap-promises/rudder.json: 30 | cp variables.json $@ 31 | 32 | bootstrap-promises/promises.cf: 33 | cp bootstrap-promises/failsafe.cf bootstrap-promises/promises.cf 34 | 35 | rudder-templates-cli.jar: 36 | $(GET) rudder-templates-cli.jar https://repository.rudder.io/build-dependencies/rudder-templates-cli/rudder-templates-cli.jar 37 | 38 | scripts/technique-files: 39 | $(GET) scripts/technique-files https://repository.rudder.io/tools/technique-files 40 | chmod +x scripts/technique-files 41 | 42 | test: scripts/technique-files 43 | cd scripts && ./check-techniques.sh 44 | 45 | clean: 46 | rm -rf initial-promises/ scripts/technique-files 47 | -------------------------------------------------------------------------------- /PSScriptAnalyzerSettingsPolicy.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | IncludeDefaultRules = $True 3 | CustomRulePath = @( 4 | './CustomRules/CustomRules.psm1' 5 | ) 6 | Rules = @{ 7 | PSPlaceOpenBrace = @{ 8 | Enable = $true 9 | OnSameLine = $true 10 | NewLineAfter = $true 11 | IgnoreOneLineBlock = $true 12 | } 13 | 14 | PSPlaceCloseBrace = @{ 15 | Enable = $true 16 | NoEmptyLineBefore = $true 17 | IgnoreOneLineBlock = $true 18 | NewLineAfter = $false 19 | } 20 | 21 | PSUseConsistentIndentation = @{ 22 | Enable = $true 23 | IndentationSize = 2 24 | PipelineIndentation = "IncreaseIndentationForFirstPipeline" 25 | Kind = "space" 26 | } 27 | 28 | PSUseConsistentWhitespace = @{ 29 | Enable = $true 30 | CheckInnerBrace = $true 31 | CheckOpenBrace = $true 32 | CheckOpenParen = $true 33 | CheckOperator = $false 34 | CheckPipe = $true 35 | CheckPipeForRedundantWhitespace = $false 36 | CheckSeparator = $true 37 | CheckParameter = $false 38 | IgnoreAssignmentOperatorInsideHashTable = $false 39 | } 40 | } 41 | 42 | ExcludeRules = @( 43 | "PSAvoidTrailingWhitespace", 44 | "AvoidUninitializedVariableInModule", 45 | "PSAvoidUsingWriteHost", 46 | "PSUseApprovedVerbs", 47 | "PSAvoidDefaultValueSwitchParameter", 48 | "PSUseOutputTypeCorrectly", 49 | "PSUseShouldProcessForStateChangingFunctions", 50 | "PSAvoidUsingInvokeExpression", 51 | "PSAvoidUsingPlainTextForPassword", 52 | "PSAvoidUsingConvertToSecureStringWithPlainText", 53 | "PSUseSingularNouns", 54 | "PSUseToExportFieldsInManifest" 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Rudder: Continuous Auditing & Configuration 2 | 3 | This project is part of Rudder, see https://github.com/Normation/rudder[the main repository] 4 | for more information. 5 | 6 | == License 7 | 8 | This sub-project is licensed under GPLv3 license, 9 | see the provided "LICENSE" file or 10 | http://www.gnu.org/licenses/gpl-3.0.txt 11 | 12 | == Synopsis 13 | 14 | This repository contains the Techniques Library of Rudder. 15 | 16 | == Usage 17 | 18 | This project is part of Rudder, and as such is bundled with every Rudder server. 19 | 20 | -------------------------------------------------------------------------------- /ci/cf-promises.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 2 | LABEL ci=rudder/ci/cf-promises.Dockerfile 3 | 4 | RUN apt-get update && apt-get install -y wget gnupg2 make libxml-parser-perl openjdk-17-jdk-headless git python3-distutils 5 | 6 | # Accept all OSes 7 | ENV UNSUPPORTED=y 8 | RUN wget https://repository.rudder.io/tools/rudder-setup && sh ./rudder-setup setup-agent latest || true 9 | -------------------------------------------------------------------------------- /ci/common.Dockerfile: -------------------------------------------------------------------------------- 1 | # rust is the latest debian image with latest rust preinstalled 2 | FROM rust 3 | 4 | # Is there a reason to lock a specific version ? 5 | RUN cargo install -f typos-cli 6 | RUN apt-get update && apt-get install -y shellcheck pylint 7 | -------------------------------------------------------------------------------- /ci/linter.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye 2 | LABEL ci=rudder/ci/linter.Dockerfile 3 | ARG VERSION 4 | ARG USER_ID=1000 5 | 6 | ENV HOME=/tmp 7 | RUN < .shellcheck/$(basename ${file}).log || true 15 | # fail on >=error 16 | shellcheck --severity error "$file" 17 | done 18 | } 19 | 20 | # fails on error and ignores other levels 21 | test_shell_error() 22 | { 23 | # Shellcheck 24 | find . -path ./.git -prune -o -path "*.py" -prune -o -type f -exec grep -Eq '^#!(.*/|.*env +)(sh|bash|ksh)' {} \; -print | 25 | while IFS="" read -r file 26 | do 27 | # with recent shellcheck, "-S error" replaces this hack 28 | # kept as this runs on machines running rudder-dev 29 | shellcheck --format gcc "$file" | grep " error: " && exit 1 || true 30 | done 31 | } 32 | 33 | # verify that each file has a correct license header 34 | test_license_header() 35 | { 36 | find . -name '*.cf' -o -name '*.st' -print0 | 37 | while IFS= read -r -d '' file; do 38 | if ! grep -qE "# SPDX-FileCopyrightText.*" $file; then 39 | # Ignore very small files 40 | if [ `wc -l $file | awk '{print $1}'` -gt "10" ]; then 41 | echo "$file is missing a correct license header" 42 | exit 1 43 | fi 44 | fi 45 | done 46 | } 47 | 48 | test_windows_techniques() 49 | { 50 | if [ ! -f rudder-templates-cli.jar ]; then 51 | wget https://repository.rudder.io/build-dependencies/rudder-templates-cli/rudder-templates-cli.jar 52 | fi 53 | for technique in $(find techniques -type d -regex ".*[0-9]+\(.[0-9]+\)?") 54 | do 55 | tmp_dir=$(mktemp -d -t qa-test-XXXXXXXXXX) 56 | cp -r $technique/* $tmp_dir 57 | for file in $(find $technique -name "*.ps1.st") 58 | do 59 | baseFile=$(basename $file .ps1.st) 60 | renderedFile=$tmp_dir/$baseFile.ps1 61 | java -Dfile.encoding=UTF-8 -jar rudder-templates-cli.jar --outdir $tmp_dir -p variables.json $file 62 | done 63 | pwsh -command "Invoke-ScriptAnalyzer -Path ${tmp_dir} -Settings ./PSScriptAnalyzerSettingsPolicy.psd1 -EnableExit -ReportSummary" 64 | rm -rf $tmp_dir 65 | done 66 | } 67 | 68 | if [ "$1" = "--shell" ]; then 69 | test_shell 70 | exit 0 71 | elif [ "$1" = "--license" ]; then 72 | test_license_header 73 | elif [ "$1" = "--dsc" ]; then 74 | test_windows_techniques 75 | else 76 | # quick tests to be launched during merge 77 | test_shell_error 78 | make test 79 | fi 80 | -------------------------------------------------------------------------------- /rudderVariables.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | Policy = @( 3 | 'ALLDSCRESOURCES', 4 | # Should not be needed anymore since 8.2 5 | 'RUDDERVARIABLE', 6 | 'WINDOWSUPDATEPERSISTENTDATA', 7 | 'WINDOWSUPDATEPERSISTENTFILE', 8 | 'WINDOWSUPDATEPERSISTENTSTATEFILE' 9 | ) 10 | Internal = @( 11 | 'LOCAL', 12 | 'RUDDERVARIABLE' 13 | ) 14 | 15 | } 16 | -------------------------------------------------------------------------------- /scripts/ordering.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use warnings; 3 | use strict; 4 | 5 | my $exit = 0; 6 | 7 | # ordering from cfengine documentation 8 | # convert to a hash { promise_type => order_id } 9 | my $orderings = { 10 | agent => make_hash(qw/meta vars defaults classes files packages guest_environments methods processes services commands storage databases reports/), 11 | edit_line => make_hash(qw/meta vars defaults classes delete_lines field_edits insert_lines replace_patterns reports/), 12 | server => make_hash(qw/vars classes access roles/), 13 | monitor => make_hash(qw/vars classes measurements reports/), 14 | common => make_hash(qw/vars classes reports/), 15 | }; 16 | 17 | while(my $file = shift @ARGV) { 18 | check_ordering($file); 19 | } 20 | exit $exit; 21 | 22 | sub check_ordering { 23 | # open file 24 | my $filename = shift; 25 | 26 | open(my $fh, "<$filename") or die "Can't open file $filename"; 27 | 28 | # work variables 29 | my $bundle = "unknown"; 30 | my $bundle_type = "unknown"; 31 | my $type = ""; 32 | 33 | # scan the file 34 | while(my $line = <$fh>) { 35 | $line =~ s/#.*//; 36 | 37 | if($line =~ /^\s*bundle\s+(\w+)\s+(\w+)/) { 38 | # detect bundles 39 | 40 | $bundle_type = $1; 41 | $bundle = $2; 42 | $type = ""; 43 | 44 | } elsif($line =~ /\W(\w+):\s*$/) { 45 | # detect promise type 46 | 47 | my $new_type = $1; 48 | if($type ne "") { 49 | 50 | # check ordering 51 | die "Unknown bundle type $bundle_type" unless exists $orderings->{$bundle_type}; 52 | my $ordering = $orderings->{$bundle_type}; 53 | if (!exists($ordering->{$type})){ 54 | print "Unknown promise type '$type' in '$filename' for 'bundle $bundle_type $bundle'\n"; 55 | } elsif (!exists($ordering->{$new_type})){ 56 | print "Unknown promise type '$new_type' in '$filename' for 'bundle $bundle_type $bundle'\n"; 57 | } elsif($ordering->{$type} > $ordering->{$new_type}) { 58 | print "Error in '$filename' in 'bundle $bundle_type $bundle' : $type before $new_type\n"; 59 | $exit++; 60 | } 61 | 62 | } 63 | $type = $new_type; 64 | } 65 | } 66 | close($fh); 67 | } 68 | 69 | sub make_hash { 70 | my $i=1; 71 | my %ordering = map { $_ => $i++ } @_; 72 | return \%ordering; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /scripts/xval.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use XML::Parser; 7 | 8 | my $xmlfile; 9 | my $quiet = 0; 10 | 11 | if($ARGV[0] eq "-q") 12 | { 13 | $quiet = 1; 14 | shift @ARGV; 15 | } 16 | 17 | if($ARGV[0] ne "") 18 | { 19 | print "Opening $ARGV[0]...\n" unless $quiet; 20 | $xmlfile = shift @ARGV; # the file to parse 21 | } 22 | else 23 | { 24 | die("Syntax : xwf.pl file"); 25 | } 26 | 27 | # initialize parser object and parse the string 28 | my $parser = XML::Parser->new( ErrorContext => 2 ); 29 | eval { $parser->parsefile( $xmlfile ); }; 30 | 31 | # report any error that stopped parsing, or announce success 32 | if( $@ ) { 33 | $@ =~ s/at \/.*?$//s; # remove module line number 34 | print STDERR "\nERROR in '$xmlfile':\n$@\n"; 35 | exit 1; 36 | } else { 37 | print STDERR "'$xmlfile' is well-formed\n" unless $quiet; 38 | exit 0; 39 | } 40 | -------------------------------------------------------------------------------- /technique-metadata-sample.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 8 | 9 | 11 | 12 | 13 | 16 | This sample technique actually does nothing, except demonstrate. 17 | 18 | 21 | false 22 | 23 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | sample_technique 36 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 46 |
47 | 48 | MOTD 49 | Message of the day (MOTD) to display 50 | 51 | 52 | textarea 53 | 54 | 55 | 56 | MOTD_EMPTY 57 | Enforce this MOTD only 58 | This option will remove any existing messages in the motd file and replace them with the text provided above 59 | 60 | 61 | true 62 | 63 | 64 | 65 | false 66 | 67 | 68 | false 69 | 70 | 71 |
72 |
73 | 74 |
75 | -------------------------------------------------------------------------------- /techniques/applications/aptPackageManagerSettings/3.1/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Alexis Mousset Wed Mar 16 15:31:23 2016 8 | * Version 3.1 9 | ** Add a free component field 10 | -------------------------------------------------------------------------------- /techniques/applications/aptPackageManagerSettings/3.2/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Alexis Mousset Wed Mar 16 15:31:23 2016 8 | * Version 3.1 9 | ** Add a free component field 10 | -- Nicolas Charles Wed Sep 16 21:40:13 2020 11 | * Version 3.2 12 | ** Don't write unexpanded variable when distro is not detected 13 | -------------------------------------------------------------------------------- /techniques/applications/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Application management 4 | This category contains Techniques designed to install, configure and manage applications 5 | 6 | -------------------------------------------------------------------------------- /techniques/applications/packageManagement/1.3/changelog: -------------------------------------------------------------------------------- 1 | -- Alexis Mousset Mon, 26 Sep 2016 17:19:00 +0100 2 | * Version 1.0 3 | ** Use the new package promises 4 | -- Alexis Mousset Thu Aug 3 16:53:40 2017 5 | * Version 1.1 6 | ** Add options for package managers 7 | -- Nicolas Charles Thu Dec 7 17:16:30 2017 8 | * Version 1.2 9 | ** Convert to multiversionned technique 10 | -- Félix Dallidet Mon Mar 1 10:23:30 2021 11 | * Version 1.3 12 | ** Add upgrade only option 13 | -------------------------------------------------------------------------------- /techniques/applications/repoGpgKeyManagement/1.1/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas Charles Wed Apr 4 14:52:44 2018 2 | * Version 1.1 3 | ** Port technique to multiversionned generation 4 | -------------------------------------------------------------------------------- /techniques/applications/snmp/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Install an SNMP agent, and configure it 5 | This technique version is not maintained anymore, it will no longer be available in the next version of Rudder. 6 | separated 7 | 8 | false 9 | 10 | 11 | 12 | snmp 13 | 14 | 15 | 16 | 17 | 18 | 19 | true 20 | 21 | 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | snmp 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | SNMP_COMMUNITY_NAME 38 | 39 | 40 | 41 |
42 |
43 | 44 |
45 | 46 | SNMP_AUTHORIZED_SOURCES 47 | Sources authorized to access to the agent via following communities. Comma separated 48 | Sources can be hostnames, IP addresses or subnets(Linux only). Just enter "any" if you do not want to restrict the access. 49 | 50 | false 51 | 52 | 53 |
54 | 55 |
56 | 57 | Flush the snmp configuration 58 | This will ensure that only the configuration defined in Rudder will be applied on the Windows nodes. 59 | SNMP_FLUSH 60 | 61 | boolean 62 | false 63 | 64 | 65 |
66 | 67 |
68 | 69 | Community name 70 | SNMP_COMMUNITY_NAME 71 | 72 | false 73 | 74 | 75 | 76 | SNMP_COMMUNITY_ACL 77 | Access restrictions for the given community 78 | 79 | false 80 | 81 | 82 | rocommunity 83 | 84 | 85 | 86 | rwcommunity 87 | 88 | 89 | 90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerRepositories/1.0/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas CHARLES Tue Oct 21 18:00:00 CEST 2014 2 | * Version 1.0 3 | ** Creation to replace zypperPackageManagerSettings, which is now split in 4 | ** Zypper Package Manager Setup, and Zypper Package Manager Repositories 5 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerRepositories/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | This technique configures repositories for Zypper package manager. 3 | 4 | true 5 | 6 | 7 | zypper_repositories_management 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | ZYPPER_REPO_URL 22 | 23 | 24 | 25 |
26 | 27 | ZYPPER_REPO_NAME 28 | Repository name 29 | 30 | 31 | ZYPPER_REPO_URL 32 | Repository URL 33 | 34 | 35 | ZYPPER_REPO_TYPE 36 | Repository type 37 | You should not modify this entry, do it only if you know what you are doing 38 | 39 | rpm-md 40 | 41 | 42 | 43 | yast2 44 | 45 | 46 | 47 | yast2 48 | 49 | 50 | 51 | ZYPPER_REPO_ENABLED 52 | Enabled 53 | 54 | 0 55 | 56 | 57 | 58 | 1 59 | 60 | 61 | 62 | 1 63 | 64 | 65 | 66 | ZYPPER_REPO_AUTOREFRESH 67 | Enable auto refresh for this repository metadata 68 | 69 | 0 70 | 71 | 72 | 73 | 1 74 | 75 | 76 | 77 | 0 78 | 79 | 80 |
81 |
82 | 83 | ZYPPER_REPO_DISABLE_OTHER_REPOSITORIES 84 | Delete all other repositories than those managed by Rudder (potentially dangerous) 85 | If true, it will delete all other repositories than those managed. If multiple Directives based on this Technique are applied to one node, then the value for this variable will be the one of the Directive with highest priority 86 | 87 | boolean 88 | false 89 | 90 | 91 |
92 |
93 | 94 |
95 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerRepositories/1.0/zypper-repo.tml: -------------------------------------------------------------------------------- 1 | ${rudder_parameters.rudder_file_edit_header} 2 | 3 | [${configure_zypper_repos.zypper_name}] 4 | name=${configure_zypper_repos.zypper_name} 5 | enabled=${configure_zypper_repos.zypper_enabled} 6 | autorefresh=${configure_zypper_repos.zypper_autorefresh} 7 | baseurl=${configure_zypper_repos.zypper_url} 8 | type=${configure_zypper_repos.zypper_type} 9 | keeppackages=0 10 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerSetup/1.0/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas CHARLES Tue Oct 21 18:00:00 CEST 2014 2 | * Version 1.0 3 | ** Creation to replace zypperPackageManagerSettings, which is now split in 4 | ** Zypper Package Manager Setup, and Zypper Package Manager Repositories 5 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerSetup/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | This technique configures Zypper package manager. 3 | 4 | 5 | zypper_package_manager_setup 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | ZYPPER_INSTALLRECOMMENDS 17 | Install 'recommended' packages automatically 18 | 19 | dontchange 20 | 21 | 22 | 23 | true 24 | 25 | 26 | 27 | false 28 | 29 | 30 | 31 | dontchange 32 | 33 | 34 | 35 |
36 |
37 | 38 |
39 | -------------------------------------------------------------------------------- /techniques/applications/zypperPackageManagerSetup/1.0/zypper-package-manager-setup.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | ###################################################### 5 | # Setups the Zypper Package Manager # 6 | ###################################################### 7 | 8 | bundle agent zypper_package_manager_setup 9 | { 10 | 11 | vars: 12 | 13 | "directive_id" string => "&TRACKINGKEY&"; 14 | 15 | "zmdconf[main][solver.onlyRequires]" string => "&ZYPPER_INSTALLRECOMMENDS&"; 16 | 17 | "zypper_sections" slist => getindices("zmdconf"); 18 | 19 | "class_prefix" string => "zypper_package_manager_setup"; 20 | 21 | files: 22 | 23 | SuSE:: 24 | "/etc/zypp/zypp.conf" 25 | create => "true", 26 | perms => mog("644", "root", "0"), 27 | edit_defaults => noempty_backup, 28 | edit_line => set_variable_values_ini("zypper_package_manager_setup.zmdconf", "${zypper_sections}"), 29 | classes => classes_generic("${class_prefix}"); 30 | 31 | 32 | methods: 33 | SuSE:: 34 | "suse" usebundle => rudder_common_reports_generic("Zypper package manager setup", "${class_prefix}", "${directive_id}", "General settings", "None", "The Zypper package manager setup"); 35 | 36 | !SuSE:: 37 | "not applicable" usebundle => rudder_common_report("Zypper package manager setup", "result_na", "${directive_id}", "General settings", "None", "The Zypper package manager setup is not applicable on this system"); 38 | } 39 | -------------------------------------------------------------------------------- /techniques/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Technique library root 4 | 5 | This is the root category for the Techniques library. It contains Techniques provided by Normation. 6 | 7 | 8 | -------------------------------------------------------------------------------- /techniques/default-directive-names.conf: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # This file contains the default name that a directive gets in Rudder UI creation form. 4 | # 5 | # The file format is a simple "key:value" file, with key being the techniqueId 6 | # or techniqueId/version and the value being the name to use. 7 | # 8 | # An empty value will lead to an empty default name. 9 | # For a new Directive, we will try to lookup "TechniqueName/version" and if not 10 | # available "TechniqueName" from this file. If neither key is available, the 11 | # pop-up will use the actual Technique name as default. 12 | # 13 | # Don't forget to commit the file in git (git add default-directive-names.conf; 14 | # git commit -m "change new directive name) and reload technique library 15 | # (rudder server reload-techniques) to have modifications seen by Rudder. 16 | # 17 | 18 | # Example: change default naming scheme for "Users" Technique. 19 | 20 | # Default pattern for new directive from "userManagement" technique: 21 | #userManagement=User: Role : 22 | 23 | # For userManagement version 7.0, use the following pattern in new Directives: 24 | #userManagement/7.0: Role (with login ) 25 | 26 | -------------------------------------------------------------------------------- /techniques/fileConfiguration/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | File state configuration 4 | 5 | Define state about files (especially configuration files) 6 | 7 | 8 | -------------------------------------------------------------------------------- /techniques/fileConfiguration/fileManagement/4.1/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 3.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 4.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Nicolas Charles Fri Dec 8 16:38:29 2017 8 | * Version 4.1 9 | ** Port technique to multi-versioned format 10 | -------------------------------------------------------------------------------- /techniques/fileConfiguration/fileSecurity/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Security configuration 4 | 5 | Assert and correct security rules 6 | 7 | 8 | -------------------------------------------------------------------------------- /techniques/fileConfiguration/fileSecurity/filesPermissions/2.2/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 2 | * Version 2.0 3 | ** Use rudder_common_report instead of reports: 4 | -- Benoît Peccatte Fri Sep 25 11:04:43 2015 5 | * Version 2.1 6 | ** Add a button to ignore non existent file 7 | -- Nicolas Charles Tue Dec 12 11:41:14 2017 8 | * Version 2.2 9 | ** Convert to multiversionned technique 10 | -------------------------------------------------------------------------------- /techniques/fileConfiguration/fileSecurity/filesPermissions/2.2/permlist.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # List of files permission 5 | # Format of the file : 6 | # directiveId:file:user;;group;;mode;;edituser;;editgroup;;editmode;;suid;;sgid;;recursion 7 | &TRACKINGKEY, FILEPERMISSION_FILENAME, FILEPERMISSION_USER, FILEPERMISSION_GROUP, FILEPERMISSION_MODE, FILEPERMISSION_EDITUSER, FILEPERMISSION_EDITGROUP, FILEPERMISSION_EDITMODE, FILEPERMISSION_SUID, FILEPERMISSION_SGID, FILEPERMISSION_RECURSION, FILEPERMISSION_IGNORE_ABSENTFILE:{directiveId, fileName, user, group, perm, edituser, editgroup, editperm, suid, sgid, recursion, fileAbsent | &directiveId&:&fileName&:&user&;;&group&;;&perm&;;&edituser&;;&editgroup&;;&editperm&;;&suid&;;&sgid&;;&recursion&;;&fileAbsent& 8 | }& 9 | -------------------------------------------------------------------------------- /techniques/fileDistribution/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Distributing files 4 | 5 | Manage node files. 6 | 7 | 8 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/changelog: -------------------------------------------------------------------------------- 1 | -- Matthieu CERDA Fri, 9 Dec 2011 15:32:00 +0100 2 | * Version 2.1 3 | ** Added the possibility to delete a line based on a regexp 4 | ** Added the possibility to replace a line based on a regexp 5 | -- Nicolas CHARLES Tue, 15 Jan 2013 17:49:00 +0100 6 | * Version 3.2 7 | ** Added the possibility to enforce content of file only at creation 8 | -- Nicolas CHARLES Sun, 15 Dec 2013 19:00:00 +0100 9 | * Version 4.0 10 | ** Added possibility to enforce strictly the content of a section 11 | 12 | 13 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 14 | * Version 6.0 15 | ** Rewrite with normal ordering and {} 16 | ** Added possibility to check only a zone of file 17 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 18 | * Version 7.0 19 | ** Use rudder_common_report instead of reports: 20 | -- Nicolas Charles Wed Apr 4 09:40:14 2018 21 | * Version 8.0 22 | ** Port to multi-versioned format 23 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/tests/simple_content_enforce.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": [], 3 | "directives": "[simple_content_enforce.json"], 4 | "checks": ["simple_content_enforce.rb"], 5 | "sharedFiles":[], 6 | "name": "Test_checkGenericFileContent_v8_0_simple_content_enforce", 7 | "compliance": 100 8 | }] 9 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/tests/simple_content_enforce.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe file('/tmp/simple_content_enforce') do 4 | it { should be_file } 5 | it { should be_owned_by 'root' } 6 | its(:content) { should match /contenttest/ } 7 | end 8 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/tests/simple_content_replace.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent init { 5 | 6 | methods: 7 | "any" usebundle => file_enforce_content("/tmp/simple_content_replace", "replaceme", "true"); 8 | 9 | } 10 | 11 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/tests/simple_content_replace.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": ["simple_content_replace.cf"], 3 | "directives": ["simple_content_replace.json"], 4 | "checks": ["simple_content_replace.rb"], 5 | "sharedFiles":[], 6 | "name": "Test_checkGenericFileContent_v8_0_simple_content_replace", 7 | "compliance": 100 8 | }] 9 | -------------------------------------------------------------------------------- /techniques/fileDistribution/checkGenericFileContent/8.0/tests/simple_content_replace.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe file('/tmp/simple_content_replace') do 4 | it { should be_file } 5 | it { should be_owned_by 'root' } 6 | its(:content) { should match /contenttest/ } 7 | end 8 | -------------------------------------------------------------------------------- /techniques/fileDistribution/copyGitFile/2.3/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 2 | * Version 2.0 3 | ** Use rudder_common_report instead of reports: 4 | ** Add an option to purge local directory 5 | -- Nicolas Charles Fri Nov 13 18:20:30 CEST 2014 6 | * Version 2.1 7 | ** Add option to set sticky bit on whole folder 8 | -- Nicolas Charles Wed Dec 13 15:41:33 2017 9 | * Version 2.2 10 | ** Report on destination rather than on source 11 | -- Nicolas Charles Thu Dec 7 17:18:54 2017 12 | * Version 2.3 13 | ** Convert to multiversionned technique 14 | -------------------------------------------------------------------------------- /techniques/fileDistribution/copyGitFile/2.3/copyFileFromSharedFolder.ps1.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | function copyFileFromSharedFolder_&RudderUniqueID& { 5 | [CmdletBinding()] 6 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'reportId', Justification = 'Very old technique')] 7 | param ( 8 | [parameter(Mandatory=$true)] 9 | [string]$reportId, 10 | 11 | [parameter(Mandatory=$true)] 12 | [string]$techniqueName, 13 | 14 | [Rudder.PolicyMode]$policyMode 15 | ) 16 | 17 | $trackingkey = @( 18 | &TRACKINGKEY:{directiveId | 19 | "&directiveId&" };separator=","& ) 20 | 21 | $names = @( 22 | ©FILE_NAME:{name | 23 | "&name&" };separator=","& ) 24 | 25 | $destinations = @( 26 | ©FILE_DESTINATION:{destination | 27 | "&destination&" };separator=","& ) 28 | 29 | $posthooks = @( 30 | ©FILE_POST_HOOK_COMMAND:{posthook | 31 | "&posthook&" };separator=","& ) 32 | 33 | for ($i=0; $i -lt $trackingkey.length; $i++) { 34 | $commonParams = @{ 35 | TechniqueName = $techniqueName 36 | PolicyMode = $policyMode 37 | ClassPrefix = "copyGitFile_&RUDDERUniqueID&" 38 | ReportID = $trackingkey[$i] 39 | } 40 | $downloadCall = File-From-Shared-Folder -Source $names[$i] -Path $destinations[$i] -HashType "sha256" -PolicyMode $policyMode 41 | $downloadParams = $commonParams + @{ 42 | ComponentName = "Copy file" 43 | ComponentKey = $destinations[$i] 44 | } 45 | $null = Compute-Method-Call -MethodCall $downloadCall @downloadParams 46 | 47 | #Posthook execution 48 | $posthookParams = $commonParams + @{ 49 | ComponentName = "Post-modification hook" 50 | ComponentKey = $destinations[$i] 51 | } 52 | if ((-not([String]::IsNullOrEmpty($posthooks[$i]))) -And ($downloadCall.MethodStatus -eq ([Rudder.MethodStatus]::Repaired))) { 53 | $posthookCall = Command-Execution -Command $posthooks[$i] -PolicyMode $policyMode 54 | $null = Compute-Method-Call -MethodCall $posthookCall @posthookParams 55 | } else { 56 | $message = if ([String]::IsNullOrEmpty($posthooks[$i])) { 57 | "No posthook defined" 58 | } else { 59 | "No posthook execution needed" 60 | } 61 | $null = Rudder-Report-NA @postHookParams -Message $message 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /techniques/fileDistribution/downloadFile/4.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 2 | * Version 3.0 3 | ** Use rudder_common_report instead of reports: 4 | -- Nicolas Charles Tue Dec 18 17:53:26 2018 5 | * Version 4.0 6 | ** Support separated policy generation 7 | -------------------------------------------------------------------------------- /techniques/fileDistribution/downloadFile/4.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique downloads a file from a HTTP server. 4 | 5 | It takes a cURL compatible source (HTTP/FTP/...) and a destination on the target host. 6 | If cURL is not available, it will try to use minicurl.pl, a LWP-based Perl script. 7 | 8 | 9 | 10 | execute_file_download_RudderUniqueID 11 | 12 | 13 | true 14 | separated 15 | 16 | 17 | 18 | 19 | 20 | 21 | DOWNLOADFILE_SOURCE 22 | 23 | 24 | 25 |
26 |
27 | 28 | DOWNLOADFILE_SOURCE 29 | File URL 30 | For example http://server/file or ftp://server/file. cURL/miniperl will do its best to use what you pass to it as a URL. It is not trying to validate it as a syntactically correct URL by any means but is instead very liberal with what it accepts. 31 | 32 | 33 | DOWNLOADFILE_DESTINATION 34 | Full path of the downloaded file 35 | This path must be absolute, for example /home/foo/file or C:\foo\file 36 | 37 | string 38 | (/.*)|([a-zA-Z]:[/\\].*) 39 | 40 | 41 |
42 | 43 |
44 | 45 | DOWNLOADFILE_USER 46 | File owner 47 | 48 | root 49 | 50 | 51 | 52 | DOWNLOADFILE_GROUP 53 | File group 54 | 55 | root 56 | 57 | 58 | 59 | DOWNLOADFILE_MODE 60 | File mode 61 | 62 | perm 63 | 640 64 | 65 | 66 |
67 |
68 |
69 | 70 |
71 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/loadVars.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "Test_filetemplate_v1_0_loadVars", 3 | "enabled": true, 4 | "longDescription": "", 5 | "parameters": { 6 | "section": { 7 | "name": "sections", 8 | "sections": [ 9 | { 10 | "section": { 11 | "name": "Variable definition", 12 | "vars": [ 13 | { 14 | "var": { 15 | "name": "GENERIC_VARIABLE_CONTENT", 16 | "value": "Alice" 17 | } 18 | }, 19 | { 20 | "var": { 21 | "name": "GENERIC_VARIABLE_NAME", 22 | "value": "nom1" 23 | } 24 | } 25 | ] 26 | } 27 | }, 28 | { 29 | "section": { 30 | "name": "Variable definition", 31 | "vars": [ 32 | { 33 | "var": { 34 | "name": "GENERIC_VARIABLE_CONTENT", 35 | "value": "1 chemin de la rue" 36 | } 37 | }, 38 | { 39 | "var": { 40 | "name": "GENERIC_VARIABLE_NAME", 41 | "value": "adresse1" 42 | } 43 | } 44 | ] 45 | } 46 | }, 47 | { 48 | "section": { 49 | "name": "Variable definition", 50 | "vars": [ 51 | { 52 | "var": { 53 | "name": "GENERIC_VARIABLE_CONTENT", 54 | "value": "Bob" 55 | } 56 | }, 57 | { 58 | "var": { 59 | "name": "GENERIC_VARIABLE_NAME", 60 | "value": "nom2" 61 | } 62 | } 63 | ] 64 | } 65 | } 66 | ] 67 | } 68 | }, 69 | "shortDescription": "", 70 | "techniqueName": "genericVariableDefinition", 71 | "techniqueVersion": "2.0" 72 | } 73 | 74 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/template1: -------------------------------------------------------------------------------- 1 | {{{vars.generic_variable_definition.nom1}}} habite {{{vars.generic_variable_definition.adresse1}}} 2 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_error_fileTemplate/test_error_fileTemplate.cf: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ncf -f 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # SPDX-FileCopyrightText: 2021 Normation SAS 4 | 5 | bundle agent init { 6 | vars: 7 | "gen_files" slist => {"test1.conf", "test2.conf", "posthooktest", "persistentPosthooktest"}; 8 | "src_files" slist => {"template1", "_tmp_test2_conf.tpl"}; 9 | "other_files" slist => {"/tmp/toRepairPosthook"}; 10 | 11 | methods: 12 | "any" usebundle => file_remove("/tmp/${gen_files}"); 13 | "any" usebundle => file_remove("/var/rudder/templates/${src_files}"); 14 | "any" usebundle => file_remove("${other_files}"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_error_fileTemplate/test_error_fileTemplate.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": ["test_error_fileTemplate.cf"], 3 | "directives": ["test_error_fileTemplate.json", "loadVars.json"], 4 | "checks": ["test_error_fileTemplate.rb"], 5 | "sharedFiles":["template1"], 6 | "name": "Test_fileTemplate_v1_0_test_error_fileTemplate", 7 | "compliance": 66.67 8 | }] 9 | 10 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_error_fileTemplate/test_error_fileTemplate.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | # Test with an inexistent template file, should failed 3 | describe file("/var/rudder/tmp/templates") do 4 | it { should be_directory } 5 | it { should be_mode 750 } 6 | it { should be_owned_by "root" } 7 | end 8 | 9 | describe file("/tmp/test3.conf") do 10 | it { should_not exist } 11 | end 12 | 13 | describe command("rudder agent run -r") do 14 | its(:stdout) { should match /^R: @@fileTemplate@@result_error@@.*?@@.*?@@.*?@@Load Template from a file or text input@@\/tmp\/test3.conf@@.*?The copy of the file.*?from the policy server to .*? could not be repaired$/m} 15 | end 16 | 17 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_fileTemplate/test_fileTemplate.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": [], 3 | "directives": ["test_fileTemplate.json", "loadVars.json"], 4 | "checks": ["test_fileTemplate.rb"], 5 | "sharedFiles":["template1"], 6 | "name": "Test_fileTemplate_v1_0_test_fileTemplate", 7 | "compliance": 100 8 | }] 9 | 10 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_fileTemplate/test_fileTemplate.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | describe file("/var/rudder/tmp/templates") do 3 | it { should be_directory } 4 | it { should be_mode 750 } 5 | it { should be_owned_by "root" } 6 | end 7 | 8 | describe file("/var/rudder/tmp/templates/template1") do 9 | it {should be_file} 10 | its(:content) { should match /{{{vars.generic_variable_definition.nom1}}} habite {{{vars.generic_variable_definition.adresse1}}}/ } 11 | end 12 | 13 | describe file("/var/rudder/tmp/templates/_tmp_test2_conf.tpl") do 14 | it {should be_file} 15 | its(:content) { should match /{{{vars.generic_variable_definition.nom1}}} et {{{vars.generic_variable_definition.nom2}}} habitent {{{vars.generic_variable_definition.adresse1}}}/ } 16 | end 17 | 18 | describe file("/tmp/test1.conf") do 19 | it { should be_file } 20 | it { should be_mode 700 } 21 | it { should be_owned_by "root" } 22 | its(:content) { should match /Alice habite 1 chemin de la rue/} 23 | end 24 | 25 | describe file("/tmp/test2.conf") do 26 | it { should be_file } 27 | it { should be_mode 770 } 28 | it { should be_owned_by "root" } 29 | its(:content) { should match /Alice et Bob habitent 1 chemin de la rue/} 30 | end 31 | 32 | 33 | describe command("rm -f -R /tmp/toRepairPosthook") do 34 | end 35 | 36 | describe command("rm -f /tmp/test1.conf") do 37 | end 38 | 39 | describe command("rm -f /tmp/posthookTest") do 40 | end 41 | 42 | describe command("rm -f /tmp/persistentPosthooktest") do 43 | end 44 | 45 | describe command("rm -f /var/rudder/tmp/templates/*") do 46 | end 47 | 48 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_posthook/test_posthook.cf: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ncf -f 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # SPDX-FileCopyrightText: 2021 Normation SAS 4 | 5 | bundle agent init { 6 | vars: 7 | "gen_files" slist => {"test1.conf", "test2.conf", "posthooktest", "persistentPosthooktest"}; 8 | "src_files" slist => {"template1", "_tmp_test2_conf.tpl"}; 9 | "other_files" slist => {"/tmp/toRepairPosthook"}; 10 | 11 | methods: 12 | "any" usebundle => file_remove("/tmp/${gen_files}"); 13 | "any" usebundle => file_remove("/var/rudder/templates/${src_files}"); 14 | "any" usebundle => file_remove("${other_files}"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_posthook/test_posthook.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": ["test_posthook.cf"], 3 | "directives": ["test_posthook.json", "loadVars.json"], 4 | "checks": ["test_posthook.rb"], 5 | "sharedFiles":["template1"], 6 | "name": "Test_fileTemplate_v1_0_test_posthook", 7 | "compliance": 100 8 | }] 9 | 10 | -------------------------------------------------------------------------------- /techniques/fileDistribution/fileTemplate/1.0/tests/test_posthook/test_posthook.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | # First run is done by technique scenario => persistent posthook launched 4 | describe command("rudder agent run -r") do 5 | its(:stdout) { should match /^R: @@fileTemplate@@result_na@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/posthookTest@@.*?No post-modification needed to run$/m} 6 | 7 | its(:stdout) { should match /^R: @@fileTemplate@@result_error@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/persistentPosthooktest@@.*?The command .*?from postHook execution could not be repaired$/m} 8 | end 9 | 10 | # Force the execution of the posthook 11 | describe command("rm -f /tmp/posthookTest /tmp/persistentPosthookTest") do 12 | end 13 | 14 | describe command("rudder agent run -r") do 15 | its(:stdout) { should match /^R: @@fileTemplate@@result_repaired@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/posthookTest@@.*?The command .*?from postHook execution was repaired$/m} 16 | 17 | its(:stdout) { should match /^R: @@fileTemplate@@result_error@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/persistentPosthooktest@@.*?The command .*?from postHook execution could not be repaired$/m} 18 | end 19 | 20 | # We retry to ensure that the persistent one continues 21 | 22 | describe command("rudder agent run -r") do 23 | 24 | its(:stdout) { should match /^R: @@fileTemplate@@result_na@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/posthookTest@@.*?No post-modification needed to run$/m} 25 | 26 | its(:stdout) { should match /^R: @@fileTemplate@@result_error@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/persistentPosthooktest@@.*?The command .*?from postHook execution could not be repaired$/m} 27 | end 28 | 29 | # Resolution of the persistent posthook 30 | describe command("mkdir /tmp/toRepairPosthook; rudder agent run -r") do 31 | 32 | its(:stdout) { should match /^R: @@fileTemplate@@result_na@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/posthookTest@@.*?No post-modification needed to run$/m} 33 | 34 | its(:stdout) { should match /^R: @@fileTemplate@@result_repaired@@.*?@@.*?@@.*?@@Posthook@@\/tmp\/persistentPosthooktest@@.*?The command .*?from postHook execution was repaired$/m} 35 | end 36 | 37 | describe command("rm -rf /tmp/toRepairPosthook") do 38 | end 39 | 40 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas Charles Tue Sep 12 18:45:08 2017 2 | * Version 1.1 3 | ** Add an option to be strict on spaces around separator 4 | -- Nicolas Charles Thu Dec 7 17:20:54 2017 5 | * Version 1.2 6 | ** Convert to multiversionned technique 7 | -- Benoît Peccatte Thu Feb 15 15:18:30 2018 8 | * Version 1.3 9 | ** Add post-hook 10 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/manage-key-value-file.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent manage_key_value_file_&RudderUniqueID& { 5 | vars: 6 | &MANAGE_KEY_VALUE_FILEPATH:{file | "file[&i&]" string => "&file&"; 7 | }& 8 | &MANAGE_KEY_VALUE_KEY:{key | "key[&i&]" string => "&key&"; 9 | }& 10 | &MANAGE_KEY_VALUE_VALUE:{value | "value[&i&]" string => "&value&"; 11 | }& 12 | &MANAGE_KEY_VALUE_SEPARATOR:{separator | "separator[&i&]" string => "&separator&"; 13 | }& 14 | &MANAGE_KEY_VALUE_OPTION:{option | "option[&i&]" string => "&option&"; 15 | }& 16 | &MANAGE_KEY_VALUE_POST_HOOK_COMMAND:{post_hook | "post_hook[&i&]" string => "&post_hook&"; 17 | }& 18 | &TRACKINGKEY:{uuid | "trackingkey[&i&]" string => "&uuid&"; 19 | }& 20 | 21 | 22 | "index" slist => getindices("file"); 23 | 24 | "args" slist => { "${file[${index}]}", "${key[${index}]}", "${value[${index}]}","${separator[${index}]}", "${option[${index}]}" }; 25 | "report_param[${index}]" string => join("_", args); 26 | "canonified_params[${index}]" string => canonify("${report_param[${index}]}"); 27 | "canonified_hook[${index}]" string => canonify("${post_hook[${index}]}"); 28 | 29 | "class_prefix_${index}" string => "file_ensure_key_value_${canonified_params[${index}]}"; 30 | "hook_class_prefix_${index}" string => "command_execution_${canonified_hook[${index}]}"; 31 | "technique_name" string => "Manage keys-values file"; 32 | 33 | classes: 34 | "hook_empty_${index}" expression => strcmp("${post_hook[${index}]}", ""); 35 | 36 | methods: 37 | "apply_${index}" usebundle => file_ensure_key_value_option("${file[${index}]}", "${key[${index}]}", "${value[${index}]}", "${separator[${index}]}", "${option[${index}]}"); 38 | "report_${index}" usebundle => rudder_common_reports_generic_index("${technique_name}", "${class_prefix_${index}}", "${trackingkey[${index}]}", "File", "${file[${index}]}", "The key -> value ${key[${index}]} ${separator[${index}]} ${value[${index}]} with ${option[${index}]} spacing around the separator", "${index}"); 39 | 40 | # call post-hooks 41 | "apply_${index}" usebundle => command_execution("${post_hook[${index}]}"), 42 | ifvarclass => "!hook_empty_${index}.${class_prefix_${index}}_repaired"; 43 | "na_report" usebundle => _classes_noop("${hook_class_prefix_${index}}"), 44 | ifvarclass => "hook_empty_${index}|${class_prefix_${index}}_kept|${class_prefix_${index}}_error"; 45 | "report_${index}" usebundle => rudder_common_reports_generic_index("${technique_name}", "${hook_class_prefix_${index}}", "${trackingkey[${index}]}", "Post-modification script", "${file[${index}]}", "The hook '${post_hook[${index}]}'", "${index}"); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Manage keys-values in file 5 | true 6 | separated 7 | 8 | manage_key_value_file_RudderUniqueID 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | MANAGE_KEY_VALUE_FILEPATH 17 | 18 | 19 | 20 |
21 |
22 | 23 | MANAGE_KEY_VALUE_FILEPATH 24 | Path of the file to manage 25 | 26 | 27 | MANAGE_KEY_VALUE_KEY 28 | Key to define 29 | 30 | string 31 | 32 | 33 | 34 | MANAGE_KEY_VALUE_VALUE 35 | Value to define 36 | 37 | string 38 | true 39 | 40 | 41 | 42 | MANAGE_KEY_VALUE_SEPARATOR 43 | Separator between key and value (for example "=") 44 | If you need to use space as a separator, you should use ${ncf_const.s} value. 45 | 46 | string 47 | 48 | 49 | 50 | MANAGE_KEY_VALUE_OPTION 51 | Prevent spaces around separator 52 | If "No spacing" is selected, this will prevent any spaces around the separator, enforcing strictly KEY=VALUE; otherwise any number of spaces will be accepted before or after the separator. 53 | 54 | strict 55 | 56 | 57 | 58 | lax 59 | 60 | 61 | 62 | lax 63 | 64 | 65 |
66 |
67 | 68 | MANAGE_KEY_VALUE_POST_HOOK_COMMAND 69 | Command to run after changes on one file 70 | 71 | textarea 72 | true 73 | 74 | 75 |
76 |
77 |
78 |
79 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_create.cf: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ncf -f 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # SPDX-FileCopyrightText: 2021 Normation SAS 4 | 5 | bundle agent init { 6 | 7 | methods: 8 | "any" usebundle => file_remove("/tmp/manage-key-value"); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_create.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": [ "simple_key_create.cf" ], 3 | "directives": [ "simple_key_replace.json" ], 4 | "checks": [ "simple_key_replace.rb" ], 5 | "sharedFiles":[], 6 | "compliance": 100 7 | }] 8 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_replace.cf: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ncf -f 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # SPDX-FileCopyrightText: 2021 Normation SAS 4 | 5 | bundle agent init { 6 | 7 | methods: 8 | "any" usebundle => file_enforce_content("/tmp/manage-key-value", "", "true"); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_replace.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "Manage keys-values in file /tmp/manage-key-value", 3 | "shortDescription": "", 4 | "longDescription": "Set key=value in this file", 5 | "techniqueName": "manageKeyValueFile", 6 | "techniqueVersion": "1.0", 7 | "parameters": { 8 | "section": { 9 | "name": "sections", 10 | "sections": [ 11 | { 12 | "section": { 13 | "name": "File to manage", 14 | "sections": [ 15 | { 16 | "section": { 17 | "name": "File", 18 | "vars": [ 19 | { 20 | "var": { 21 | "name": "MANAGE_KEY_VALUE_FILEPATH", 22 | "value": "/tmp/manage-key-value" 23 | } 24 | }, 25 | { 26 | "var": { 27 | "name": "MANAGE_KEY_VALUE_KEY", 28 | "value": "key" 29 | } 30 | }, 31 | { 32 | "var": { 33 | "name": "MANAGE_KEY_VALUE_SEPARATOR", 34 | "value": "=" 35 | } 36 | }, 37 | { 38 | "var": { 39 | "name": "MANAGE_KEY_VALUE_VALUE", 40 | "value": "value" 41 | } 42 | } 43 | ] 44 | } 45 | } 46 | ] 47 | } 48 | } 49 | ] 50 | } 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_replace.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": [ "simple_key_replace.cf" ], 3 | "directives": [ "simple_key_replace.json" ], 4 | "checks": [ "simple_key_replace.rb" ], 5 | "sharedFiles": [], 6 | "compliance": 100 7 | }] 8 | -------------------------------------------------------------------------------- /techniques/fileDistribution/manageKeyValueFile/1.3/tests/simple_key_replace.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe file('/tmp/manage-key-value') do 4 | it { should be_file } 5 | it { should be_owned_by 'root' } 6 | its(:content) { should match /key=value/ } 7 | end 8 | -------------------------------------------------------------------------------- /techniques/jobScheduling/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Job scheduling 4 | This category contains Techniques to schedule jobs across groups of nodes 5 | 6 | -------------------------------------------------------------------------------- /techniques/jobScheduling/jobScheduler/3.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Thu Oct 23 13:41:08 CEST 2014 2 | * Version 2.0 3 | ** Use rudder_common_report instead of reports: 4 | -- Nicolas Charles Fri Nov 16 10:41:19 2018 5 | * Version 3.0 6 | ** Support non default agent schedule 7 | -------------------------------------------------------------------------------- /techniques/ncf_techniques/category.xml: -------------------------------------------------------------------------------- 1 | 2 | User Techniques 3 | 4 | Techniques created using the Technique editor. 5 | 6 | 7 | -------------------------------------------------------------------------------- /techniques/system/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | System Techniques 4 | 5 | This category contains internal Techniques (system). 6 | These Techniques should not be used directly. 7 | 8 | true 9 | 10 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/common.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # Common variable for common system technique 5 | bundle common system_common { 6 | vars: 7 | "directiveId" string => "&TRACKINGKEY&"; 8 | "sharedfiles_folder" string => "${g.shared_files}"; 9 | "cf_serverd_port" string => "&COMMUNITYPORT&"; 10 | "community_port" string => "${server_info.policy_server_port}"; 11 | "uuid" string => "&UUID&"; 12 | "davuser" string => "&DAVUSER&"; 13 | "davpw" string => "&DAVPASSWORD&"; 14 | "rudder_configuration_repository" 15 | string => "&CONFIGURATION_REPOSITORY_FOLDER&"; 16 | "rudder_node_config_id" string => "&RUDDER_NODE_CONFIG_ID&"; 17 | "agent_run_interval" string => "&AGENT_RUN_INTERVAL&"; 18 | 19 | "cf_serverd_service_name" string => "rudder-cf-serverd"; 20 | 21 | system_common_pass3.executor:: 22 | "inventory_splay_hex" string => string_head(hash("${sys.host}", "md5"), "7"); 23 | # first line is the data used to create splay hash 24 | # +0 is the uid of the user we use to run (root) 25 | # Other lines are used to compute real splay time 26 | "executor_data" string => execresult("printf '${sys.fqhost}+${sys.ipv4}+0\n${sys.systime}\n&AGENT_RUN_SPLAYTIME&\n${agent_run_interval}\n${inventory_splay_hex}\n' > /var/rudder/tmp/cf-execd.data ", "useshell"); 27 | 28 | classes: 29 | &if(INITIAL)& 30 | "initial_promises" expression => "any", scope => "namespace"; 31 | &endif& 32 | 33 | "system_common_pass3" expression => "system_common_pass2"; 34 | "system_common_pass2" expression => "any"; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/cron-setup.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent setup_cronjob 5 | { 6 | vars: 7 | pass2.in_hours:: 8 | # seq is not posix. We are using awk for improved portability 9 | "interval_str" string => eval("${system_common.agent_run_interval} / 60", "math", "infix"); 10 | "interval" string => format("%d", "${interval_str}"); 11 | "steps" string => execresult("echo '0 23' | ${paths.awk} '{ for (i=$1;i<=$2;i=i+${interval}) { printf \"%s%s\", sep, i; sep=\",\"}} END{print \"\"}'", "useshell"); 12 | "cron_prefix" string => "0 ${steps} * * *"; 13 | 14 | pass2.!in_hours:: 15 | "steps" string => execresult("echo '0 59' | ${paths.awk} '{ for (i=$1;i<=$2;i=i+${system_common.agent_run_interval}) { printf \"%s%s\", sep, i; sep=\",\"}} END{print \"\"}'", "useshell"); 16 | "cron_prefix" string => "${steps} * * * *"; 17 | 18 | classes: 19 | "in_hours" expression => isgreaterthan("${system_common.agent_run_interval}","60"); 20 | "pass2" expression => "any"; 21 | 22 | files: 23 | 24 | pass2:: 25 | "/etc/cron.d/rudder-agent" 26 | create => "true", 27 | perms => mog("644", "root", "0"), 28 | edit_defaults => empty_backup, 29 | template_method => "mustache", 30 | edit_template => "${sys.workdir}/inputs/common/cron/rudder-agent-community-cron"; 31 | } 32 | 33 | ####################################################### 34 | # Check if the cron daemon is running 35 | # This only works with unix flavoured systems too 36 | 37 | bundle agent check_cron_daemon 38 | { 39 | vars: 40 | 41 | redhat|fedora|slackware:: 42 | "service_name" string => "crond"; 43 | !(redhat|fedora|slackware):: 44 | "service_name" string => "cron"; 45 | 46 | classes: 47 | 48 | any:: 49 | "pass3" expression => "pass2"; 50 | "pass2" expression => "pass1"; 51 | "pass1" expression => "any"; 52 | 53 | methods: 54 | "restart_cron" usebundle => disable_reporting; 55 | "restart_cron" usebundle => _method_reporting_context("CRON Daemon", "None"); 56 | "check_cron_service" 57 | usebundle => service_check_running("${service_name}"); 58 | 59 | "restart_cron" usebundle => service_restart("${service_name}"), 60 | if => "(rudder_system_user_crontab_insertion_repaired|service_check_running_${service_name}_error)"; 61 | "restart_cron" usebundle => enable_reporting; 62 | 63 | 64 | pass3:: 65 | "any" usebundle => rudder_common_reports_generic("Common", "service_restart_${service_name}", "${system_common.directiveId}", "CRON Daemon", "None", "Cron daemon status"), 66 | if => "(rudder_system_user_crontab_insertion_repaired|service_check_running_${service_name}_error)"; 67 | 68 | "any" usebundle => rudder_common_report("Common", "result_success", "${system_common.directiveId}", "CRON Daemon", "None", "CRON is correctly running"), 69 | if => "!(rudder_system_user_crontab_insertion_repaired|service_check_running_${service_name}_error)"; 70 | } 71 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/environment-variables.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # Define module script to read environment variables, in the module format 5 | # Store them in the node.env context 6 | bundle agent get_environment_variables 7 | { 8 | vars: 9 | agent:: 10 | "env_vars_list_cmd" string => "awk 'BEGIN { for (k in ENVIRON) { print k }; }'"; 11 | "env_vars" slist => splitstring( execresult("${env_vars_list_cmd}","useshell"), "\n" , 2000); 12 | "node.env[${env_vars}]" string => getenv( "${env_vars}", 5000); 13 | } 14 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/internal-security.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent internal_security 5 | { 6 | vars: 7 | 8 | "mode" string => "600"; 9 | "user" string => "root"; 10 | "group" string => "0"; # This is "root" on most UNIX-like systems, but "system" on AIX 11 | 12 | files: 13 | 14 | "${g.rudder_var}/modified-files" 15 | perms => mog("${mode}", "${user}", "${group}"), 16 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 17 | 18 | "${g.rudder_var}/tmp" 19 | perms => mog("${mode}", "${user}", "${group}"), 20 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 21 | 22 | "${g.rudder_var}/reports/ready" 23 | perms => mog("${mode}", "${user}", "${group}"), 24 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 25 | 26 | "${sys.workdir}/inputs" 27 | depth_search => recurse("inf"), 28 | perms => mog("${mode}", "${user}", "${group}"), 29 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 30 | 31 | "${sys.workdir}/inputs" 32 | perms => mog("${mode}", "${user}", "${group}"), 33 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 34 | 35 | "${sys.workdir}/ppkeys" 36 | depth_search => recurse("inf"), 37 | perms => mog("${mode}", "${user}", "${group}"), 38 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 39 | 40 | "${sys.workdir}/ppkeys" 41 | perms => mog("${mode}", "${user}", "${group}"), 42 | classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); 43 | 44 | methods: 45 | 46 | security_sanitization_ok.!security_sanitization_repaired:: 47 | "any" usebundle => rudder_common_report("Common", "result_success", "${system_common.directiveId}", "Security parameters", "None", "The internal environment security is acceptable"); 48 | 49 | security_sanitization_repaired:: 50 | "any" usebundle => rudder_common_report("Common", "result_repaired", "${system_common.directiveId}", "Security parameters", "None", "Some internal security parameters were adjusted"); 51 | 52 | security_sanitization_failed:: 53 | "any" usebundle => rudder_common_report("Common", "result_error", "${system_common.directiveId}", "Security parameters", "None", "The internal environment security is NOT acceptable!"); 54 | } 55 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/monitoring.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent monitoring_hook_pre 5 | { 6 | methods: 7 | "reporting" usebundle => disable_reporting; 8 | "reporting_pre" usebundle => _method_reporting_context("Monitoring", "None"); 9 | "deletion" usebundle => file_absent("/var/rudder/tmp/rudder_monitoring.csv"); 10 | "reporting" usebundle => enable_reporting; 11 | } 12 | 13 | bundle agent monitoring_hook_post 14 | { 15 | classes: 16 | "csv_exists" expression => fileexists("/var/rudder/tmp/rudder_monitoring.csv"); 17 | 18 | methods: 19 | "reporting" usebundle => disable_reporting; 20 | "reporting" usebundle => _method_reporting_context("Monitoring", "None"); 21 | 22 | csv_exists:: 23 | "share file" usebundle => sharedfile_to_node("root", "rudder_monitoring.csv", "/var/rudder/tmp/rudder_monitoring.csv", "1d"); 24 | 25 | any:: 26 | "reporting" usebundle => enable_reporting; 27 | 28 | csv_exists:: 29 | "reporting" usebundle => rudder_common_reports_generic("Common", "sharedfile_to_node_rudder_monitoring_csv", "${system_common.directiveId}", "Monitoring", "None", "Share Rudder monitoring information with the server"); 30 | 31 | !csv_exists:: 32 | "reporting" usebundle => rudder_common_report("Common", "result_na", "${system_common.directiveId}", "Monitoring", "None", "No Rudder monitoring information to share with the server"); 33 | } 34 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/reporting-http.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent send_rudder_report(path) { 5 | vars: 6 | "c_path" string => canonify("${path}"); 7 | "endpoint" string => "https://${server_info.policy_server}/reports/"; 8 | 9 | files: 10 | "${path}" 11 | delete => tidy, 12 | if => "send_report_${c_path}_ok", 13 | classes => classes_generic("tidy_report_${c_path}"); 14 | 15 | methods: 16 | "any" usebundle => rudder_common_report("Common", "log_warn", "${system_common.directiveId}", "Log system for reports", "None", "Could not send report ${path}"), 17 | if => "send_report_${c_path}_error"; 18 | # May be a another done by another agent run 19 | "any" usebundle => rudder_common_report("Common", "log_warn", "${system_common.directiveId}", "Log system for reports", "None", "Could not remove report ${path}"), 20 | if => "tidy_report_${c_path}_error"; 21 | 22 | commands: 23 | "/opt/rudder/bin/rudder-client -e /reports/ -- --upload-file ${path}" 24 | classes => classes_generic_two("send_report_${c_path}", "send_rudder_reports"); 25 | } 26 | 27 | bundle agent send_rudder_reports 28 | { 29 | vars: 30 | agent_capability_http_reporting:: 31 | "raw_reports" slist => lsdir("${g.rudder_reports}/ready/", ".+\.log\.gz", "false"); 32 | # Max 50 reports by run to avoid blocking the agent too long after a long 33 | # disconnection 34 | "reports" slist => sublist("raw_reports", "head", 50); 35 | "nb_reports" int => length("reports"); 36 | 37 | classes: 38 | "has_reports" not => strcmp("${nb_reports}", "0"); 39 | 40 | methods: 41 | has_reports:: 42 | "send" usebundle => send_rudder_report("${g.rudder_reports}/ready/${reports}"); 43 | "cleanup" usebundle => _classes_sanitize("send_rudder_reports"); 44 | !has_reports:: 45 | "cleanup" usebundle => _classes_success("send_rudder_reports"); 46 | any:: 47 | "report" usebundle => rudder_common_reports_generic("Common", "send_rudder_reports", "${system_common.directiveId}", "Log system for reports", "None", "Reports forwarding to policy server"); 48 | 49 | "cleanup" usebundle => clean_old_rudder_reports; 50 | } 51 | 52 | bundle agent clean_old_rudder_reports 53 | { 54 | files: 55 | "${g.rudder_reports}/ready/" 56 | delete => tidy, 57 | file_select => days_old("7"), 58 | depth_search => recurse("inf"); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rpm-key.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2024 Normation SAS 3 | 4 | bundle agent import_rpm_key 5 | { 6 | methods: 7 | redhat|suse:: 8 | "disable_reporting_rpm_key" usebundle => disable_reporting; 9 | "check trusted key" usebundle => audit_from_command("rpm -q gpg-pubkey-474a19e8-4eea5279", 0); 10 | "import key" usebundle => command_execution("rpm --import ${sys.workdir}/inputs/common/1.0/rudder_release_key.pub"), 11 | if => "audit_from_command_rpm__q_gpg_pubkey_474a19e8_4eea5279_error"; 12 | "enable_reporting_rpm_key" usebundle => enable_reporting; 13 | 14 | "any" usebundle => rudder_common_report("Common", "result_success", "${system_common.directiveId}", "GPG key", "None", "GPG key for RPM is trusted"), 15 | if => "audit_from_command_rpm__q_gpg_pubkey_474a19e8_4eea5279_kept"; 16 | "any" usebundle => rudder_common_report("Common", "result_repaired", "${system_common.directiveId}", "GPG key", "None", "GPG key for RPM has been imported"), 17 | if => canonify("command_execution_rpm___import_${sys.workdir}_inputs_common_1_0_rudder_release_key_pub_repaired"); 18 | "any" usebundle => rudder_common_report("Common", "result_error", "${system_common.directiveId}", "GPG key", "None", "GPG key for RPM could not be imported"), 19 | if => canonify("command_execution_rpm___import_${sys.workdir}_inputs_common_1_0_rudder_release_key_pub_error"); 20 | 21 | !(redhat|suse):: 22 | "report NA" usebundle => rudder_common_report("Common", "result_na", "${system_common.directiveId}", "GPG key", "None", "No GPG key trust needed"); 23 | } 24 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-agent-community-cron: -------------------------------------------------------------------------------- 1 | # Cron file for Rudder 2 | # 3 | # Will manually run cf-agent in case cf-execd is no longer running. cf-agent will fire up a new cf-execd. 4 | # 5 | # To temporarily avoid this behaviour, run 'rudder agent disable' 6 | 7 | {{#classes.slackware}} 8 | {{{vars.setup_cronjob.cron_prefix}}} /opt/rudder/bin/rudder agent check -q >> /var/log/rudder/agent-check/check.log 2>&1 9 | {{/classes.slackware}} 10 | {{^classes.slackware}} 11 | {{{vars.setup_cronjob.cron_prefix}}} root /opt/rudder/bin/rudder agent check -q >> /var/log/rudder/agent-check/check.log 2>&1 12 | {{/classes.slackware}} 13 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-directives.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # This file is the main entry points for the bundle sequence for 5 | # Rudder user directives. It is actually a list of method calls, and not 6 | # a bundle sequence, which allows to add the technique or directives 7 | # names as promiser. 8 | 9 | body file control { 10 | 11 | inputs => { 12 | &RUDDER_DIRECTIVES_INPUTS& 13 | }; 14 | 15 | } 16 | 17 | 18 | bundle agent rudder_directives { 19 | # The directive sequence will be correctly indented by the generated variable so we can support multiline variable 20 | methods: 21 | &RUDDER_DIRECTIVES_SEQUENCE& 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-groups.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # This file contains all the groups where the node belongs to. The groups are available on two ways: 5 | # 1/ two classes are added for each groups: 6 | # - group_UUID with UUID replaced by the group unique identifier 7 | # - group_NAME with NAME replaced by the transliteration of the group name to lower-case ascii, and the 8 | # canonification of the result 9 | # 2/ an array "by_uuid" of UUID -> ORIG_NAME, available as a global variable (for example for processing 10 | # all node groups to use in templates) 11 | # 12 | # For example, if node belongs to group: (id: 64f85ba8-39c7-418a-a099-24c2c2909dfd ; name: "Serveurs pré-prod") 13 | # we will have the following classes: 14 | # - group_64f85ba8_39c7_418a_a099_24c2c2909dfd 15 | # - group_serveurs_pre_prod 16 | # and vars: 17 | # - by_uuid["64f85ba8-39c7-418a-a099-24c2c2909dfd"] = "Serveurs pré-prod" 18 | # More over, each value of the array will have an attribute "meta": { "inventory", "attribute_name=rudder_groups" } 19 | # 20 | bundle common rudder_groups { 21 | 22 | vars: 23 | &RUDDER_NODE_GROUPS_VARS& 24 | 25 | classes: 26 | &RUDDER_NODE_GROUPS_CLASSES& 27 | 28 | } 29 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-parameters.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # This file contain the Global Parameters, to be available within all 5 | # promises, in the form ${rudder_parameters.parameterName} 6 | 7 | # WARNING: This syntax will be deprecated, use the new one defined below ("rudder.parameters[]"). 8 | 9 | bundle common rudder_parameters { 10 | vars: 11 | &RUDDER_PARAMETERS:{parameter | "¶meter.escapedParameterName&" string => "¶meter.escapedValue&"; 12 | }& 13 | } 14 | 15 | 16 | # Read rudder global parameters and put them into the rudder bundle 17 | # 18 | # Parameters are available using the rudder.parameters container that contains the values 19 | # Those values are read from /var/rudder/cfengine-community/inputs/rudder-parameters.json 20 | # 21 | # The file must contain at least a 2 levels JSON content, the first level is the namespace level 22 | # (namely parameters) and the second level is the key level. 23 | # The namespace name must comply with CFEngine variable names rules (ie [a-zA-Z_]+) 24 | # 25 | 26 | # The result key is available in the rudder. data variable 27 | # usage example: ${rudder.parameters[my_global_parameter]} 28 | # 29 | bundle agent rudder_global_parameters 30 | { 31 | vars: 32 | # The files to read 33 | "parameters_file" string => "${this.promise_dirname}/../../rudder-parameters.json"; 34 | 35 | # Read the files, 10MB maximum 36 | "parameters" data => readjson("${parameters_file}", "10000000"); 37 | 38 | # Get namespace names 39 | "namespaces" slist => getindices("parameters"); 40 | 41 | # Define the result variable 42 | "rudder.${namespaces}" data => mergedata("parameters[${namespaces}]", "{}"); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-promises-generated.st: -------------------------------------------------------------------------------- 1 | &GENERATIONTIMESTAMP& 2 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-system-directives.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # This file is the main entry points for the bundle sequence for 5 | # Rudder system directives. It is actually a list of method calls, and not 6 | # a bundle sequence, which allows to add the technique or directives 7 | # names as promiser. 8 | 9 | body file control { 10 | 11 | inputs => { 12 | &RUDDER_SYSTEM_DIRECTIVES_INPUTS& 13 | }; 14 | 15 | } 16 | 17 | 18 | bundle agent rudder_system_directives { 19 | # fully generated in bundle common va for iinitial promises 20 | # The directive sequence will be correctly indented by the generated variable so we can support multiline variable 21 | methods: 22 | &RUDDER_SYSTEM_DIRECTIVES_SEQUENCE& 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder-vars.st: -------------------------------------------------------------------------------- 1 | &RUDDER_INVENTORY_VARS& 2 | 3 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/rudder_promises_generated.st: -------------------------------------------------------------------------------- 1 | &GENERATIONTIMESTAMP& 2 | -------------------------------------------------------------------------------- /techniques/system/common/1.0/run_interval.st: -------------------------------------------------------------------------------- 1 | &AGENT_RUN_INTERVAL& 2 | -------------------------------------------------------------------------------- /techniques/system/inventory/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Inventory of the computer 4 | 5 | true 6 | 7 | false 8 | 9 | 10 | AGENT_RUN_INTERVAL 11 | 12 | 13 | 14 | doInventory 15 | 16 | 17 | 18 | 19 | 20 | inventory/1.0/test-inventory.pl 21 | false 22 | 23 | 24 | 25 | 26 |
27 | 28 | None 29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/apache/apache-certificate.cf: -------------------------------------------------------------------------------- 1 | bundle agent apache_cert(trackingkey, technique_name) 2 | { 3 | vars: 4 | "component" string => "Configure apache certificate"; 5 | 6 | "ssl_ca_file" string => "nodescerts.pem"; 7 | # Concatenated list of sub-nodes certificates 8 | # Also used by relayd 9 | "nodes_certs" string => "${g.rudder_var}/lib/ssl/${ssl_ca_file}"; 10 | 11 | "nodes_certs_src" string => "${this.promise_dirname}/${ssl_ca_file}"; 12 | # Before first generation we do not have a nodescerts.pem, 13 | # so we use local cert to allow starting apache 14 | "nodes_certs_default" string => "${g.rudder_base}/etc/ssl/agent.cert"; 15 | 16 | "nodes_certs_src_size" string => filestat("${nodes_certs_src}", "size"); 17 | 18 | "copy_prefix" string => canonify("file_from_local_source_${src_ca_file}_${nodes_certs}_0"); 19 | "perms_prefix" string => canonify("permissions_${nodes_certs}_640_root_rudder"); 20 | 21 | 22 | pass1:: 23 | "src_ca_file" string => "${nodes_certs_src}", 24 | if => "!empty_ssl_ca"; 25 | "src_ca_file" string => "${nodes_certs_default}", 26 | if => "empty_ssl_ca"; 27 | 28 | classes: 29 | "empty_ssl_ca" expression => strcmp("${nodes_certs_src_size}", "0"); 30 | 31 | "pass3" expression => "pass2"; 32 | "pass2" expression => "pass1"; 33 | "pass1" expression => "any"; 34 | 35 | "rudder_server_system_reload_apache" expression => or("${copy_prefix}_repaired", "${perms_prefix}_repaired"), 36 | scope => "namespace"; 37 | 38 | methods: 39 | pass2:: 40 | # Copy the right file in the expected path 41 | "any" usebundle => _method_reporting_context_v4("${component}", "Apache certificate", "apache_certificate"); 42 | "any" usebundle => file_from_local_source_recursion("${src_ca_file}", "${nodes_certs}", "0"); 43 | 44 | "any" usebundle => _method_reporting_context_v4("${component}", "Permissions", "apache_certificate_permissions"); 45 | "any" usebundle => permissions("${nodes_certs}", "640", "root", "rudder"); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/apache/apache-logrotate.mustache: -------------------------------------------------------------------------------- 1 | {{#vars.system_apache_logrotate.apache_logs}} 2 | {{{.name}}} { 3 | daily 4 | missingok 5 | rotate {{{.duration}}} 6 | compress 7 | notifempty 8 | create {{{.create}}} 9 | delaycompress 10 | sharedscripts 11 | postrotate 12 | {{{.postrotate}}} 13 | endscript 14 | } 15 | {{/vars.system_apache_logrotate.apache_logs}} 16 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/apache/logrotate.cf: -------------------------------------------------------------------------------- 1 | bundle agent system_apache_logrotate { 2 | vars: 3 | pass1.!duration_configured:: 4 | "logrotate_duration" string => "30"; 5 | pass1.duration_configured:: 6 | "logrotate_duration" string => "${rudder_parameters.log_duration}"; 7 | 8 | pass1:: 9 | "apache_logs" data => parsejson('{ 10 | "name": "${g.rudder_log}/apache2/*.log", 11 | "duration": "${logrotate_duration}", 12 | "create": "${rudder_syslog.file_mode} ${rudder_syslog.user_name} ${rudder_syslog.group_name}" 13 | "postrotate": "systemctl reload ${rudder_apache.service_name} > /dev/null || true" 14 | }'); 15 | 16 | classes: 17 | "pass2" expression => "pass1"; 18 | "pass1" expression => "any"; 19 | "duration_configured" expression => isvariable("rudder_parameters.log_duration"); 20 | 21 | files: 22 | "/etc/logrotate.d/rudder" 23 | delete => tidy, 24 | comment => "Removing logrotate file from 6.x"; 25 | 26 | methods: 27 | pass2:: 28 | "any" usebundle => _method_reporting_context_v4("Apache configuration", "Logrotate", "logrotate"); 29 | "any" usebundle => file_from_template_mustache("${sys.workdir}/inputs/rudder-service-apache/1.0/apache/apache-logrotate.mustache", "/etc/logrotate.d/rudder-apache"); 30 | } 31 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/apache/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common rudder_apache { 5 | vars: 6 | any:: 7 | "service_name" string => "apache2"; 8 | "group_name" string => "www"; 9 | redhat:: 10 | "service_name" string => "httpd"; 11 | "group_name" string => "apache"; 12 | debian:: 13 | "group_name" string => "www-data"; 14 | } 15 | 16 | bundle agent system_rudder_apache_configuration { 17 | vars: 18 | "trackingkey" string => "&TRACKINGKEY&"; 19 | "technique_name" string => "Rudder apache"; 20 | "https_port" string => "&HTTPS_POLICY_DISTRIBUTION_PORT&"; 21 | 22 | methods: 23 | # Force certificates and permissions 24 | "any" usebundle => apache_cert("${trackingkey}", "${technique_name}"); 25 | 26 | # Force allowed networks 27 | "any" usebundle => system_rudder_apache_networks_configuration; 28 | 29 | # Force webdav user/password 30 | "any" usebundle => system_rudder_apache_webdav_configuration("${trackingkey}", "${technique_name"); 31 | 32 | # Configure log rotation 33 | "any" usebundle => system_apache_logrotate; 34 | 35 | # Check that apache is running and enabled 36 | "any" usebundle => _method_reporting_context_v4("Apache service", "Started", "apache_started"); 37 | "any" usebundle => service_started("${rudder_apache.service_name}"); 38 | 39 | "any" usebundle => _method_reporting_context_v4("Apache service", "Enabled", "apache_enabled"); 40 | "any" usebundle => service_enabled("${rudder_apache.service_name}"); 41 | } 42 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/apache/nodescerts.pem.st: -------------------------------------------------------------------------------- 1 | &MANAGED_NODES_CERT_PEM: {cert | &cert& 2 | }& 3 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-apache/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure the apache components 3 | true 4 | false 5 | true 6 | 7 | 8 | 9 | 10 | false 11 | rudder-service-apache/1.0/apache/nodescerts.pem 12 | 13 | 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | 21 | 22 | true 23 | 24 | 25 | true 26 | 27 | 28 | false 29 | 30 | 31 | 32 | 33 | system_rudder_apache_configuration 34 | 35 | 36 | 37 | MANAGED_NODES_CERT_PEM 38 | HTTPS_POLICY_DISTRIBUTION_PORT 39 | 40 | 41 | 42 |
43 | 44 | Enabled 45 | Started 46 | 47 |
48 |
49 | 50 | Allowed networks permissions 51 | Allowed networks configuration 52 | Remote run permissions 53 | Remote run configuration 54 | Webdav configuration 55 | Webdav permissions 56 | Logrotate 57 | 58 |
59 |
60 | 61 | Permissions 62 | Apache certificate 63 | 64 |
65 |
66 |
67 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-postgresql/1.0/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common rudder_postgresql { 5 | vars: 6 | # sles 12, sp1 and sp2 don't have by default a systemd postgresql 7 | agent.!(sles_12_0|sles_12_1|sles_12_2):: 8 | "service_name" string => execresult("${paths.systemctl} --no-ask-password list-unit-files --type service | ${paths.awk} -F'.' '{print $1}' | ${paths.grep} -E \"^postgresql-?[0-9]*$\" | tail -n 1", "useshell"); 9 | agent.(sles_12_0|sles_12_1|sles_12_2):: 10 | "service_name" string => execresult("chkconfig 2>/dev/null | ${paths.awk} '{ print $1 }' | ${paths.grep} 'postgresql' | tail -n 1", "useshell"); 11 | 12 | agent:: 13 | "no" int => getfields("RUDDER_PSQL_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","password_getter"); 14 | "postgres_passwd" string => "${password_getter[2]}"; 15 | 16 | "db_url" string => "&RUDDER_REPORTS_DB_URL&"; 17 | "db_name" string => "&RUDDER_REPORTS_DB_NAME&"; 18 | "db_admin_name" string => "postgres"; 19 | "postgres_connection" slist => string_split(string_replace("${db_url}", "postgresql://", ""), "[@|:|/]", 5); 20 | 21 | # Define the where to send the reports messages 22 | "db_host" string => nth("postgres_connection", 1); 23 | "db_port" string => nth("postgres_connection", 2); 24 | } 25 | 26 | bundle agent system_rudder_postgresql_configuration { 27 | vars: 28 | any:: 29 | "trackingkey" string => "&TRACKINGKEY&"; 30 | "postgres_passwd" string => "${rudder_postgresql.postgres_passwd}"; 31 | "technique_name" string => "Rudder Postgresql"; 32 | 33 | methods: 34 | 35 | # Check that apache is running and enabled 36 | "any" usebundle => _method_reporting_context_v4("Postgresql service", "Started", "postgres_started"); 37 | "any" usebundle => service_started("${rudder_postgresql.service_name}"); 38 | 39 | "any" usebundle => _method_reporting_context_v4("Postgresql service", "Enabled", "postgres_enabled"); 40 | "any" usebundle => service_enabled("${rudder_postgresql.service_name}"); 41 | 42 | # Check pgpass and db credentials 43 | "any" usebundle => system_rudder_postgresql("${trackingkey}", "${technique_name}", "${postgres_passwd}"); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-postgresql/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure the postgresql Rudder database and service 3 | true 4 | false 5 | true 6 | 7 | 8 | 9 | system_rudder_postgresql_configuration 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | RUDDER_REPORTS_DB_URL 19 | RUDDER_REPORTS_DB_NAME 20 | 21 | 22 | 23 |
24 | 25 | Check pgpass file 26 | Postgresql credentials 27 | 28 |
29 |
30 | 31 | Started 32 | Enabled 33 | 34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/common/logrotate.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent system_relay_logrotate { 5 | files: 6 | "/etc/logrotate.d/rudder-relay" 7 | delete => tidy, 8 | comment => "Removing logrotate file from pre 8.x"; 9 | } 10 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/common/relayd.conf.tpl: -------------------------------------------------------------------------------- 1 | # Format is TOML 0.5 (https://github.com/toml-lang/toml/blob/v0.5.0/README.md) 2 | 3 | [general] 4 | 5 | nodes_list_file = "{{{vars.g.rudder_var}}}/lib/relay/nodeslist.json" 6 | {{#classes.root_server}} 7 | nodes_certs_file = "{{{vars.g.rudder_var}}}/lib/ssl/allnodescerts.pem" 8 | {{/classes.root_server}} 9 | {{^classes.root_server}} 10 | nodes_certs_file = "{{{vars.g.rudder_var}}}/lib/ssl/nodescerts.pem" 11 | {{/classes.root_server}} 12 | 13 | node_id = "{{{vars.g.uuid}}}" 14 | listen = "127.0.0.1:3030" 15 | 16 | # Use the number of CPUs 17 | #core_threads = "4" 18 | #blocking_threads = 100 19 | 20 | # Use cert pinning 21 | peer_authentication = "cert_pinning" 22 | 23 | # Use proper port 24 | https_port = {{{vars.system_rudder_relay_configuration.https_port}}} 25 | 26 | [processing.inventory] 27 | directory = "{{{vars.g.rudder_var}}}/inventories" 28 | {{#classes.root_server}} 29 | output = "disabled" 30 | {{/classes.root_server}} 31 | {{^classes.root_server}} 32 | output = "upstream" 33 | {{/classes.root_server}} 34 | 35 | [processing.inventory.catchup] 36 | frequency = 10 37 | limit = 50 38 | 39 | [processing.inventory.cleanup] 40 | frequency = "10min" 41 | retention = "1day" 42 | 43 | [processing.reporting] 44 | directory = "{{{vars.g.rudder_var}}}/reports" 45 | {{#classes.root_server}} 46 | output = "database" 47 | {{/classes.root_server}} 48 | {{^classes.root_server}} 49 | output = "upstream" 50 | {{/classes.root_server}} 51 | skip_event_types = [] 52 | 53 | [processing.reporting.catchup] 54 | frequency = 10 55 | limit = 0 56 | 57 | [processing.reporting.cleanup] 58 | frequency = "10min" 59 | retention = "1day" 60 | 61 | {{#classes.root_server}} 62 | [output.database] 63 | url = "{{{vars.system_rudder_relay_configuration.db_url}}}" 64 | password = "{{{vars.system_rudder_relay_configuration.db_password}}}" 65 | max_pool_size = 10 66 | {{/classes.root_server}} 67 | 68 | [output.upstream] 69 | # url in 6.X, host after 70 | {{#classes.cfengine_3_15}} 71 | url = "https://{{{vars.server_info.policy_server}}}" 72 | {{/classes.cfengine_3_15}} 73 | {{^classes.cfengine_3_15}} 74 | host = "{{{vars.server_info.policy_server}}}" 75 | {{/classes.cfengine_3_15}} 76 | user = "{{{vars.g.davuser}}}" 77 | password = "{{{vars.g.davpw}}}" 78 | {{#classes.rudder_relayd_disable_cert_pinning}} 79 | verify_certificates = false 80 | {{/classes.rudder_relayd_disable_cert_pinning}} 81 | 82 | [remote_run] 83 | command = "{{{vars.g.rudder_base}}}/bin/rudder" 84 | use_sudo = true 85 | 86 | [shared_files] 87 | path = "{{{vars.g.rudder_var}}}/shared-files/" 88 | 89 | [shared_folder] 90 | path = "{{{vars.g.shared_files}}}/" 91 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # Common variable for distribute policy system technique 5 | bundle common rudder_relayd { 6 | vars: 7 | "config_dir" string => "${g.rudder_base}/etc/relayd"; 8 | "config_file" string => "${config_dir}/main.conf"; 9 | "config_log_file" string => "${config_dir}/logging.conf"; 10 | "service_name" string => "rudder-relayd"; 11 | } 12 | 13 | bundle agent system_rudder_relay_configuration { 14 | vars: 15 | "technique_name" string => "Rudder relay"; 16 | "trackingkey" string => "&TRACKINGKEY&"; 17 | "relay_sync_method" string => "&RELAY_SYNC_METHOD&"; 18 | "relay_sync_promises" string => "&RELAY_SYNC_PROMISES&"; 19 | "relay_sync_sharedfiles" string => "&RELAY_SYNC_SHAREDFILES&"; 20 | "https_port" string => "&HTTPS_POLICY_DISTRIBUTION_PORT&"; 21 | 22 | root_server:: 23 | "db_url" string => "&RUDDER_REPORTS_DB_URL&"; 24 | # The value is empty on non-root servers 25 | "db_password" string => "&RUDDER_REPORTS_DB_PASSWORD&"; 26 | 27 | methods: 28 | # Only run this on relays (non-root) 29 | root_server:: 30 | "any" usebundle => rudder_relay_root_na("${trackingkey}", "${technique_name}"); 31 | policy_server.!root_server:: 32 | "any" usebundle => propagate_promises("${trackingkey}", "${technique_name}", "${relay_sync_method}", "${relay_sync_promises}", "${relay_sync_sharedfiles}"); 33 | !initial_promises:: 34 | "any" usebundle => system_rudder_relayd_configuration; 35 | } 36 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure the relay components 3 | true 4 | false 5 | true 6 | 7 | 8 | 9 | 10 | 11 | false 12 | rudder-service-relayd/1.0/relay/nodeslist.json 13 | 14 | 15 | 16 | 17 | 18 | true 19 | 20 | 21 | rudder-service-relayd/1.0/common/relayd.conf.tpl 22 | false 23 | 24 | 25 | true 26 | 27 | 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | system_rudder_relay_configuration 37 | 38 | 39 | 40 | SUB_NODES_NAME 41 | SUB_NODES_ID 42 | SUB_NODES_KEYHASH 43 | SUB_NODES_SERVER 44 | RELAY_SYNC_METHOD 45 | RELAY_SYNC_PROMISES 46 | RELAY_SYNC_SHAREDFILES 47 | RUDDER_REPORTS_DB_URL 48 | RUDDER_REPORTS_DB_PASSWORD 49 | HTTPS_POLICY_DISTRIBUTION_PORT 50 | 51 | 52 | 53 |
54 | 55 | Configuration permissions 56 | Configuration 57 | Enabled 58 | Started 59 | Policy-server certificate 60 | Root server certificate 61 | Root certificate permissions 62 | Policy server certificate permissions 63 | 64 |
65 |
66 |
67 |
68 | 69 | 70 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/relay/nodeslist.json.st: -------------------------------------------------------------------------------- 1 | { 2 | &SUB_NODES_NAME, SUB_NODES_ID, SUB_NODES_KEYHASH, SUB_NODES_SERVER: {host, uuid, key, server | 3 | "&uuid&": { 4 | "hostname": "&host&", 5 | "key-hash": "&key&", 6 | "policy-server": "&server&" 7 | } 8 | };separator=", 9 | " & 10 | } 11 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-relayd/1.0/root/rudderRelayRootNa.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent rudder_relay_root_na(trackingkey, technique_name) { 5 | methods: 6 | "any" usebundle => rudder_common_report("${technique_name}", "result_na", "${trackingkey}", "Synchronize resources", "None", "No need to synchronize resources on the root server"); 7 | "any" usebundle => rudder_common_report("${technique_name}", "result_na", "${trackingkey}", "Synchronize policies", "None", "No need to synchronize policies on the root server"); 8 | "any" usebundle => rudder_common_report("${technique_name}", "result_na", "${trackingkey}", "Synchronize files", "None", "No need to synchronize shared-files on the root server"); 9 | } 10 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-slapd/1.0/logrotate.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent system_slapd_logrotate { 5 | classes: 6 | "pass2" expression => "pass1"; 7 | "pass1" expression => "any"; 8 | "duration_configured" expression => isvariable("rudder_parameters.log_duration"); 9 | 10 | files: 11 | "/etc/logrotate.d/rudder-slapd" 12 | delete => tidy, 13 | comment => "Removing logrotate file from pre-8.x"; 14 | } 15 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-slapd/1.0/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common rudder_slapd { 5 | vars: 6 | "service_name" string => "rudder-slapd"; 7 | "user_name" string => "rudder-slapd"; 8 | "group_name" string => "rudder-slapd"; 9 | 10 | "config_file" string => "${g.rudder_base}/etc/openldap/slapd.conf"; 11 | } 12 | 13 | bundle agent system_rudder_slapd_configuration { 14 | vars: 15 | 16 | "no" int => getfields("RUDDER_OPENLDAP_BIND_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","password_getter"); 17 | "slapd_password" string => "${password_getter[2]}"; 18 | "technique_name" string => "Rudder slapd"; 19 | "trackingkey" string => "&TRACKINGKEY&"; 20 | 21 | "args" slist => { "${rudder_slapd.config_file}", "640", "root", "${rudder_slapd.group_name}" }; 22 | "report_param" string => join("_", args); 23 | "permission_class" string => canonify("permissions_${report_param}"); 24 | 25 | classes: 26 | "rudder_server_system_restart_slapd" expression => "rudder_slapd_ldap_password_repaired|${permission_class}_repaired", 27 | scope => "namespace"; 28 | "rudder_server_system_restart_jetty" expression => "rudder_slapd_ldap_password_repaired|${permission_class}_repaired", 29 | scope => "namespace"; 30 | 31 | files: 32 | "${rudder_slapd.config_file}" 33 | edit_line => set_rudder_slapd_password("${slapd_password}"), 34 | classes => classes_generic("rudder_slapd_ldap_password"), 35 | comment => "Verifying the Rudder LDAP file password and user"; 36 | 37 | methods: 38 | # Log rotation 39 | "any" usebundle => system_slapd_logrotate; 40 | # Service configuration 41 | "any" usebundle => _method_reporting_context_v4("Rudder slapd configuration", "Check Rudder ldap permissions", "rudder_ldap_permissions"); 42 | "any" usebundle => permissions("${rudder_slapd.config_file}", "640", "root", "${rudder_slapd.group_name}"); 43 | !is_rudder_bootstrap:: 44 | "any" usebundle => _method_reporting_context_v4("Rudder slapd service", "Started", "slapd_started"); 45 | "any" usebundle => service_started("${rudder_slapd.service_name}"); 46 | any:: 47 | "any" usebundle => _method_reporting_context_v4("Rudder slapd service", "Enabled", "slapd_enabled"); 48 | "any" usebundle => service_enabled("${rudder_slapd.service_name}"); 49 | 50 | "any" usebundle => rudder_common_reports_generic("${technique_name}", "rudder_slapd_ldap_password", "${trackingkey}", "Rudder slapd configuration", "Check Rudder ldap password", "OpenLDAP configuration file (rootdn password)"); 51 | } 52 | 53 | 54 | bundle edit_line set_rudder_slapd_password(password) { 55 | delete_lines: 56 | "rootpw.*"; 57 | 58 | insert_lines: 59 | "rootpw ${password}" location => after("^rootdn.*"); 60 | } 61 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-slapd/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure the rudder-slapd service 3 | true 4 | false 5 | true 6 | 7 | 8 | system_rudder_slapd_configuration 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | true 18 | 19 | 20 | 21 | 22 |
23 | 24 | Started 25 | Enabled 26 | 27 |
28 |
29 | 30 | Check Rudder ldap password 31 | Check Rudder ldap permissions 32 | 33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/alive-check.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent system_rudder_jetty_alive_check { 5 | vars: 6 | "site_to_check" string => "http://localhost:8080/rudder/api/status"; 7 | 8 | "api_check_cmd" string => "${g.rudder_curl} --proxy '' --max-time 240 -s ${site_to_check} |/bin/grep -q OK"; 9 | "condition_prefix" string => "rudder_system_api_status"; 10 | "persistent_condition" string => "rudder_system_api_status_down"; 11 | 12 | classes: 13 | "pass3" expression => "pass2"; 14 | "pass2" expression => "pass1"; 15 | "pass1" expression => "any"; 16 | 17 | pass3:: 18 | # Restart rudder-jetty if the api call failed two times in two agent run intervals. 19 | "rudder_server_system_restart_jetty" expression => "${condition_prefix}_false.${persistent_condition}", 20 | scope => "namespace"; 21 | 22 | "${persistent_condition}" expression => "${condition_prefix}_false", 23 | persistence => "${g.agent_run_interval}"; 24 | 25 | methods: 26 | "any" usebundle => _method_reporting_context_v4("Rudder-jetty service", "API status", "api_status"); 27 | "any" usebundle => condition_from_command("${condition_prefix}", "${api_check_cmd}", "0", "1,255"); 28 | } 29 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/bootstrapRudderServer.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # Used only for bootstrapping Rudder server 5 | bundle agent bootstrap_server_rudder { 6 | vars: 7 | # we need a var here, otherwise the bundle name will be checked, and it fails 8 | # with external postgresql 9 | "postgres_bundle" string => "system_rudder_postgresql_configuration"; 10 | 11 | classes: 12 | "is_rudder_bootstrap" expression => "any", 13 | scope => "namespace"; 14 | 15 | methods: 16 | 17 | "system_rudder_postgresql_configuration" usebundle => "${postgres_bundle}"; 18 | "system_rudder_slapd_configuration" usebundle => "system_rudder_slapd_configuration"; 19 | "system_rudder_webapp" usebundle => "system_rudder_webapp"; 20 | "system_rudder_relay_configuration" usebundle => "system_rudder_relay_configuration"; 21 | "system_reload_rudder_services" usebundle => "system_reload_rudder_services"; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/compress-webapp-log.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2014 Normation SAS 3 | # SPDX-FileCopyrightText: 2016 Janos Mattyasovszky 4 | 5 | bundle agent system_compress_webapp_log 6 | { 7 | vars: 8 | # compress files older than 2 days 9 | "log_compress_delay" int => "2"; 10 | 11 | # compress file.log and file.log.1 12 | "logs_pattern" slist => { ".*\.log", ".*\.log\.\d+" }; 13 | 14 | files: 15 | "${g.rudder_log}/webapp" 16 | file_select => date_pattern("${log_compress_delay}", "@{logs_pattern}"), 17 | depth_search => recurse("0"), 18 | transformer => "${g.gzip} -fq \"${this.promiser}\""; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/integrity-check.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent system_root_integrity_check(trackingkey, technique_name) 5 | { 6 | vars: 7 | "key_destination" string => "${sys.workdir}/ppkeys/root-${sys.key_digest}.pub"; 8 | "component" string => "Check configuration-repository"; 9 | "component_key1" string => "Configuration-repository exists"; 10 | "component_key2" string => "Check configuration-repository GIT lock"; 11 | 12 | classes: 13 | any:: 14 | "pass3" expression => "pass2"; 15 | "pass2" expression => "pass1"; 16 | "pass1" expression => "any"; 17 | 18 | files: 19 | "${g.rudder_configuration_repository}" 20 | create => "true", 21 | action => WarnOnly, 22 | classes => if_else("rudder_integrity_ok", "rudder_integrity_failed"); 23 | 24 | "${g.rudder_configuration_repository}/.git/index.lock" 25 | delete => tidy, 26 | file_select => ncf_minutes_old("5"), 27 | classes => classes_generic("rudder_git_lock"), 28 | comment => "Delete the git locking file in the configuration-repository if older than 5 minutes"; 29 | 30 | methods: 31 | "any" usebundle => _method_reporting_context_v4("${component}", "None", "server_key_symklink"); 32 | "link the key" usebundle => disable_reporting; 33 | "link the key" usebundle => file_create_symlink("${sys.workdir}/ppkeys/localhost.pub", "${key_destination}"), 34 | comment => "Creating a link of the server key to itself to allow auto-copy"; 35 | "link the key" usebundle => enable_reporting; 36 | 37 | pass3.rudder_integrity_ok.!rudder_integrity_failed:: 38 | "any" usebundle => rudder_common_report("${technique_name}", "result_success", "${trackingkey}", "${component}", "${component_key1}", "The ${g.rudder_configuration_repository} directory is present"); 39 | 40 | pass3.(!rudder_integrity_ok|rudder_integrity_failed):: 41 | "any" usebundle => rudder_common_report("${technique_name}", "result_error", "${trackingkey}", "${component}", "${component_key1}", "The required ${g.rudder_configuration_repository} directory is absent, central server will not operate properly"); 42 | 43 | pass3.(!rudder_git_lock_repaired.!rudder_git_lock_failed):: 44 | "any" usebundle => rudder_common_report("${technique_name}", "result_success", "${trackingkey}", "${component}", "${component_key2}", "The ${g.rudder_configuration_repository} git lock file is not present or not older than 5 minutes"); 45 | 46 | pass3.(rudder_git_lock_repaired.!rudder_git_lock_failed):: 47 | "any" usebundle => rudder_common_report("${technique_name}", "result_repaired", "${trackingkey}", "${component}", "${component_key2}", "The ${g.rudder_configuration_repository} git lock file was older than 5 minutes and has been deleted"); 48 | 49 | pass3.rudder_git_lock_failed:: 50 | "any" usebundle => rudder_common_report("${technique_name}", "result_error", "${trackingkey}", "${component}", "${component_key2}", "The ${g.rudder_configuration_repository} git lock file is older than 5 minutes and could not be deleted, central server will not operate properly"); 51 | } 52 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common rudder_webapp { 5 | vars: 6 | "service_name" string => "rudder-jetty"; 7 | } 8 | 9 | bundle agent system_rudder_webapp { 10 | vars: 11 | any:: 12 | "trackingkey" string => "&TRACKINGKEY&"; 13 | "technique_name" string => "Rudder Webapp"; 14 | 15 | methods: 16 | # Generate ncf hash file 17 | "any" usebundle => update_ncf_hash; 18 | # Check pgpass and db credentials 19 | "any" usebundle => system_compress_webapp_log; 20 | "any" usebundle => system_root_integrity_check("${trackingkey}", "${technique_name}"); 21 | "any" usebundle => system_rudder_jetty_alive_check; 22 | "any" usebundle => system_rudder_webapp_properties; 23 | 24 | # Check that rudder-jetty is running and enabled 25 | !is_rudder_bootstrap:: 26 | "any" usebundle => _method_reporting_context_v4("Rudder-jetty service", "Started", "jetty_started"); 27 | "any" usebundle => service_started("${rudder_webapp.service_name}"); 28 | any:: 29 | "any" usebundle => _method_reporting_context_v4("Rudder-jetty service", "Enabled", "jetty_enabled"); 30 | "any" usebundle => service_enabled("${rudder_webapp.service_name}"); 31 | } 32 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure the Rudder webapp 3 | false 4 | true 5 | true 6 | 7 | 8 | 9 | system_rudder_webapp 10 | 11 | 12 | 13 | 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | 21 | 22 | true 23 | 24 | 25 | true 26 | 27 | 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | Enabled 40 | Started 41 | API status 42 | 43 |
44 |
45 | 46 | Configuration-repository exists 47 | Check configuration-repository GIT lock 48 | 49 |
50 |
51 | 52 | postgres password 53 | ldap password 54 | webdav password 55 | rudder-passwords.conf permissions 56 | rudder-web.properties permissions 57 | rudder-users.xml permissions 58 | 59 |
60 |
61 |
62 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/password-check.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle agent system_rudder_webapp_properties { 5 | vars: 6 | "password_file" string => "${g.rudder_base}/etc/rudder-passwords.conf"; 7 | "properties_file" string => "${g.rudder_base}/etc/rudder-web.properties"; 8 | "c_properties_file" string => canonify("${properties_file}"); 9 | "user_file" string => "${g.rudder_base}/etc/rudder-users.xml"; 10 | 11 | "secure_files" slist => { "${password_file}", "${properties_file}", "${user_file}" }; 12 | 13 | "pwd1" int => getfields("RUDDER_PSQL_PASSWORD:.*","${password_file}",":","psql_password"); 14 | "pwd2" int => getfields("RUDDER_OPENLDAP_BIND_PASSWORD:.*","${password_file}",":","ldap_password"); 15 | "pwd3" int => getfields("RUDDER_WEBDAV_PASSWORD:.*","${password_file}",":","dav_password"); 16 | 17 | classes: 18 | # if configuration file has been updated, we need to restart rudder-jetty 19 | "rudder_server_system_restart_jetty" expression => "file_key_value_present_${c_properties_file}_repaired", 20 | scope => "namespace"; 21 | 22 | methods: 23 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "rudder-passwords.conf permissions", "rudder_password_permissions"); 24 | "any" usebundle => permissions("${password_file}", "600", "root", "0"); 25 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "rudder-web.properties permissions", "rudder_web_properties_permissions"); 26 | "any" usebundle => permissions("${properties_file}", "600", "root", "0"); 27 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "rudder-users.xml permissions", "rudder_users_permissions"); 28 | "any" usebundle => permissions("${user_file}", "600", "root", "0"); 29 | 30 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "postgres password", "rudder_postgres_password"); 31 | "any" usebundle => file_key_value_present("${properties_file}", "rudder.jdbc.password", "${psql_password[2]}", "="); 32 | 33 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "ldap password", "rudder_ldap_password"); 34 | "any" usebundle => file_key_value_present("${properties_file}", "ldap.authpw", "${ldap_password[2]}", "="); 35 | 36 | "any" usebundle => _method_reporting_context_v4("Check webapp configuration", "webdav password", "rudder_webdav_password"); 37 | "any" usebundle => file_key_value_present("${properties_file}", "rudder.webdav.password", "${dav_password[2]}", "="); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /techniques/system/rudder-service-webapp/1.0/updateNcfHash.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # Update the ncf hash 5 | bundle agent update_ncf_hash 6 | { 7 | vars: 8 | agent:: 9 | "ncf_common_sha_sum" string => execresult("${paths.path[find]} ${g.rudder_ncf_origin_common} -not -name ${g.rudder_ncf_hash_file} -type f -print0 | ${paths.path[sort]} -z | /usr/bin/xargs -0 /usr/bin/sha1sum | /usr/bin/sha1sum", "useshell"); 10 | "ncf_local_sha_sum" string => execresult("${paths.path[find]} ${g.rudder_ncf_origin_local} -not -name ${g.rudder_ncf_hash_file} -type f -print0 | ${paths.path[sort]} -z | /usr/bin/xargs -0 /usr/bin/sha1sum | /usr/bin/sha1sum", "useshell"); 11 | 12 | files: 13 | # each run, update the hash files of ncf 14 | # these hashes are used by node to know if they should update their copy of ncf 15 | any:: 16 | "${g.rudder_ncf_origin_common_hash}" 17 | create => "true", 18 | edit_defaults => empty, 19 | edit_line => insert_lines("${ncf_common_sha_sum}"), 20 | perms => mog("660", "root", "rudder"), 21 | comment => "Update the hash of ncf common"; 22 | 23 | "${g.rudder_ncf_origin_local_hash}" 24 | create => "true", 25 | edit_defaults => empty, 26 | edit_line => insert_lines("${ncf_local_sha_sum}"), 27 | perms => mog("660", "root", "rudder"), 28 | comment => "Update the hash of ncf local"; 29 | } 30 | -------------------------------------------------------------------------------- /techniques/system/server-common/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configure generic feature for all Rudder policy servers 3 | true 4 | false 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | true 13 | 14 | 15 | 16 | 17 | system_reload_rudder_services 18 | 19 | 20 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /techniques/system/server-common/1.0/rudder_syslog.cf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common rudder_syslog { 5 | vars: 6 | any:: 7 | "user_name" string => "root"; 8 | "group_name" string => "root"; 9 | "file_mode" string => "640"; 10 | 11 | debian:: 12 | "group_name" string => "adm"; 13 | } 14 | -------------------------------------------------------------------------------- /techniques/systemSettings/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | System settings 4 | This category contains Techniques to configure the basic components of a system: name resolution, time synchronization, remote access, networking... 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Miscellaneous 4 | This sub-category contains various Techniques to configure system settings. 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/genericCommandVariableDefinition/3.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/genericCommandVariableDefinition/3.0/genericCommandVariableDefinition.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | bundle common generic_cmd_var_def { 5 | 6 | vars: 7 | agent:: 8 | &GENERIC_COMMAND_VARIABLE_NAME, GENERIC_COMMAND_VARIABLE_BINARY, GENERIC_COMMAND_VARIABLE_SHELL:{name, binary, shell |"&name&" string => execresult("&binary&", "&shell&"); 9 | }& 10 | 11 | } 12 | 13 | bundle agent generic_cmd_var_def_report { 14 | vars: 15 | &TRACKINGKEY:{directiveId |"generic_command_name_uuid[&i&]" string => "&directiveId&"; 16 | }& 17 | &GENERIC_COMMAND_VARIABLE_NAME:{name |"generic_cmd_variable_name[&i&]" string => "&name&"; 18 | }& 19 | 20 | "generic_cmd_variable_name_index" slist => getindices("generic_command_name_uuid"); 21 | 22 | classes: 23 | any:: 24 | "pass3" expression => "pass2"; 25 | "pass2" expression => "pass1"; 26 | "pass1" expression => "any"; 27 | 28 | methods: 29 | 30 | pass3:: 31 | 32 | "any" usebundle => rudder_common_report_index("genericCommandVariableDefinition", "result_success", "${generic_command_name_uuid[${generic_cmd_variable_name_index}]}", "Variable command definition", "${generic_cmd_variable_name[${generic_cmd_variable_name_index}]}", "A generic command variable definition is set for variable ${generic_cmd_variable_name[${generic_cmd_variable_name_index}]}", "${generic_cmd_variable_name_index}"); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/genericCommandVariableDefinition/3.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Defines a variable from the output of a command. Its value can be used in other Directive parameters with the following syntax: `${generic_cmd_var_def.variablename}` 3 | This technique version is not maintained anymore, it will no longer be available in the next version of Rudder. 4 | true 5 | 6 | 7 | generic_cmd_var_def_report 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | GENERIC_COMMAND_VARIABLE_NAME 16 | 17 | 18 | 19 | 20 |
21 | 22 | GENERIC_COMMAND_VARIABLE_NAME 23 | Variable name 24 | 25 | Its value can be used in other Directive parameters with the following syntax: ${generic_cmd_var_def.variablename}. 26 | 27 | string 28 | 29 | 30 | 31 | 32 | GENERIC_COMMAND_VARIABLE_BINARY 33 | Command(s) to run 34 | 35 | If using system shell (see below), be careful, the absolute path to the binary must be specified here. Example: /bin/uname instead of uname. 36 | If not using system shell (see below), this is a list of shell-compatible statements to be executed. Multiple commands may be specified on separate lines. 37 | 38 | textarea 39 | 40 | 41 | 42 |
43 | 44 | GENERIC_COMMAND_VARIABLE_SHELL 45 | Use system shell 46 | 47 | Use of a shell has both resource and security consequences. A shell consumes an extra process and inherits environment variables, 48 | reads commands from files and performs other actions beyond the control of the agent. 49 | If one does not need shell functionality such as piping through multiple commands then it is best to manage without it. 50 | 51 | useshell 52 | 53 | 54 | 55 | noshell 56 | 57 | 58 | 59 | useshell 60 | 61 | 62 |
63 | 64 |
65 |
66 | 67 |
68 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/partitionSizeMonitoring/3.1/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Nicolas Charles Tue Dec 12 11:49:13 2017 8 | * Version 3.1 9 | ** Convert to multiversionned technique 10 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/partitionSizeMonitoring/3.1/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Execute command(s) when partition free space gets under desired threshold 4 | This technique version is not maintained anymore, it will no longer be available in the next version of Rudder. 5 | 6 | true 7 | separated 8 | 9 | monitor_partition_size_RudderUniqueID 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | PARTITION_SIZE_MONITORING_PATH 18 | 19 | 20 | 21 |
22 |
23 | 24 | PARTITION_SIZE_MONITORING_PATH 25 | Partition mounted path 26 | Where is your partition mounted. 27 | 28 | 29 | PARTITION_SIZE_MONITORING_FREE_SIZE 30 | Free size threshold 31 | How much free space before triggering command execution (in percent or in absolute space value). Allowed input range: [0-9]+[MBkKgGmb%] 32 | 33 |
34 |
35 | 36 | PARTITION_SIZE_MONITORING_CMD_EXEC_REPAIRED_RUN 37 | Enable post-modification hook 38 | Run the command(s) below if the threshold is met 39 | 40 | boolean 41 | false 42 | 43 | 44 | 45 | PARTITION_SIZE_MONITORING_CMD_EXEC_REPAIRED_COMMAND 46 | Command(s) to run 47 | List of shell-compatible statements to be executed. Multiple commands may be specified on separate lines. 48 | 49 | textarea 50 | true 51 | 52 | 53 |
54 |
55 |
56 |
57 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/rudderSNMP/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Configuration of the SNMP service and rudder agent monitoring. 5 | 6 | Snmpd will be installed if needed, and the required configuration will be appended to `/etc/snmp/snmpd.conf`, without destroying any existing user config. 7 | 8 | This technique version is not maintained anymore, it will no longer be available in the next version of Rudder. 9 | 10 | rudderSNMP 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /techniques/systemSettings/misc/rudderSNMP/1.0/rudder_health.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #This is the SNMP OID for the rudder agent health 4 | echo 1.3.6.1.4.1.35061.2.3.1 5 | echo string 6 | rudder agent health -n 7 | exit 0 8 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Networking 4 | This sub-category contains Techniques to configure networking on a system (DNS, routing, interfaces...) 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/dnsConfiguration/3.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/firewall/1.0/changelog: -------------------------------------------------------------------------------- 1 | -- Alexis Mousset Mon, 25 May 2020 17:19:00 +0100 2 | * Version 1.0 3 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/firewall/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | Configures a simple firewall using nftables 3 | 4 | false 5 | separated 6 | 7 | 8 | rudder_firewall 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 | 22 | FIREWALL_IMPL 23 | Firewall to use 24 | 25 | 26 | nftables 27 | 28 | 29 | nftables 30 | 31 | 32 | 33 | FIREWALL_CONF 34 | Firewall configuration 35 | Output of "iptables-save" or "nft list ruleset". It will be templated as mustache. 36 | 37 | textarea 38 | true 39 | 40 | 41 |
42 |
43 |
44 | 45 | FIREWALL_POST_HOOK_COMMAND 46 | Command to run after changes the firewall configuration 47 | 48 | textarea 49 | true 50 | 51 | 52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/hostsConfiguration/2.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 2 | * Version 2.0 3 | ** Use rudder_common_report instead of reports: 4 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/hostsConfiguration/2.0/hostsConfiguration.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2011 Normation SAS 3 | 4 | # 5 | # NOTE : I permitted the creation of the hosts file if absent, but on a purely 6 | # functional side, its absence means a severe breakage of your IP stack. Be 7 | # aware of this if a file creation is reported ! 8 | # 9 | 10 | bundle agent check_hosts_configuration 11 | { 12 | 13 | vars: 14 | 15 | &HOSTS_HOST:{host |"hosts_host[&i&]" string => "&host&"; 16 | }& 17 | 18 | &HOSTS_IP:{ip |"hosts_ip[&i&]" string => "&ip&"; 19 | }& 20 | 21 | "hosts_base_template" string => "&HOSTS_BASE_TEMPLATE&"; 22 | 23 | classes: 24 | any:: 25 | "pass3" expression => "pass2"; 26 | "pass2" expression => "pass1"; 27 | "pass1" expression => "any"; 28 | 29 | files: 30 | 31 | "/etc/hosts" 32 | 33 | create => "true", 34 | perms => m("644"), 35 | &if (HOSTS_ENFORCE)& 36 | edit_defaults => empty_backup, 37 | &else& 38 | edit_defaults => noempty_backup, 39 | &endif& 40 | 41 | edit_line => set_hosts_values("check_hosts_configuration.hosts_host", "check_hosts_configuration.hosts_ip", "${hosts_base_template}"), 42 | classes => kept_if_else("hosts_edition_kept", "hosts_edition_done", "hosts_edition_failed"); 43 | 44 | methods: 45 | 46 | pass3.cfengine:: 47 | &if (HOSTS_ENFORCE)& 48 | "any" usebundle => rudder_common_report("hostsConfiguration", "log_debug", "&TRACKINGKEY&", "hostsConfiguration", "None", "Hosts file content enforcement requested"); 49 | &endif& 50 | 51 | pass3.hosts_edition_done:: 52 | "any" usebundle => rudder_common_report("hostsConfiguration", "result_repaired", "&TRACKINGKEY&", "hostsConfiguration", "None", "Hosts file was updated"); 53 | 54 | pass3.(hosts_edition_kept.!hosts_edition_done):: 55 | "any" usebundle => rudder_common_report("hostsConfiguration", "result_success", "&TRACKINGKEY&", "hostsConfiguration", "None", "Hosts file already OK"); 56 | 57 | pass3.hosts_edition_failed:: 58 | "any" usebundle => rudder_common_report("hostsConfiguration", "result_error", "&TRACKINGKEY&", "hostsConfiguration", "None", "Hosts file could not be edited"); 59 | 60 | } 61 | 62 | bundle edit_line set_hosts_values(hosts, ips, base_tmpl) 63 | { 64 | 65 | vars: 66 | 67 | "hosts_index" slist => getindices("${hosts}"); 68 | 69 | delete_lines: 70 | 71 | "${${ips}[${hosts_index}]}.*"; 72 | 73 | insert_lines: 74 | 75 | &if (HOSTS_ENFORCE)& 76 | 77 | "${base_tmpl}" 78 | insert_type => "preserve_block"; 79 | 80 | &endif& 81 | 82 | "${${ips}[${hosts_index}]} ${${hosts}[${hosts_index}]}"; 83 | 84 | } 85 | 86 | -------------------------------------------------------------------------------- /techniques/systemSettings/networking/hostsConfiguration/2.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique configures the machine hosts file. Be careful: The IP address is used as the key reference for any edition and if multiple hosts have been specified with the same IP in the hosts file, the matching entry defined here will take precedence and erase all the other occurrences of the same IP 4 | 5 | check_hosts_configuration 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | HOSTS_ENFORCE 16 | Replace the hosts file content 17 | If enabled, only the entries and the template defined below will be inserted in the hosts file. Every other line will be deleted 18 | 19 | boolean 20 | false 21 | 22 | 23 | 24 | HOSTS_BASE_TEMPLATE 25 | Initial content in case of replacement 26 | Initial content that will be used only in case of replacement. Other entries will be appended. You SHOULD include at least the default TCP/IP entries (like localhost) or you MAY break your TCP/IP stack ! 27 | 28 | textarea 29 | 127.0.0.1 localhost 30 | 127.0.1.1 ${sys.host} 31 | ## 32 | # The following lines are desirable for IPv6 capable hosts 33 | ::1 localhost ip6-localhost ip6-loopback 34 | fe00::0 ip6-localnet 35 | ff00::0 ip6-mcastprefix 36 | ff02::1 ip6-allnodes 37 | ff02::2 ip6-allrouters 38 | ff02::3 ip6-allhosts 39 | ### 40 | ## Here follows all the rudder defined hosts : 41 | 42 | 43 |
44 | 45 |
46 | 47 | HOSTS_IP 48 | IP address 49 | 50 | string 51 | ^[0-9a-f.:]+$ 52 | 53 | 54 | 55 | HOSTS_HOST 56 | Hostname 57 | 58 |
59 |
60 | 61 |
62 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Process 4 | This sub-category contains Techniques to enforce some system process policies 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas Charles Tue Dec 12 11:47:37 2017 2 | * Version 1.1 3 | ** Convert to multiversionned technique 4 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Check and enforce the state of services 4 | 5 | true 6 | separated 7 | 8 | services_RudderUniqueID 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | SERVICES_TECHNIQUE_NAME 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 | SERVICES_TECHNIQUE_NAME 25 | Service name (as seen in systemctl, chkconfig, etc.) 26 | 27 | 28 | 29 | SERVICES_TECHNIQUE_STATUS 30 | Status 31 | 32 | 33 | running 34 | 35 | 36 | 37 | stopped 38 | 39 | 40 | 41 | ignore 42 | 43 | 44 | 45 | ignore 46 | 47 | 48 | 49 | 50 | SERVICES_TECHNIQUE_BOOT 51 | Boot status 52 | 53 | 54 | enabled 55 | 56 | 57 | 58 | disabled 59 | 60 | 61 | 62 | ignore 63 | 64 | 65 | ignore 66 | 67 | 68 | 69 | 70 | SERVICES_TECHNIQUE_POSTHOOK 71 | Command to run in case of repaired result 72 | 73 | true 74 | 75 | 76 | 77 | SERVICES_TECHNIQUE_PERSISTENT 78 | Retry the posthook until success 79 | 80 | 81 | true 82 | 83 | 84 | 85 | false 86 | 87 | 88 | false 89 | false 90 | 91 | 92 |
93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/tests/test_service.cf: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ncf -f 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # SPDX-FileCopyrightText: 2021 Normation SAS 4 | 5 | bundle agent init { 6 | methods: 7 | "any" usebundle => file_remove("/tmp/test_output.log"); 8 | #Only for debian machine 9 | "any" usebundle => package_present("ntp", "latest", "default", "apt"); 10 | "any" usebundle => command_execution("service ntp start"), 11 | ifvarclass => "package_present_ntp_ok"; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/tests/test_service.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "Services technique", 3 | "enabled": true, 4 | "longDescription": "", 5 | "parameters": { 6 | "section": { 7 | "name": "sections", 8 | "sections": [ 9 | { 10 | "section": { 11 | "name": "Services boot status" 12 | } 13 | }, 14 | { 15 | "section": { 16 | "name": "Services posthook" 17 | } 18 | }, 19 | { 20 | "section": { 21 | "name": "Services status", 22 | "vars": [ 23 | { 24 | "var": { 25 | "name": "SERVICES_TECHNIQUE_BOOT", 26 | "value": "true" 27 | } 28 | }, 29 | { 30 | "var": { 31 | "name": "SERVICES_TECHNIQUE_NAME", 32 | "value": "ntp" 33 | } 34 | }, 35 | { 36 | "var": { 37 | "name": "SERVICES_TECHNIQUE_PERSISTENT", 38 | "value": "true" 39 | } 40 | }, 41 | { 42 | "var": { 43 | "name": "SERVICES_TECHNIQUE_POSTHOOK", 44 | "value": "/bin/true" 45 | } 46 | }, 47 | { 48 | "var": { 49 | "name": "SERVICES_TECHNIQUE_STATUS", 50 | "value": "false" 51 | } 52 | } 53 | ] 54 | } 55 | }, 56 | { 57 | "section": { 58 | "name": "Services status", 59 | "vars": [ 60 | { 61 | "var": { 62 | "name": "SERVICES_TECHNIQUE_BOOT", 63 | "value": "true" 64 | } 65 | }, 66 | { 67 | "var": { 68 | "name": "SERVICES_TECHNIQUE_NAME", 69 | "value": "ssh" 70 | } 71 | }, 72 | { 73 | "var": { 74 | "name": "SERVICES_TECHNIQUE_PERSISTENT", 75 | "value": "false" 76 | } 77 | }, 78 | { 79 | "var": { 80 | "name": "SERVICES_TECHNIQUE_POSTHOOK", 81 | "value": "" 82 | } 83 | }, 84 | { 85 | "var": { 86 | "name": "SERVICES_TECHNIQUE_STATUS", 87 | "value": "true" 88 | } 89 | } 90 | ] 91 | } 92 | } 93 | ] 94 | } 95 | }, 96 | "shortDescription": "", 97 | "techniqueName": "services", 98 | "techniqueVersion": "1.0" 99 | } 100 | 101 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/tests/test_service.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "inits": ["test_service.cf"], 3 | "directives": ["test_service.json", "test_service_cron.json"], 4 | "checks": ["test_service.rb"], 5 | "sharedFiles": [], 6 | "compliance": 100 7 | }] 8 | 9 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/tests/test_service.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe service('ntp') do 4 | it { should be_enabled } 5 | it { should_not be_running } 6 | end 7 | 8 | describe service('ssh') do 9 | it { should be_enabled } 10 | it { should be_running } 11 | end 12 | 13 | describe service('cron') do 14 | it { should_not be_enabled } 15 | it { should be_running } 16 | end 17 | 18 | describe command('/bin/cat /tmp/test_output.log') do 19 | its(:stdout) { should match /[\s\S]*?The service status \"stopped\" for ntp was repaired[\s\S]*?The command \/bin\/true from postHook execution was repaired/ } 20 | end 21 | 22 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/services/1.1/tests/test_service_cron.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "cron Services technique", 3 | "enabled": true, 4 | "longDescription": "", 5 | "parameters": { 6 | "section": { 7 | "name": "sections", 8 | "sections": [ 9 | { 10 | "section": { 11 | "name": "Services boot status" 12 | } 13 | }, 14 | { 15 | "section": { 16 | "name": "Services posthook" 17 | } 18 | }, 19 | { 20 | "section": { 21 | "name": "Services status", 22 | "vars": [ 23 | { 24 | "var": { 25 | "name": "SERVICES_TECHNIQUE_BOOT", 26 | "value": "ignore" 27 | } 28 | }, 29 | { 30 | "var": { 31 | "name": "SERVICES_TECHNIQUE_NAME", 32 | "value": "cron" 33 | } 34 | }, 35 | { 36 | "var": { 37 | "name": "SERVICES_TECHNIQUE_PERSISTENT", 38 | "value": "false" 39 | } 40 | }, 41 | { 42 | "var": { 43 | "name": "SERVICES_TECHNIQUE_POSTHOOK", 44 | "value": "" 45 | } 46 | }, 47 | { 48 | "var": { 49 | "name": "SERVICES_TECHNIQUE_STATUS", 50 | "value": "ignore" 51 | } 52 | } 53 | ] 54 | } 55 | } 56 | ] 57 | } 58 | }, 59 | "shortDescription": "", 60 | "techniqueName": "services", 61 | "techniqueVersion": "1.0" 62 | } 63 | 64 | -------------------------------------------------------------------------------- /techniques/systemSettings/process/servicesManagement/3.0/changelog: -------------------------------------------------------------------------------- 1 | Version 1.2: 2 | 3 | * Fixed support for CentOS/RHEL 4 | * Reworked variables and commands promises to be DRY-er 5 | 6 | -- Jonathan CLARKE Fri, 31 Aug 2012 18:19:00 +0100 7 | 8 | Version 1.1: 9 | 10 | * Added a correct Debian support 11 | 12 | -- Matthieu CERDA Thu, 26 Jan 2012 16:22:00 +0100 13 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 14 | * Version 2.0 15 | ** Rewrite with normal ordering and {} 16 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 17 | * Version 3.0 18 | ** Use rudder_common_report instead of reports: 19 | ** Add support for Windows services 20 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Remote access 4 | This sub-category contains Techniques to configure remote access to a system (SSH, RDP, VNC, ...) 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshConfiguration/5.0/bodies.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | # 5 | # Configure the port numbers/listen addresses in the OpenSSH configuration file 6 | # The first argument is the name of parameter in the config file, second is the values (either a string or a slist) 7 | # 8 | bundle edit_line rudder_openssh_server_parameters_configuration(parameter_name, values) 9 | { 10 | vars: 11 | "entries" slist => maplist("${parameter_name} ${this}", "values"); 12 | 13 | delete_lines: 14 | "${parameter_name}.*" 15 | delete_select => ncf_delete_if_not_in_list("@{this.entries}"); 16 | 17 | insert_lines: 18 | "${entries}"; 19 | } 20 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshConfiguration/5.0/changelog: -------------------------------------------------------------------------------- 1 | -- Jonathan CLARKE Wed Feb 22 18:42:29 2012 +0100 2 | * Version 1.0 3 | ** Initial version 4 | -- Matthieu CERDA Thu Dec 20 17:46:24 2012 +0100 5 | * Version 2.0 6 | ** Converted the OpenSSH server Technique to the new reporting format 7 | -- Nicolas Charles Thu Feb 14 16:01:25 2013 +0100 8 | * Version 3.0 9 | ** Improves the uses of conventions in the ssh technique 10 | ** Remove unused parameters 11 | -- Matthieu CERDA Wed Sep 10 15:39:37 2014 +0200 12 | * Version 4.0 13 | ** Support AIX 14 | ** Support systemd 15 | -- Nicolas CHARLES Thu Jul 09 10:01:37 2015 +0200 16 | * Version 5.0 17 | ** Add possibility to configure Listen Addresses 18 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshConfiguration/5.0/installation.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | ############################################################### 5 | # Installs SSH, and checks whether it is started on boot or not. 6 | ############################################################### 7 | 8 | bundle agent rudder_openssh_server_installation(class_prefix, service_name, params) 9 | { 10 | vars: 11 | linux.!SuSE:: 12 | "rudder_openssh_server_package_name" 13 | string => "openssh-server"; 14 | SuSE:: 15 | "rudder_openssh_server_package_name" 16 | string => "openssh"; 17 | 18 | any:: 19 | "c_rudder_openssh_server_package_name" string => canonify("${rudder_openssh_server_package_name}"); 20 | 21 | methods: 22 | linux:: 23 | "any" usebundle => package_present("${rudder_openssh_server_package_name}", "", "", ""); 24 | } 25 | 26 | bundle agent rudder_openssh_server_installation_reporting(class_prefix, service_name, params) 27 | { 28 | methods: 29 | "any" usebundle => rudder_common_reports_generic("${service_name}", "package_present_${rudder_openssh_server_installation.c_rudder_openssh_server_package_name}", "${${params}[report]}", "SSH installation", "None", "The ${service_name} package installation"); 30 | 31 | !linux:: 32 | "any" usebundle => rudder_common_report("${service_name}", "result_success", "${${params}[report]}", "SSH installation", "None", "Support to check if ${service_name} is installed not available on this platform"); 33 | 34 | } 35 | 36 | # This bundle is common because it defines a class that we reuse in the configuration part, 37 | # when configuring the service, to not configure the service if the binary is not there 38 | bundle common rudder_openssh_server_check_ssh_installation 39 | { 40 | classes: 41 | # Security : if not there, SSH too, so do not bother anymore 42 | # I cannot use the class_prefix in the class definition, because it is a bundle common 43 | # and for some reason, CFEngine complains about it not being canonified 44 | "rudder_openssh_server_binary_present" 45 | expression => fileexists("/usr/sbin/sshd"); 46 | } 47 | 48 | bundle agent rudder_openssh_server_check_ssh_installation_reporting(class_prefix, service_name, params) 49 | { 50 | methods: 51 | # Make a report about the lack of proper sshd binary 52 | "any" 53 | usebundle => rudder_common_report("${service_name}", "result_error", "${${params}[report]}", "SSH installation", "None", "The ${service_name} is not installed, although it should have been"), 54 | ifvarclass => "!${class_prefix}_binary_present"; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 3.0 3 | ** Rewrite with normal ordering and {} 4 | -- Nicolas Charles Tue Aug 21 17:06:54 2018 5 | * Version 4.0 6 | ** Port sshKeyDistribution to multiversionned technique 7 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique will check if the required SSH keys are present on a user directory. Supported key formats are ssh-rsa|ssh-dss|ssh-ed25519|ecdsa-sha2-nistp521|ecdsa-sha2-nistp384|ecdsa-sha2-nistp256|ssh-dsa. 4 | true 5 | separated 6 | 7 | 8 | check_ssh_key_distribution_RudderUniqueID 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |       
18 |     
19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | SSH_KEY_DISTRIBUTION_NAME 27 | 28 | 29 | 30 |
31 |
32 | 33 | SSH_KEY_DISTRIBUTION_TAG 34 | Key tag (for tracking only) 35 | Enter a tag to track this key in reports, i.e. "root #1" or "Operations key". It will not be used in the authorized_keys file. 36 | 37 | false 38 | string 39 | 40 | 41 | 42 | SSH_KEY_DISTRIBUTION_NAME 43 | Username 44 | User to apply the key to 45 | 46 | string 47 | 48 | 49 | 50 | SSH_KEY_DISTRIBUTION_KEY 51 | Key 52 | Full content of the key to insert in authorized_keys format, may include comments. 53 | 54 | textarea 55 | 56 | 57 |
58 |
59 | 60 | SSH_KEY_DISTRIBUTION_EDIT_TYPE 61 | Remove other keys 62 | Flush the authorized keys file - only keys managed by Rudder will remain in this file. If any key for a user has this parameter set, and is not in audit mode, then all keys non managed by Rudder for this user will be purged. Also, if any keys checked in audit mode is non compliant for a given user, the keys won't be purged. 63 | 64 | 65 | true 66 | 67 | 68 | 69 | false 70 | 71 | 72 | false 73 | 74 | 75 |
76 |
77 |
78 | 79 |
80 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/FlushKey_TestSSHKeyDistribution.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | useradd -m flushKeyTesting 4 | 5 | 6 | > /home/flushKeyTesting/.ssh/authorized_keys 7 | exit 0 8 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistribution.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "checks": [ 3 | "TestSSHKeyDistribution.rb" 4 | ], 5 | "compliance": 88.89, 6 | "directives": [ 7 | "TestSSHKeyDistribution.json" 8 | ], 9 | "inits": [ "TestSSHKeyDistributionCleanSSHKeyFile.sh" ], 10 | "sharedFiles": [], 11 | "resources" : [ "common_sshKeyDistribution_test.rb" ] 12 | }] 13 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistribution.rb: -------------------------------------------------------------------------------- 1 | # Sample file generated using rtf test from-rule 2 | # This is where you test your rule 3 | 4 | require 'spec_helper' 5 | require ENV["SCENARIO_BASE"]+'/common_sshKeyDistribution_test' 6 | 7 | 8 | 9 | test_sshKeyDistribution('repaired') 10 | 11 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistributionCleanSSHKeyFile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | useradd -m keyTesting 4 | 5 | rm -rf /home/keyTesting/.ssh 6 | exit 0 7 | 8 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistributionExisting.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "checks": [ 3 | "TestSSHKeyDistributionExisting.rb" 4 | ], 5 | "compliance": 88.89, 6 | "directives": [ 7 | "TestSSHKeyDistribution.json" 8 | ], 9 | "inits": [ "TestSSHKeyDistributionExisting.sh" ], 10 | "sharedFiles": [ ], 11 | "resources" : [ "common_sshKeyDistribution_test.rb" ] 12 | }] 13 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistributionExisting.rb: -------------------------------------------------------------------------------- 1 | # Sample file generated using rtf test from-rule 2 | # This is where you test your rule 3 | 4 | require 'spec_helper' 5 | load ENV["SCENARIO_BASE"]+'/common_sshKeyDistribution_test.rb' 6 | 7 | test_sshKeyDistribution('success') 8 | 9 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/TestSSHKeyDistributionExisting.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | useradd -m keyTesting 4 | 5 | # Force keys to be present 6 | rudder agent run > /dev/null 7 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/flush_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "Test_SSHKeyDistribution_Flush_key_V4_0", 3 | "enabled": true, 4 | "longDescription": "", 5 | "parameters": { 6 | "section": { 7 | "name": "sections", 8 | "sections": [ 9 | { 10 | "section": { 11 | "name": "SSH key", 12 | "vars": [ 13 | { 14 | "var": { 15 | "name": "SSH_KEY_DISTRIBUTION_EDIT_TYPE", 16 | "value": "true" 17 | } 18 | }, 19 | { 20 | "var": { 21 | "name": "SSH_KEY_DISTRIBUTION_KEY", 22 | "value": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+D2shtMtcTHPopDymV90PTj9ORTdOimAp9GRrPoO0DgEJFvzjb2N6elWZaOHikMjSZ6L+fc9J1fFJw2wmTOu84470qNGSjUi1XmkWkMzni/c7DCWXmHdmfyGM3DAMheheu9w4FIhnelU0jIcHeB2W1gvGOEkbyphAizZvaAT5paOiVnxE9DvC+xGnJFqlyWRRvF88teeO+HDFBBqoCNnBDHtlKzAQNmPKwckns5dBmxV/oV/9fjs0MoFhvcFBs2bMJGZmQjeGNdHLzfvggEpaB8pmdhlVqKqq7DdoUfIeoS4ekzEuQEe0aaEFPF/lJjKtBYO0e//Fkc+BKpN0z5MbzN5W6oai9G6uGImSYBN8N0EsdEVm39OBHycJRtA1N0L4127LnL4OangGY6SVkN2FSDbrXcCyPUES/opuYxXQaEH8m2tKmrq7TiDPB9XFTCZ0WQJTW36t9VrTVZPMdMFcX7E1ZWDKVQ/9/k+M9G1pBLvi4iUzTBbvqvDE0A1NQDB4C1QsrcXkdqoCq3yeTdfPNcCnRGLZ2vYSkVZK4kvSYRS/691Z2tZutbsx0oKP0rrWisWLZqjIpTgT6Bf2U+lUpHMoMVmqKsSE6iRbRBubwxhwOl/BIkvG3bvgPKUcv9pAwXLMBQM/elmGrU7L5lFeUV4EnEtX4aTq+BapvF+Tvw== your_email@example.com" 23 | } 24 | }, 25 | { 26 | "var": { 27 | "name": "SSH_KEY_DISTRIBUTION_NAME", 28 | "value": "flushKeyTesting" 29 | } 30 | }, 31 | { 32 | "var": { 33 | "name": "SSH_KEY_DISTRIBUTION_TAG", 34 | "value": "Flushing key" 35 | } 36 | } 37 | ] 38 | } 39 | }, 40 | { 41 | "section": { 42 | "name": "SSH key", 43 | "vars": [ 44 | { 45 | "var": { 46 | "name": "SSH_KEY_DISTRIBUTION_EDIT_TYPE", 47 | "value": "false" 48 | } 49 | }, 50 | { 51 | "var": { 52 | "name": "SSH_KEY_DISTRIBUTION_KEY", 53 | "value": "command=\"command\" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCyK0YmNGuYgUTFkSZ6Vkk5VQRdpkR6OKa3GJgfTloCWKZ3ekkPblSgY+u6q16TVXD4Ns1EXU2Wciwtt/uJSeZA= your_email@example.com" 54 | } 55 | }, 56 | { 57 | "var": { 58 | "name": "SSH_KEY_DISTRIBUTION_NAME", 59 | "value": "flushKeyTesting" 60 | } 61 | }, 62 | { 63 | "var": { 64 | "name": "SSH_KEY_DISTRIBUTION_TAG", 65 | "value": "Non flushing key" 66 | } 67 | } 68 | ] 69 | } 70 | } 71 | ] 72 | } 73 | }, 74 | "shortDescription": "", 75 | "techniqueName": "sshKeyDistribution", 76 | "techniqueVersion": "4.0" 77 | } 78 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/flush_key.metadata: -------------------------------------------------------------------------------- 1 | [{ 2 | "checks": [ 3 | "flush_key.rb" 4 | ], 5 | "compliance": 100, 6 | "directives": [ 7 | "flush_key.json" 8 | ], 9 | "inits": [ "FlushKey_TestSSHKeyDistribution.sh"], 10 | "sharedFiles": [] 11 | }] 12 | -------------------------------------------------------------------------------- /techniques/systemSettings/remoteAccess/sshKeyDistribution/4.0/tests/flush_key.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | def test_flushKey(status) 5 | describe user('flushKeyTesting') do 6 | it { should exist } 7 | it { should have_home_directory '/home/flushKeyTesting' } 8 | end 9 | 10 | describe file('/home/flushKeyTesting/.ssh') do 11 | it { should be_directory } 12 | it { should be_mode 700 } 13 | it { should be_owned_by 'flushKeyTesting' } 14 | end 15 | 16 | #Testing /home/?/.ssh/authorized_keys file 17 | describe file('/home/flushKeyTesting/.ssh/authorized_keys') do 18 | it { should be_file } 19 | it { should be_mode 600 } 20 | it { should be_owned_by 'flushKeyTesting' } 21 | end 22 | 23 | #Testing /home/?/.ssh/authorized_keys file 24 | describe file('/home/flushKeyTesting/.ssh/authorized_keys') do 25 | it { should be_file } 26 | it { should be_mode 600 } 27 | it { should be_owned_by 'flushKeyTesting' } 28 | 29 | it { should contain 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+D2shtMtcTHPopDymV90PTj9ORTdOimAp9GRrPoO0DgEJFvzjb2N6elWZaOHikMjSZ6L+fc9J1fFJw2wmTOu84470qNGSjUi1XmkWkMzni/c7DCWXmHdmfyGM3DAMheheu9w4FIhnelU0jIcHeB2W1gvGOEkbyphAizZvaAT5paOiVnxE9DvC+xGnJFqlyWRRvF88teeO+HDFBBqoCNnBDHtlKzAQNmPKwckns5dBmxV/oV/9fjs0MoFhvcFBs2bMJGZmQjeGNdHLzfvggEpaB8pmdhlVqKqq7DdoUfIeoS4ekzEuQEe0aaEFPF/lJjKtBYO0e//Fkc+BKpN0z5MbzN5W6oai9G6uGImSYBN8N0EsdEVm39OBHycJRtA1N0L4127LnL4OangGY6SVkN2FSDbrXcCyPUES/opuYxXQaEH8m2tKmrq7TiDPB9XFTCZ0WQJTW36t9VrTVZPMdMFcX7E1ZWDKVQ/9/k+M9G1pBLvi4iUzTBbvqvDE0A1NQDB4C1QsrcXkdqoCq3yeTdfPNcCnRGLZ2vYSkVZK4kvSYRS/691Z2tZutbsx0oKP0rrWisWLZqjIpTgT6Bf2U+lUpHMoMVmqKsSE6iRbRBubwxhwOl/BIkvG3bvgPKUcv9pAwXLMBQM/elmGrU7L5lFeUV4EnEtX4aTq+BapvF+Tvw== your_email@example.com' } 30 | end 31 | 32 | if status == "success" 33 | message_status = "correct" 34 | else 35 | message_status = status 36 | end 37 | 38 | test_report_present('sshKeyDistribution', "result_#{status}", 'SSH key', 'Non flushing key', "SSH key \"Non flushing key\" for user flushKeyTesting was #{message_status}") 39 | test_report_present('sshKeyDistribution', "result_#{status}", 'SSH key', 'Flushing key', "SSH key \"Flushing key\" for user flushKeyTesting was #{message_status}") 40 | end 41 | 42 | 43 | test_flushKey('repaired') 44 | -------------------------------------------------------------------------------- /techniques/systemSettings/security/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Security settings 4 | This category contains Techniques aimed to configure the basic security settings a system, like the file integrity monitoring 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/security/fileAlterationMonitoring/2.2/changelog: -------------------------------------------------------------------------------- 1 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 2 | * Version 2.0 3 | ** Use rudder_common_report instead of reports: 4 | -- Nicolas Charles Wed Jun 14 15:07:55 2017 5 | * Version 2.1 6 | ** Add exception for non-existent files 7 | -- Nicolas Charles Fri Dec 8 16:39:15 2017 8 | * Version 2.2 9 | ** Port technique to multi-versioned format 10 | -------------------------------------------------------------------------------- /techniques/systemSettings/security/fileAlterationMonitoring/2.2/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique checks whether a file or directory has changed between agent executions and report changes if any 4 | This technique version is not maintained anymore, it will no longer be available in the next version of Rudder. 5 | 6 | true 7 | separated 8 | 9 | 10 | file_alteration_monitor_RudderUniqueID 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | MONITOR_ENTITY_NAME 19 | 20 | 21 | 22 |
23 | 24 | MONITOR_ENTITY_NAME 25 | Full path to the file or directory to monitor 26 | 27 | 28 | MONITOR_ERROR_NOFILE 29 | Report an error if the file or directory is absent 30 | 31 | true 32 | 33 | 34 | 35 | false 36 | 37 | 38 | 39 | true 40 | 41 | 42 |
43 |
44 | 45 |
46 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | System management 4 | This category contains Techniques to manage all system related parameters, such as fstab, ... 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/cronManagement/3.2/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Jeremy HOCDE Tue Aug 09 12:05:43 CEST 2016 8 | * Version 3.1 9 | ** Add special values: reboot, yearly and annually 10 | -- Nicolas Charles Thu Dec 20 12:27:44 2018 11 | * Version 3.2 12 | ** Port technique to separated policy generation 13 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/motdConfiguration/3.3/changelog: -------------------------------------------------------------------------------- 1 | -- Nicolas Charles Wed Feb 13 15:39:07 2019 2 | * Version 3.3 3 | ** Adapt technique for DSC 4 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/motdConfiguration/3.3/config.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | ############################################################################## 5 | # This Technique configures a machine MOTD. See metadata.xml for more details. 6 | ############################################################################## 7 | 8 | bundle agent rudder_motd 9 | { 10 | vars: 11 | "rudder_motd_service_name" string => "MOTD"; 12 | 13 | # Prefix for all the defined classes 14 | "rudder_motd_class_prefix" string => "rudder_motd"; 15 | 16 | "rudder_motd_config[payload]" string => "&MOTD&"; 17 | 18 | "rudder_motd_config[location]" string => "&MOTD_LOCATION&"; 19 | 20 | "rudder_motd_config[file_empty]" string => "&MOTD_EMPTY&"; 21 | 22 | "rudder_motd_config[banner]" string => "&MOTD_BANNER&"; 23 | 24 | "rudder_motd_config[trackingkey]" string => "&TRACKINGKEY&"; 25 | 26 | methods: 27 | # Note: 28 | # The reporting is made on separate bundles to abstract the complexity 29 | # inherent to the normal ordering. 30 | "any" usebundle => rudder_motd_configuration("${rudder_motd_class_prefix}", "${rudder_motd_service_name}", "${rudder_motd_config[trackingkey]}", "rudder_motd.rudder_motd_config"); 31 | "any" usebundle => rudder_motd_configuration_reporting("${rudder_motd_class_prefix}", "${rudder_motd_service_name}", "${rudder_motd_config[trackingkey]}"); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/motdConfiguration/3.3/main.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | ############################################################## 5 | # Sets the MOTD according to the value given in the Directive. 6 | ############################################################## 7 | 8 | bundle agent rudder_motd_configuration(class_prefix, service_name, trackingkey, params) 9 | { 10 | vars: 11 | "rudder_motd_payload" string => "${${params}[payload]}"; 12 | "rudder_motd_location" string => "${${params}[location]}"; 13 | "rudder_motd_empty" string => "${${params}[file_empty]}"; 14 | 15 | aix:: 16 | "rudder_motd_group" string => "bin"; 17 | !aix:: 18 | "rudder_motd_group" string => "root"; 19 | 20 | debian:: 21 | "rudder_motd_file" slist => { "/etc/motd", "/etc/motd.tail" }; 22 | !debian:: 23 | "rudder_motd_file" slist => { "/etc/motd" }; 24 | 25 | pass2.set_banner:: 26 | "banner_files" slist => { "/etc/issue", "/etc/issue.net" }; 27 | 28 | pass2:: 29 | "rudder_motd_issue_files" slist => { @{rudder_motd_file}, @{banner_files} }, 30 | policy => "ifdefined"; 31 | 32 | 33 | classes: 34 | "rudder_motd_absent" not => fileexists("/etc/motd"); 35 | 36 | "set_banner" expression => strcmp("true", "${${params}[banner]}"); 37 | 38 | "pass2" expression => "pass1"; 39 | "pass1" expression => "any"; 40 | 41 | files: 42 | # Set every MOTD file to the wanted value 43 | pass2:: 44 | "${rudder_motd_issue_files}" 45 | create => "true", 46 | edit_defaults => rudder_empty_select("${rudder_motd_empty}"), 47 | perms => mog("644", "root", "${rudder_motd_group}"), 48 | edit_line => rudder_line_insertion("${rudder_motd_payload}", "${rudder_motd_location}"), 49 | classes => classes_generic("${class_prefix}_file_edition"); 50 | 51 | methods: 52 | # Here, we will define reports for elements which only have a local visibility (like the MOTD file presence detection). 53 | pass2.rudder_motd_absent:: 54 | "any" 55 | usebundle => rudder_common_report("${service_name}", "log_repaired", "${trackingkey}", "MOTD Configuration", "None", "The ${service_name} file was absent, it will be created"); 56 | } 57 | 58 | # The reporting is made on separate bundles to abstract the complexity 59 | # inherent to the normal ordering. 60 | bundle agent rudder_motd_configuration_reporting(class_prefix, service_name, trackingkey) 61 | { 62 | methods: 63 | "any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_file_edition", "${trackingkey}", "MOTD Configuration", "None", "The ${service_name} file"); 64 | } 65 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/motdConfiguration/3.3/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique will check if the required Message Of The Day is present on the system. 4 | false 5 | 6 | 7 | 8 | rudder_motd 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | rudderMotd 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | MOTD 29 | Message of the day (MOTD) to display 30 | 31 | textarea 32 | 33 | 34 | 35 | MOTD_LOCATION 36 | Where should this text be added in the MOTD 37 | This option defines if the content specified before should be appended or prepended to the file. It is irrelevant if you enforce the file content (option below), or on Windows 38 | 39 | 40 | before 41 | 42 | 43 | 44 | after 45 | 46 | 47 | after 48 | 49 | 50 | 51 | MOTD_EMPTY 52 | Replace the existing content of the MOTD 53 | This option will remove any existing messages in the motd file and replace them with the text provided above. On Windows, the provided text will always remove any existing message 54 | 55 | 56 | true 57 | 58 | 59 | 60 | false 61 | 62 | 63 | false 64 | 65 | 66 | 67 | 68 | MOTD_BANNER 69 | Display also this message before login 70 | If this option is set, the text will also be printed before the login prompt (by editing /etc/issue and /etc/issue.net). Not available on Windows. 71 | 72 | 73 | true 74 | 75 | 76 | 77 | false 78 | 79 | 80 | false 81 | 82 | 83 | 84 |
85 |
86 | 87 |
88 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/motdConfiguration/3.3/motd.ps1.st: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-3.0-or-later 2 | # SPDX-FileCopyrightText: 2021 Normation SAS 3 | 4 | function rudderMotd { 5 | [CmdletBinding()] 6 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'reportId', Justification = 'Very old technique')] 7 | param ( 8 | [parameter(Mandatory = $true)] 9 | [string]$reportId, 10 | 11 | [parameter(Mandatory = $true)] 12 | [string]$techniqueName, 13 | 14 | [Rudder.PolicyMode]$policyMode 15 | ) 16 | $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 17 | 18 | $commonParams = @{ 19 | TechniqueName = $techniqueName 20 | PolicyMode = $policyMode 21 | ClassPrefix = "rudderMotd" 22 | ReportID = "&TRACKINGKEY&" 23 | ComponentKey = "None" 24 | ComponentName = "MOTD Configuration" 25 | } 26 | 27 | # Ensure that the caption is there (mandatory to have the message) 28 | $regCall = Registry-Entry-Present -Key $registryPath -Entry "legalnoticecaption" -Value "Notice" -RegistryType "String" -PolicyMode $policyMode 29 | $null = Compute-Method-Call @commonParams -MethodCall $regCall -DisableReporting:$true 30 | 31 | # Ensure that the content is valid 32 | $contentCall = Registry-Entry-Present -Key $registryPath -Entry "legalnoticetext" -Value "&MOTD&" -RegistryType "String" -PolicyMode $policyMode 33 | $null = Compute-Method-Call @commonParams -MethodCall $contentCall 34 | } 35 | -------------------------------------------------------------------------------- /techniques/systemSettings/systemManagement/userCronManagement/1.0/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | This technique enables you to set jobs that will be launched regularly using crond for users, in /var/spool/cron/crontab 3 | It supports both Linux, AIX and Solaris. 4 | 5 | true 6 | separated 7 | 8 | 9 | user_cron_configuration_RudderUniqueID 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | USER_CRON_TAG 25 | 26 | 27 | 28 |
29 |
30 | 31 | USER_CRON_TAG 32 | Tag to identify the command 33 | Tag to identify the command, included after the command with a # to document and identify it 34 | 35 | false 36 | 37 | 38 | 39 | 40 | USER_CRON_USER 41 | User to run the command as 42 | 43 | [a-z][-a-zA-Z0-9_.]+ 44 | root 45 | 46 | 47 | 48 | 49 | USER_CRON_COMMAND 50 | Command to run 51 | 52 | textarea 53 | 54 | 55 | 56 | 57 | 58 | USER_CRON_FREQUENCY 59 | Manually defined frequency 60 | Please input a valid cron frequency definition 61 | 62 | (\*|(([0-5]?[0-9])(-([0-5]?[0-9]))?))(/\d+)?(,(\*|(([0-5]?[0-9])(-([0-5]?[0-9]))?))(/\d+)?)*\s+(\*|([01]?[0-9]|2[0-3])(-([01]?[0-9]|2[0-3]))?)(/\d+)?(,(\*|(([01]?[0-9]|2[0-3])(-([01]?[0-9]|2[0-3]))?))(/\d+)?)*\s+(\*|(([1-9]|[12][0-9]|3[01])(-([1-9]|[12]?[0-9]|3[01]))?))(/\d+)?(,(\*|(([1-9]|[12]?[0-9]|3[01])(-([1-9]|[12]?[0-9]|3[01]))?))(/\d+)?)*\s+(\*|(([1-9]|1[0-2])(-([1-9]|1[0-2]))?))(/\d+)?(,(\*|(([1-9]|1[0-2])(-([1-9]|1[0-2]))?))(/\d+)?)*\s+(\*|(([0-7])(-([0-7]))?))(/\d+)?(,(\*|(([0-7])(-([0-7]))?))(/\d+)?)* 63 | false 64 | 65 | 66 |
67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | User management 4 | This category contains Techniques to manage all user related parameters, such as group and user creation, sudo parameters... 5 | 6 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/groupManagement/5.1/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 4.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 5.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Nicolas Charles Tue Dec 12 11:45:14 2017 8 | * Version 5.1 9 | ** Convert to multiversionned technique 10 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/groupManagement/5.1/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique manages the target host(s) groups. 4 | 5 | It will ensure that the defined groups are present on the system. 6 | true 7 | separated 8 | 9 | 10 | check_usergroup_grp_parameters_RudderUniqueID 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | USERGROUP_GROUP_NAME 19 | 20 | 21 | 22 |
23 |
24 | 25 | USERGROUP_GROUP_NAME 26 | Name 27 | 28 | true 29 | 30 | 31 | 32 | USERGROUP_GROUP_CREATE 33 | Create the group if it doesn't exist 34 | 35 | boolean 36 | true 37 | 38 | 39 | 40 | USERGROUP_GROUP_SET_GID 41 | Set Group ID 42 | 43 | boolean 44 | false 45 | 46 | 47 | 48 | USERGROUP_GROUP_GID 49 | Group ID 50 | 51 | true 52 | 53 | 54 | 55 | USERGROUP_GROUP_ENFORCE_CONTENT 56 | Enforce only the following users in the group 57 | If checked, group content will be completely replaced by the user list, otherwise, the user list is appended 58 | 59 | boolean 60 | false 61 | 62 | 63 | 64 | USERGROUP_GROUP_CONTENT 65 | Group members 66 | This should be a comma separated list of user names 67 | 68 | true 69 | 70 | 71 |
72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/sudoParameters/3.2/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:52:55 CEST 2014 2 | * Version 2.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 5 | * Version 3.0 6 | ** Use rudder_common_report instead of reports: 7 | -- Nicolas Charles Fri Jun 16 12:32:55 2017 8 | * Version 3.1 9 | ** Make sudo management update safe 10 | -- Nicolas Charles Thu Mar 1 16:58:20 2018 11 | * Version 3.2 12 | ** Adapt technique to directive by directive generation 13 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/sudoParameters/3.2/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | This technique configures the sudo utility. 4 | 5 | It will ensure that the defined rights for given users and groups are correctly defined. 6 | true 7 | separated 8 | 9 | 10 | check_sudo_parameters_RudderUniqueID 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | SUDO_NAME 19 | 20 | 21 | 22 |
23 |       
24 |       
25 |     
26 |
27 |       
28 |     
29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 |
37 |
38 | 39 | 40 |
41 | 42 | SUDO_TYPE 43 | Entity type 44 | 45 | user 46 | 47 | 48 | 49 | group 50 | 51 | 52 | 53 | user 54 | 55 | 56 | 57 | SUDO_NAME 58 | Entity name 59 | 60 | 61 | SUDO_NOPASSWD 62 | Allow the entity to execute the given commands without entering his password 63 | 64 | boolean 65 | false 66 | 67 | 68 | 69 | SUDO_ALL 70 | Allow the entity to execute all commands 71 | 72 | boolean 73 | true 74 | 75 | 76 | 77 | SUDO_COMMAND 78 | Commands allowed to this entity 79 | 80 | true 81 | 82 | 83 |
84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/userManagement/10/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:17:55 CEST 2014 2 | * Version 4.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Thu Oct 2 10:00:32 CEST 2014 5 | * Version 5.0 6 | ** Handle gid/uid at user creation 7 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 8 | * Version 6.0 9 | ** Use rudder_common_report instead of reports: 10 | -- Nicolas Charles Fri Jul 15 15:50:00 CEST 2016 11 | * Version 7.0 12 | ** Add AIX support 13 | -- Nicolas Charles Fri Jul 22 15:41:00 CEST 2016 14 | * Version 7.1 15 | ** Add an option to move the home directory 16 | -- Felix Dallidet Thu Aug 17 16:14:11 2017 17 | * Version 8.0 18 | ** make a linux and windows compatible user technique 19 | -- Nicolas Charles Wed Oct 18 11:45:50 2017 20 | * Version 8.1 21 | ** Add an option to force gid 22 | -- Nicolas Charles Tue Jun 5 17:06:21 2018 23 | * Version 9.0 24 | ** Port to multi-versioned format 25 | -- Nicolas Charles Tue Jun 5 17:27:21 2023 26 | * Version 9.1 27 | ** Add option to set secondary group 28 | -- Nicolas Charles Wed Ap 17 14:19:00 2024 29 | * Version 10.0 30 | ** Add option to update only, use generic methods 31 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/userManagement/9.0/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:17:55 CEST 2014 2 | * Version 4.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Thu Oct 2 10:00:32 CEST 2014 5 | * Version 5.0 6 | ** Handle gid/uid at user creation 7 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 8 | * Version 6.0 9 | ** Use rudder_common_report instead of reports: 10 | -- Nicolas Charles Fri Jul 15 15:50:00 CEST 2016 11 | * Version 7.0 12 | ** Add AIX support 13 | -- Nicolas Charles Fri Jul 22 15:41:00 CEST 2016 14 | * Version 7.1 15 | ** Add an option to move the home directory 16 | -- Felix Dallidet Thu Aug 17 16:14:11 2017 17 | * Version 8.0 18 | ** make a linux and windows compatible user technique 19 | -- Nicolas Charles Wed Oct 18 11:45:50 2017 20 | * Version 8.1 21 | ** Add an option to force gid 22 | -- Nicolas Charles Tue Jun 5 17:06:21 2018 23 | * Version 9.0 24 | ** Port to multi-versioned format 25 | -------------------------------------------------------------------------------- /techniques/systemSettings/userManagement/userManagement/9.1/changelog: -------------------------------------------------------------------------------- 1 | -- Benoit PECCATTE Tue Sep 9 08:17:55 CEST 2014 2 | * Version 4.0 3 | ** Rewrite with normal ordering and {} 4 | -- Benoît Peccatte Thu Oct 2 10:00:32 CEST 2014 5 | * Version 5.0 6 | ** Handle gid/uid at user creation 7 | -- Benoît Peccatte Fri Oct 17 14:10:43 CEST 2014 8 | * Version 6.0 9 | ** Use rudder_common_report instead of reports: 10 | -- Nicolas Charles Fri Jul 15 15:50:00 CEST 2016 11 | * Version 7.0 12 | ** Add AIX support 13 | -- Nicolas Charles Fri Jul 22 15:41:00 CEST 2016 14 | * Version 7.1 15 | ** Add an option to move the home directory 16 | -- Felix Dallidet Thu Aug 17 16:14:11 2017 17 | * Version 8.0 18 | ** make a linux and windows compatible user technique 19 | -- Nicolas Charles Wed Oct 18 11:45:50 2017 20 | * Version 8.1 21 | ** Add an option to force gid 22 | -- Nicolas Charles Tue Jun 5 17:06:21 2018 23 | * Version 9.0 24 | ** Port to multi-versioned format 25 | -- Nicolas Charles Tue Jun 5 17:27:21 2023 26 | * Version 9.1 27 | ** Add option to set secondary group 28 | 29 | -------------------------------------------------------------------------------- /typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | #extend-exclude = [ "*.json", "test_fileTemplate.*", "template1", "checkGenericFileContent.st", "rudder-groups.st", "Jenkinsfile" ] 3 | extend-exclude = [ "*.json", "test_fileTemplate.*", "template1", "Jenkinsfile", "*.pub" ] 4 | 5 | [default] 6 | extend-ignore-re = [ "2nd", "64f85ba8" ] 7 | 8 | -------------------------------------------------------------------------------- /variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "AGENT_RUN_INTERVAL": "5", 3 | "AGENT_RUN_SCHEDULE": "\"Min00\", \"Min05\", \"Min10\", \"Min15\", \"Min20\", \"Min25\", \"Min30\", \"Min35\", \"Min40\", \"Min45\", \"Min50\", \"Min55\"", 4 | "AGENT_RUN_SPLAYTIME": "1", 5 | "AGENT_TYPE": "cfengine-community", 6 | "AUTHORIZED_NETWORKS": [], 7 | "CFENGINE_OUTPUTS_TTL": "7", 8 | "COMMUNITYPORT": "5309", 9 | "CONFIGURATION_REPOSITORY_FOLDER": "/var/rudder/configuration-repository", 10 | "DAVPASSWORD": "rudder", 11 | "DAVUSER": "rudder", 12 | "DENYBADCLOCKS": "true", 13 | "INITIAL": true, 14 | "MANAGED_NODES_ID": [ ], 15 | "MANAGED_NODES_NAME": [ ], 16 | "MODIFIED_FILES_TTL": "30", 17 | "POLICYSERVER_ADMIN": "root", 18 | "RUDDER_DIRECTIVES_INPUTS": "", 19 | "RUDDER_DIRECTIVES_SEQUENCE": "", 20 | "RUDDER_SYSTEM_DIRECTIVES_INPUTS": "", 21 | "RUDDER_SYSTEM_DIRECTIVES_SEQUENCE": "", 22 | "RUDDER_HEARTBEAT_INTERVAL": "4", 23 | "RUDDER_NODE_CONFIG_ID": "0", 24 | "RUDDER_REPORT_MODE": "full-compliance", 25 | "RUDDER_REPORTS_DB_NAME": "rudder", 26 | "RUDDER_REPORTS_DB_USER": "rudder", 27 | "RUDDER_SYSTEM_DIRECTIVES_INPUTS": "", 28 | "RUDDER_SYSTEM_DIRECTIVES_SEQUENCE": "", 29 | "SEND_METRICS": "no", 30 | "SHARED_FILES_FOLDER": "/var/rudder/configuration-repository/shared-files", 31 | "TRACKINGKEY": "root-DP@@root-distributePolicy@@00", 32 | "RUDDER_INVENTORY_VARS": "{ \"initial-policies\": \"true\" }" 33 | } 34 | --------------------------------------------------------------------------------