Skip to content

Commit e085f69

Browse files
committed
copy sshdconfig files from main
1 parent cd13485 commit e085f69

21 files changed

+2195
-0
lines changed

sshdconfig/Cargo.lock

Lines changed: 865 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sshdconfig/Cargo.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "sshdconfig"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[profile.release]
7+
strip = true
8+
# optimize for size
9+
opt-level = 2
10+
# enable link time optimization to remove dead code
11+
lto = true
12+
13+
[profile.dev]
14+
lto = true
15+
16+
[dependencies]
17+
atty = { version = "0.2" }
18+
chrono = { version = "0.4" }
19+
serde = { version = "1.0", features = ["derive"] }
20+
serde_json = { version = "1.0", features = ["preserve_order"] }
21+
thiserror = { version = "2.0" }
22+
tracing = "0.1.37"
23+
tracing-subscriber = "0.3.17"
24+
tree-sitter = "0.25"
25+
tree-sitter-rust = "0.24"
26+
tree-sitter-ssh-server-config = { path = "./tree-sitter-ssh-server-config" }
27+
28+
[build-dependencies]
29+
cc="*"

sshdconfig/build.ps1

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
param(
5+
[switch]$Release,
6+
[ValidateSet('current','aarch64-pc-windows-msvc','x86_64-pc-windows-msvc','aarch64-apple-darwin','x86_64-apple-darwin','aarch64-unknown-linux-gnu','aarch64-unknown-linux-musl','x86_64-unknown-linux-gnu','x86_64-unknown-linux-musl')]
7+
$architecture = 'current',
8+
[switch]$Clippy,
9+
[switch]$Test
10+
)
11+
12+
## Test if Rust is installed
13+
if (!(Get-Command 'cargo' -ErrorAction Ignore)) {
14+
Write-Verbose -Verbose "Rust not found, installing..."
15+
if (!$IsWindows) {
16+
curl https://sh.rustup.rs -sSf | sh
17+
}
18+
else {
19+
Invoke-WebRequest 'https://static.rust-lang.org/rustup/dist/i686-pc-windows-gnu/rustup-init.exe' -OutFile 'temp:/rustup-init.exe'
20+
Write-Verbose -Verbose "Use the default settings to ensure build works"
21+
& 'temp:/rustup-init.exe'
22+
Remove-Item temp:/rustup-init.exe -ErrorAction Ignore
23+
}
24+
}
25+
26+
$BuildToolsPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC"
27+
28+
function Find-LinkExe {
29+
try {
30+
# this helper may not be needed anymore, but keeping in case the install doesn't work for everyone
31+
Write-Verbose -Verbose "Finding link.exe"
32+
Push-Location $BuildToolsPath
33+
Set-Location "$(Get-ChildItem -Directory | Sort-Object name -Descending | Select-Object -First 1)\bin\Host$($env:PROCESSOR_ARCHITECTURE)\x64" -ErrorAction Stop
34+
$linkexe = (Get-Location).Path
35+
Write-Verbose -Verbose "Using $linkexe"
36+
$linkexe
37+
}
38+
finally {
39+
Pop-Location
40+
}
41+
}
42+
43+
if ($IsWindows -and !(Get-Command 'link.exe' -ErrorAction Ignore)) {
44+
if (!(Test-Path $BuildToolsPath)) {
45+
Write-Verbose -Verbose "link.exe not found, installing C++ build tools"
46+
Invoke-WebRequest 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutFile 'temp:/vs_buildtools.exe'
47+
$arg = @('--passive','--add','Microsoft.VisualStudio.Workload.VCTools','--includerecommended')
48+
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
49+
$arg += '--add','Microsoft.VisualStudio.Component.VC.Tools.ARM64'
50+
}
51+
Start-Process -FilePath 'temp:/vs_buildtools.exe' -ArgumentList $arg -Wait
52+
Remove-Item temp:/vs_installer.exe -ErrorAction Ignore
53+
Write-Verbose -Verbose "Updating env vars"
54+
$machineEnv = [environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::Machine).Split(';')
55+
$userEnv = [environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::User).Split(';')
56+
$pathEnv = ($env:PATH).Split(';')
57+
foreach ($env in $machineEnv) {
58+
if ($pathEnv -notcontains $env) {
59+
$pathEnv += $env
60+
}
61+
}
62+
foreach ($env in $userEnv) {
63+
if ($pathEnv -notcontains $env) {
64+
$pathEnv += $env
65+
}
66+
}
67+
$env:PATH = $pathEnv -join ';'
68+
}
69+
70+
#$linkexe = Find-LinkExe
71+
#$env:PATH += ";$linkexe"
72+
}
73+
74+
## Create the output folder
75+
$configuration = $Release ? 'release' : 'debug'
76+
$flags = @($Release ? '-r' : $null)
77+
if ($architecture -eq 'current') {
78+
$path = ".\target\$configuration"
79+
$target = Join-Path $PSScriptRoot 'bin' $configuration
80+
}
81+
else {
82+
$flags += '--target'
83+
$flags += $architecture
84+
$path = ".\target\$architecture\$configuration"
85+
$target = Join-Path $PSScriptRoot 'bin' $architecture $configuration
86+
}
87+
88+
if (Test-Path $target) {
89+
Remove-Item $target -Recurse -ErrorAction Stop
90+
}
91+
New-Item -ItemType Directory $target > $null
92+
93+
$failed = $false
94+
$project = 'tree-sitter-ssh-server-config'
95+
Write-Host -ForegroundColor Cyan "Building $project ... for $architecture"
96+
try {
97+
Push-Location "$PSScriptRoot/$project" -ErrorAction Stop
98+
./build.ps1
99+
if ($LASTEXITCODE -ne 0) {
100+
$failed = $true
101+
}
102+
} finally {
103+
Pop-Location
104+
}
105+
106+
if ($failed) {
107+
Write-Host -ForegroundColor Red "Tree-sitter build failed"
108+
exit 1
109+
}
110+
111+
## Build format_json
112+
Write-Host -ForegroundColor Cyan "Building sshdconfig ... for $architecture"
113+
try {
114+
Push-Location "$PSScriptRoot" -ErrorAction Stop
115+
if (Test-Path "./Cargo.toml")
116+
{
117+
if ($Clippy) {
118+
Write-Verbose -Verbose "Running clippy with pedantic for sshdconfig"
119+
cargo clippy @flags --% -- -Dwarnings -Dclippy::pedantic
120+
}
121+
else {
122+
cargo build @flags
123+
}
124+
}
125+
if ($LASTEXITCODE -ne 0) {
126+
$failed = $true
127+
}
128+
if ($IsWindows) {
129+
Copy-Item "$path/sshdconfig.exe" $target -ErrorAction Ignore
130+
}
131+
else {
132+
Copy-Item "$path/sshdconfig" $target -ErrorAction Ignore
133+
}
134+
Copy-Item "*.dsc.resource.json" $target -Force -ErrorAction Ignore
135+
Copy-Item "*.resource.ps1" $target -Force -ErrorAction Ignore
136+
Copy-Item "*.command.json" $target -Force -ErrorAction Ignore
137+
} finally {
138+
Pop-Location
139+
}
140+
141+
if ($failed) {
142+
Write-Host -ForegroundColor Red "Build failed"
143+
exit 1
144+
}
145+
146+
Copy-Item $PSScriptRoot/tools/add-path.ps1 $target -Force -ErrorAction Ignore
147+
148+
$relative = Resolve-Path $target -Relative
149+
Write-Host -ForegroundColor Green "`nEXE's are copied to $target ($relative)"
150+
151+
$paths = $env:PATH.Split([System.IO.Path]::PathSeparator)
152+
$found = $false
153+
foreach ($path in $paths) {
154+
if ($path -eq $target) {
155+
$found = $true
156+
break
157+
}
158+
}
159+
160+
# remove the other target in case switching between them
161+
if ($Release) {
162+
$oldTarget = $target.Replace('\release', '\debug')
163+
}
164+
else {
165+
$oldTarget = $target.Replace('\debug', '\release')
166+
}
167+
$env:PATH = $env:PATH.Replace(';' + $oldTarget, '')
168+
169+
if (!$found) {
170+
Write-Host -ForegroundCOlor Yellow "Adding $target to `$env:PATH"
171+
$env:PATH += [System.IO.Path]::PathSeparator + $target
172+
}
173+
174+
if ($Test) {
175+
$failed = $false
176+
177+
$FullyQualifiedName = @{ModuleName="PSDesiredStateConfiguration";ModuleVersion="2.0.7"}
178+
if (-not(Get-Module -ListAvailable -FullyQualifiedName $FullyQualifiedName))
179+
{ "Installing module PSDesiredStateConfiguration 2.0.7"
180+
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
181+
Install-Module PSDesiredStateConfiguration -RequiredVersion 2.0.7
182+
}
183+
184+
if (-not(Get-Module -ListAvailable -Name Pester))
185+
{ "Installing module Pester"
186+
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
187+
Install-Module Pester -WarningAction Ignore
188+
}
189+
190+
"For debug - env:PATH is:"
191+
$env:PATH
192+
193+
## Build format_json
194+
Write-Host -ForegroundColor Cyan "Testing sshdconfig ..."
195+
try {
196+
Push-Location "$PSScriptRoot"
197+
if (Test-Path "./Cargo.toml")
198+
{
199+
if (Test-Path "./Cargo.toml")
200+
{
201+
cargo test
202+
203+
if ($LASTEXITCODE -ne 0) {
204+
$failed = $true
205+
}
206+
}
207+
}
208+
} finally {
209+
Pop-Location
210+
}
211+
212+
if ($failed) {
213+
throw "Test failed"
214+
}
215+
216+
"PSModulePath is:"
217+
$env:PSModulePath
218+
"Pester module located in:"
219+
(Get-Module -Name Pester -ListAvailable).Path
220+
221+
# On Windows disable duplicated WinPS resources that break PSDesiredStateConfiguration module
222+
if ($IsWindows) {
223+
$a = $env:PSModulePath -split ";" | ? { $_ -notmatch 'WindowsPowerShell' }
224+
$env:PSModulePath = $a -join ';'
225+
226+
"Updated PSModulePath is:"
227+
$env:PSModulePath
228+
229+
if (-not(Get-Module -ListAvailable -Name Pester))
230+
{ "Installing module Pester"
231+
$InstallTargetDir = ($env:PSModulePath -split ";")[0]
232+
Find-Module -Name 'Pester' -Repository 'PSGallery' | Save-Module -Path $InstallTargetDir
233+
}
234+
235+
"Updated Pester module location:"
236+
(Get-Module -Name Pester -ListAvailable).Path
237+
}
238+
239+
Invoke-Pester -ErrorAction Stop
240+
}
241+
242+
$env:RUST_BACKTRACE=1

sshdconfig/src/error.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use thiserror::Error;
5+
6+
#[derive(Debug, Error)]
7+
pub enum SshdConfigError {
8+
#[error("Command: {0}")]
9+
CommandError(String),
10+
#[error("JSON: {0}")]
11+
Json(#[from] serde_json::Error),
12+
#[error("Language: {0}")]
13+
LanguageError(#[from] tree_sitter::LanguageError),
14+
#[error("Parser: {0}")]
15+
ParserError(String),
16+
#[error("Parser Int: {0}")]
17+
ParseIntError(#[from] std::num::ParseIntError),
18+
}

sshdconfig/src/export.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::error::SshdConfigError;
5+
use crate::parser::parse_text_to_map;
6+
use crate::util::invoke_sshd_config_validation;
7+
8+
/// Invoke the export command.
9+
///
10+
/// # Errors
11+
///
12+
/// This function will return an error if the command cannot invoke sshd -T, parse the return, or convert it to json.
13+
pub fn invoke_export() -> Result<String, SshdConfigError> {
14+
let sshd_config_text = invoke_sshd_config_validation()?;
15+
let sshd_config: serde_json::Map<String, serde_json::Value> = parse_text_to_map(&sshd_config_text)?;
16+
let json = serde_json::to_string_pretty(&sshd_config)?;
17+
Ok(json)
18+
}

sshdconfig/src/main.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::export::invoke_export;
5+
6+
mod error;
7+
mod export;
8+
mod metadata;
9+
mod parser;
10+
mod util;
11+
12+
fn main() {
13+
// only supports export for sshdconfig for now
14+
match invoke_export() {
15+
Ok(result) => {
16+
println!("{result}");
17+
}
18+
Err(e) => {
19+
eprintln!("Error exporting SSHD config: {e:?}");
20+
}
21+
}
22+
}

sshdconfig/src/metadata.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
// TODO: ensure lists are complete
5+
6+
// keywords that can be repeated over multiple lines and should be represented as arrays
7+
pub const REPEATABLE_KEYWORDS: [&str; 6] = [
8+
"hostkey",
9+
"include",
10+
"listenaddress",
11+
"port",
12+
"setenv",
13+
"subsystem"
14+
];
15+
16+
// keywords that can have multiple argments per line and should be represented as arrays
17+
// but cannot be repeated over multiple lines, as subsequent entries are ignored
18+
pub const MULTI_ARG_KEYWORDS: [&str; 7] = [
19+
"casignaturealgorithms",
20+
"ciphers",
21+
"hostbasedacceptedalgorithms",
22+
"hostkeyalgorithms",
23+
"kexalgorithms",
24+
"macs",
25+
"pubkeyacceptedalgorithms"
26+
];

0 commit comments

Comments
 (0)