Skip to content

Commit db7aff0

Browse files
authored
Merge pull request #1004 from tgauth/add-sshdconfig-get
Add sshdconfig get
2 parents 4750f77 + 1f75dff commit db7aff0

File tree

14 files changed

+570
-73
lines changed

14 files changed

+570
-73
lines changed

dsc/tests/dsc_sshdconfig.tests.ps1

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
BeforeDiscovery {
4+
if ($IsWindows) {
5+
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
6+
$principal = [System.Security.Principal.WindowsPrincipal]::new($identity)
7+
$isElevated = $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
8+
$sshdExists = ($null -ne (Get-Command sshd -CommandType Application -ErrorAction Ignore))
9+
$skipTest = !$isElevated -or !$sshdExists
10+
}
11+
}
12+
13+
Describe 'SSHDConfig resource tests' -Skip:(!$IsWindows -or $skipTest) {
14+
BeforeAll {
15+
# set a non-default value in a temporary sshd_config file
16+
"LogLevel Debug3`nPasswordAuthentication no" | Set-Content -Path $TestDrive/test_sshd_config
17+
$filepath = Join-Path $TestDrive 'test_sshd_config'
18+
$yaml = @"
19+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
20+
metadata:
21+
Microsoft.DSC:
22+
securityContext: elevated
23+
resources:
24+
- name: sshdconfig
25+
type: Microsoft.OpenSSH.SSHD/sshd_config
26+
metadata:
27+
filepath: $filepath
28+
properties:
29+
"@
30+
}
31+
32+
It '<command> works' -TestCases @(
33+
@{ command = 'get' }
34+
@{ command = 'export' }
35+
) {
36+
param($command)
37+
$out = dsc config $command -i "$yaml" | ConvertFrom-Json -Depth 10
38+
$LASTEXITCODE | Should -Be 0
39+
if ($command -eq 'export') {
40+
$out.resources.count | Should -Be 1
41+
$out.resources[0].properties | Should -Not -BeNullOrEmpty
42+
$out.resources[0].properties.port | Should -BeNullOrEmpty
43+
$out.resources[0].properties.passwordAuthentication | Should -Be 'no'
44+
$out.resources[0].properties._inheritedDefaults | Should -BeNullOrEmpty
45+
} else {
46+
$out.results.count | Should -Be 1
47+
$out.results.result.actualState | Should -Not -BeNullOrEmpty
48+
$out.results.result.actualState.port[0] | Should -Be 22
49+
$out.results.result.actualState.passwordAuthentication | Should -Be 'no'
50+
$out.results.result.actualState._inheritedDefaults | Should -Contain 'port'
51+
}
52+
}
53+
54+
It 'Export with filter works' {
55+
$export_yaml = @"
56+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
57+
metadata:
58+
Microsoft.DSC:
59+
securityContext: elevated
60+
resources:
61+
- name: sshdconfig
62+
type: Microsoft.OpenSSH.SSHD/sshd_config
63+
metadata:
64+
filepath: $filepath
65+
properties:
66+
passwordauthentication: 'yes'
67+
"@
68+
$out = dsc config export -i "$export_yaml" | ConvertFrom-Json -Depth 10
69+
$LASTEXITCODE | Should -Be 0
70+
$out.resources.count | Should -Be 1
71+
($out.resources[0].properties.psobject.properties | Measure-Object).count | Should -Be 1
72+
$out.resources[0].properties.passwordAuthentication | Should -Be 'no'
73+
}
74+
75+
It '<command> with _includeDefaults specified works' -TestCases @(
76+
@{ command = 'get'; includeDefaults = $false }
77+
@{ command = 'export'; includeDefaults = $true }
78+
) {
79+
param($command, $includeDefaults)
80+
$filepath = Join-Path $TestDrive 'test_sshd_config'
81+
$input = @"
82+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
83+
metadata:
84+
Microsoft.DSC:
85+
securityContext: elevated
86+
resources:
87+
- name: sshdconfig
88+
type: Microsoft.OpenSSH.SSHD/sshd_config
89+
metadata:
90+
filepath: $filepath
91+
properties:
92+
_includeDefaults: $includeDefaults
93+
"@
94+
$out = dsc config $command -i "$input" | ConvertFrom-Json -Depth 10
95+
$LASTEXITCODE | Should -Be 0
96+
if ($command -eq 'export') {
97+
$out.resources.count | Should -Be 1
98+
$out.resources[0].properties.loglevel | Should -Be 'debug3'
99+
$out.resources[0].properties.port | Should -Be 22
100+
$out.resources[0].properties._inheritedDefaults | Should -BeNullOrEmpty
101+
} else {
102+
$out.results.count | Should -Be 1
103+
($out.results.result.actualState.psobject.properties | Measure-Object).count | Should -Be 2
104+
$out.results.result.actualState.loglevel | Should -Be 'debug3'
105+
$out.results.result.actualState._inheritedDefaults | Should -BeNullOrEmpty
106+
}
107+
}
108+
109+
Context 'Surface a default value that has been set in file' {
110+
BeforeAll {
111+
"Port 22" | Set-Content -Path $TestDrive/test_sshd_config
112+
}
113+
114+
It '<command> works' -TestCases @(
115+
@{ command = 'get' }
116+
@{ command = 'export' }
117+
) {
118+
param($command)
119+
$out = dsc config $command -i "$yaml" | ConvertFrom-Json -Depth 10
120+
$LASTEXITCODE | Should -Be 0
121+
if ($command -eq 'export') {
122+
$out.resources.count | Should -Be 1
123+
$out.resources[0].properties | Should -Not -BeNullOrEmpty
124+
$out.resources[0].properties.port[0] | Should -Be 22
125+
$out.resources[0].properties.passwordauthentication | Should -BeNullOrEmpty
126+
$out.resources[0].properties._inheritedDefaults | Should -BeNullOrEmpty
127+
} else {
128+
$out.results.count | Should -Be 1
129+
$out.results.result.actualState | Should -Not -BeNullOrEmpty
130+
$out.results.result.actualState.port | Should -Be 22
131+
$out.results.result.actualState.passwordAuthentication | Should -Be 'yes'
132+
$out.results.result.actualState._inheritedDefaults | Should -Not -Contain 'port'
133+
}
134+
}
135+
}
136+
}

sshdconfig/Cargo.lock

Lines changed: 57 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sshdconfig/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ rust-i18n = { version = "3.1" }
2121
schemars = "1.0"
2222
serde = { version = "1.0", features = ["derive"] }
2323
serde_json = { version = "1.0", features = ["preserve_order"] }
24+
tempfile = "3.8"
2425
thiserror = { version = "2.0" }
2526
tracing = "0.1.37"
2627
tracing-subscriber = { version = "0.3.17", features = ["ansi", "env-filter", "json"] }

sshdconfig/locales/en-us.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
_version = 1
22

33
[args]
4+
getInput = "input to get for sshd_config or default shell settings"
5+
exportInput = "input to export from sshd_config"
46
setInput = "input to set in sshd_config"
57

68
[error]
79
command = "Command"
810
invalidInput = "Invalid Input"
11+
io = "IO"
912
json = "JSON"
1013
language = "Language"
11-
notImplemented = "Not Implemented"
1214
parser = "Parser"
1315
parseInt = "Parse Integer"
16+
persist = "Persist"
1417
registry = "Registry"
1518

1619
[get]
@@ -19,11 +22,11 @@ defaultShellCmdOptionMustBeString = "cmdOption must be a string"
1922
defaultShellEscapeArgsMustBe0Or1 = "'%{input}' must be a 0 or 1"
2023
defaultShellEscapeArgsMustBeDWord = "escapeArguments must be a DWord"
2124
defaultShellMustBeString = "shell must be a string"
22-
notImplemented = "get not yet implemented for Microsoft.OpenSSH.SSHD/sshd_config"
25+
traceInput = "Get input:"
2326
windowsOnly = "Microsoft.OpenSSH.SSHD/Windows is only applicable to Windows"
2427

2528
[main]
26-
export = "Export"
29+
export = "Export command: %{input}"
2730
schema = "Schema command:"
2831
set = "Set command: '%{input}'"
2932

@@ -51,5 +54,9 @@ shellPathDoesNotExist = "shell path does not exist: '%{shell}'"
5154
shellPathMustNotBeRelative = "shell path must not be relative"
5255

5356
[util]
57+
includeDefaultsMustBeBoolean = "_includeDefaults must be true or false"
58+
inputMustBeEmpty = "get command does not support filtering based on input settings"
59+
sshdConfigNotFound = "sshd_config not found at path: '%{path}'"
60+
sshdConfigReadFailed = "failed to read sshd_config at path: '%{path}'"
5461
sshdElevation = "elevated security context required"
5562
tracingInitError = "Failed to initialize tracing"

sshdconfig/src/args.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ pub struct Args {
1414

1515
#[derive(Subcommand)]
1616
pub enum Command {
17-
/// Get default shell, eventually to be used for `sshd_config` and repeatable keywords
17+
/// Get default shell and `sshd_config`, eventually to be used for repeatable keywords
1818
Get {
19+
#[clap(short = 'i', long, help = t!("args.getInput").to_string())]
20+
input: Option<String>,
1921
#[clap(short = 's', long, hide = true)]
2022
setting: Setting,
2123
},
@@ -24,8 +26,11 @@ pub enum Command {
2426
#[clap(short = 'i', long, help = t!("args.setInput").to_string())]
2527
input: String
2628
},
27-
/// Export `sshd_config`
28-
Export,
29+
/// Export `sshd_config`, eventually to be used for repeatable keywords
30+
Export {
31+
#[clap(short = 'i', long, help = t!("args.exportInput").to_string())]
32+
input: Option<String>
33+
},
2934
Schema {
3035
// Used to inform which schema to generate
3136
#[clap(short = 's', long, hide = true)]

sshdconfig/src/error.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
use rust_i18n::t;
5+
use tempfile::PersistError;
56
use thiserror::Error;
67

78
#[derive(Debug, Error)]
@@ -10,16 +11,18 @@ pub enum SshdConfigError {
1011
CommandError(String),
1112
#[error("{t}: {0}", t = t!("error.invalidInput"))]
1213
InvalidInput(String),
14+
#[error("{t}: {0}", t = t!("error.io"))]
15+
IOError(#[from] std::io::Error),
1316
#[error("{t}: {0}", t = t!("error.json"))]
1417
Json(#[from] serde_json::Error),
1518
#[error("{t}: {0}", t = t!("error.language"))]
1619
LanguageError(#[from] tree_sitter::LanguageError),
17-
#[error("{t}: {0}", t = t!("error.notImplemented"))]
18-
NotImplemented(String),
1920
#[error("{t}: {0}", t = t!("error.parser"))]
2021
ParserError(String),
2122
#[error("{t}: {0}", t = t!("error.parseInt"))]
2223
ParseIntError(#[from] std::num::ParseIntError),
24+
#[error("{t}: {0}", t = t!("error.persist"))]
25+
PersistError(#[from] PersistError),
2326
#[cfg(windows)]
2427
#[error("{t}: {0}", t = t!("error.registry"))]
2528
RegistryError(#[from] registry_lib::error::RegistryError),

sshdconfig/src/export.rs

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)