Johdanto
Monessa yritysympäristössä Linux-palvelimet pyörittävät kriittisiä palveluita, mutta ylläpitäjien työasema on edelleen Windows. Tämä yhdistelmä luo tarpeen tehokkaalle ja automatisoidulle tavalle kerätä tietoa Linux-palvelimilta ilman jatkuvaa manuaalista SSH-kirjautumista. Kerättyä tietoa voidaan visualisoida raporttina vaikkapa html-tiedostona, joka avautuu selaimeen luettavaan muotoon kätevästi.


Yksi käytännöllisimmistä ratkaisuista tähän on käyttää PowerShelliä yhdessä PuTTY-paketin mukana tulevan Plink-ohjelman kanssa. Plink.exe mahdollistaa SSH-komentojen suorittamisen komentoriviltä, jolloin PowerShell-skripteillä voidaan automatisoida esimerkiksi palvelinten tilatietojen keräys, levytilan tarkistus, lokien lukeminen tai ohjelmistoversioiden inventointi.
Tässä artikkelissa käydään läpi, kuinka Windows-työpöydältä voidaan hallita ja kerätä tietoa Linux-palvelimista PowerShellin avulla käyttäen Plink.exe-ohjelmaa. Samalla tarkastellaan turvallisia käytäntöjä, automaation hyötyjä sekä esimerkkiskriptejä päivittäiseen ylläpitotyöhön.
Artikkeli sopii erityisesti järjestelmävalvojille, DevOps-asiantuntijoille sekä IT-ympäristöjen ylläpitäjille, jotka haluavat yhdistää Windowsin hallintatyökalut Linux-palvelimien tehokkaaseen etähallintaan.
Turvallisuus ennen kaikkea
Kun Linux-palvelimia hallitaan automaattisesti Windows-työasemalta, turvallisuus nousee nopeasti tärkeimmäksi asiaksi. Yksi yleisimmistä virheistä on tallentaa palvelimien salasanat suoraan skripteihin tai tekstitiedostoihin. Tämä tekee ympäristöstä erittäin haavoittuvan.
PowerShellin ja Plink.exe:n yhdistelmässä turvallisuus voidaan kuitenkin toteuttaa huomattavasti paremmin käyttämällä salattuja salasanoja ja erillistä AES-avainta.
Tehdään uusi skripti: luo_lista_linux_palvelimista.ps1
#=============================================================
# luo_lista_linux_palvelimista.ps1 (AES-versio)
# - Luo aes.key (jos puuttuu)
# - Luo servers.cfg
# - Luo palvelinkohtaiset AES-salatut salasanat: pwd-<host>.enc
#=============================================================
Write-Host "=== Linux-hallinnan AES-asetustyokalu ===" -ForegroundColor Cyan
#-------------------------------------------------------------
# 1) Varmista AES-avain
#-------------------------------------------------------------
function Ensure-AesKey {
if (Test-Path "aes.key") {
Write-Verbose "aes.key loytyy."
return
}
Write-Host "aes.key puuttuu, luodaan uusi 256-bit AES-avain..." -ForegroundColor Yellow
$bytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
[Convert]::ToBase64String($bytes) | Set-Content -Path "aes.key" -Encoding ASCII
Write-Host "AES-avain luotu tiedostoon aes.key" -ForegroundColor Green
}
#-------------------------------------------------------------
# 2) Palvelinkohtaisen salasanan salaus AES:lla
#-------------------------------------------------------------
function New-ServerPasswordFile {
param(
[string]$ServerName
)
if (-not (Test-Path "aes.key")) {
Write-Error "aes.key puuttuu. Aja Ensure-AesKey ensin."
return $null
}
$key = [Convert]::FromBase64String((Get-Content aes.key -Raw))
Write-Host ""
Write-Host "Luo salasana palvelimelle: $ServerName" -ForegroundColor Yellow
$sec = Read-Host "Anna salasana palvelimelle $ServerName" -AsSecureString
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec)
$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) | Out-Null
$bytes = [Text.Encoding]::UTF8.GetBytes($plain)
$aes = [System.Security.Cryptography.Aes]::Create()
$aes.Key = $key
$aes.GenerateIV()
$enc = $aes.CreateEncryptor().TransformFinalBlock($bytes,0,$bytes.Length)
$out = [Convert]::ToBase64String($aes.IV) + ":" + [Convert]::ToBase64String($enc)
$fileName = "pwd-$ServerName.enc"
Set-Content -Path $fileName -Value $out -Encoding ASCII
Write-Host "Salasana tallennettu: $fileName" -ForegroundColor Green
return $fileName
}
#-------------------------------------------------------------
# 3) Luo servers.cfg
#-------------------------------------------------------------
function Create-ServersCfg {
Ensure-AesKey
Write-Host ""
Write-Host "Luodaan servers.cfg" -ForegroundColor Yellow
$count = Read-Host "Kuinka monta palvelinta haluat lisata?"
if (-not ($count -as [int])) {
Write-Error "Anna numero."
return
}
$servers = @()
for ($i = 1; $i -le $count; $i++) {
Write-Host ""
Write-Host "Palvelin $i / $count" -ForegroundColor Cyan
$srvHost = Read-Host "IP-osoite tai hostname"
$srvPort = Read-Host "SSH-portti (oletus 22)"
if (-not $srvPort) { $srvPort = 22 }
$srvUser = Read-Host "Kayttaja (oletus root)"
if (-not $srvUser) { $srvUser = "root" }
$auth = Read-Host "AuthMethod (password / key-auth)"
if ($auth -ne "password" -and $auth -ne "key-auth") {
$auth = "password"
}
$pwdFile = ""
if ($auth -eq "password") {
$pwdFile = New-ServerPasswordFile -ServerName $srvHost
}
$servers += [pscustomobject]@{
Host = $srvHost
Port = $srvPort
User = $srvUser
AuthMethod = $auth
PasswordFile = $pwdFile
}
}
$servers | Export-Csv -Path "servers.cfg" -NoTypeInformation -Encoding UTF8
Write-Host ""
Write-Host "servers.cfg luotu onnistuneesti." -ForegroundColor Green
}
#-------------------------------------------------------------
# 4) Valikko
#-------------------------------------------------------------
Write-Host ""
Write-Host "Valitse toiminto:" -ForegroundColor Cyan
Write-Host "1) Luo aes.key (jos puuttuu) ja servers.cfg + salasanat"
Write-Host "2) Vain servers.cfg + salasanat (aes.key jo olemassa)"
Write-Host "3) Luo/paivita vain salasanat olemassa olevaan servers.cfg:hen"
$choice = Read-Host "Valinta"
switch ($choice) {
"1" {
Ensure-AesKey
Create-ServersCfg
}
"2" {
Create-ServersCfg
}
"3" {
if (-not (Test-Path "servers.cfg")) {
Write-Error "servers.cfg puuttuu."
break
}
Ensure-AesKey
$cfg = Import-Csv "servers.cfg"
foreach ($srv in $cfg) {
if ($srv.AuthMethod -eq "password") {
$file = New-ServerPasswordFile -ServerName $srv.Host
$srv.PasswordFile = $file
}
}
$cfg | Export-Csv -Path "servers.cfg" -NoTypeInformation -Encoding UTF8
Write-Host "Salasanat paivitetty servers.cfg tiedostoon." -ForegroundColor Green
}
default {
Write-Host "Virheellinen valinta."
}
}
Write-Host ""
Write-Host "Valmis." -ForegroundColor Cyan
Esimerkkiskriptissä palvelimien tiedot tallennetaan servers.cfg-tiedostoon, mutta varsinaiset salasanat salataan AES-256 -salauksella palvelinkohtaisiin .enc-tiedostoihin. Salausavain tallennetaan erilliseen aes.key-tiedostoon, joka luodaan kryptografisesti turvallisella satunnaisgeneraattorilla.
Ratkaisun etuja ovat:
- Salasanoja ei tallenneta selväkielisinä
- Jokaisella palvelimella voi olla oma salattu tunnus
- Konfiguraatio ja salaukset ovat erotettu toisistaan
- Skriptit voidaan automatisoida ilman jatkuvaa salasanojen syöttämistä
- AES-256 tarjoaa vahvan salauksen yrityskäyttöön
Erityisen hyvä käytäntö on myös se, että skripti käyttää PowerShellin SecureString-mekanismia salasanojen käsittelyyn. Näin salasana ei näy komentorivillä eikä jää helposti muistiin luettavassa muodossa.
Miksi AES-salaus on tärkeä?
Monissa vanhoissa ylläpitoskripteissä salasanat löytyvät edelleen esimerkiksi:
$password = "Salainen123"
Tämä on merkittävä tietoturvariski. Jos skripti vuotaa, hyökkääjä saa suoraan pääsyn palvelimiin.
AES-pohjaisessa ratkaisussa hyökkääjän pitäisi saada haltuunsa:
- Salattu salasana
- AES-avain
- Itse automaatioskripti
Pelkkä .enc-tiedosto ei siis yksin riitä salasanan palauttamiseen.
SSH-avaimet vai salasanat?
Vaikka AES-salatut salasanat ovat turvallinen ratkaisu, kaikkein turvallisin vaihtoehto on edelleen SSH-avainautentikointi (key-auth), jota myös esimerkkiskripti tukee.
Suositeltu käytäntö on:
- Käytä SSH-avaimia aina kun mahdollista
- Käytä salasanoja vain poikkeustapauksissa
- Säilytä
aes.keyerillään muista tiedostoista - Rajaa tiedostojen käyttöoikeudet vain ylläpitäjille
- Älä koskaan versionhallinnoi salausavaimia Git-repositorioon
Käytännön hyöty ylläpidossa
Kun palvelinympäristö kasvaa kymmeniin, satoihin tai tuhansiin Linux-palvelimiin, automatisoitu tiedonkeruu säästää huomattavasti aikaa. PowerShell voi kutsua Plink.exe:tä, suorittaa SSH-komentoja ja kerätä esimerkiksi:
- levytilan käyttöasteet
- palveluiden tilat
- käyttöjärjestelmäversiot
- päivitystilanteet
- lokivirheet
- kuormitustiedot
Kaikki tämä voidaan tehdä keskitetysti Windows-työpöydältä ilman manuaalista kirjautumista jokaiselle palvelimelle erikseen.
Juuri tässä PowerShellin vahvuus näkyy: Windows-ympäristön automaatio voidaan yhdistää Linux-maailman tehokkaisiin komentorivityökaluihin turvallisesti ja hallitusti.
Tehdään uusi skripti: hae_tietoa_linux_palvelimista.ps1
#=============================================================
# hae_tietoa_linux_palvelimista.ps1 (AES + plink + silent hostkey + colors)
#=============================================================
function HtmlEscape {
param([string]$text)
if (-not $text) { return "" }
$text = $text.Replace("&", "&")
$text = $text.Replace("<", "<")
$text = $text.Replace(">", ">")
$text = $text.Replace('"', """)
$text = $text.Replace("'", "'")
return $text
}
$DebugPreference = "SilentlyContinue"
$VerbosePreference = "SilentlyContinue"
function Color([string]$Text, [string]$Color="White") {
Write-Host $Text -ForegroundColor $Color
}
Color "=== hae_tietoa_linux_palvelimista.ps1 kaynnistyy $(Get-Date) ===" Cyan
#-------------------------------------------------------------
# 1) Lataa AES-avain
#-------------------------------------------------------------
$aesKeyPath = Join-Path $PSScriptRoot "aes.key"
if (-not (Test-Path $aesKeyPath)) {
Color "aes.key puuttuu. Aja luo_lista_linux_palvelimista.ps1 ensin." Red
exit 1
}
$aesKey = [Convert]::FromBase64String((Get-Content $aesKeyPath -Raw))
#-------------------------------------------------------------
# 2) AES-salasanan purku
#-------------------------------------------------------------
function Decrypt-AES {
param([string]$File)
if (-not (Test-Path $File)) {
Color "Salasanatiedosto puuttuu: $File" Red
return $null
}
$raw = Get-Content $File -Raw
$parts = $raw.Split(":")
if ($parts.Count -ne 2) {
Color "Virheellinen AES-salasanatiedosto: $File" Red
return $null
}
$iv = [Convert]::FromBase64String($parts[0])
$enc = [Convert]::FromBase64String($parts[1])
$aes = [System.Security.Cryptography.Aes]::Create()
$aes.Key = $aesKey
$aes.IV = $iv
try {
$plainBytes = $aes.CreateDecryptor().TransformFinalBlock($enc,0,$enc.Length)
return [Text.Encoding]::UTF8.GetString($plainBytes)
}
catch {
Color "AES-salasanan purku epaonnistui tiedostosta: $File" Red
return $null
}
}
#-------------------------------------------------------------
# 3) Lataa servers.cfg
#-------------------------------------------------------------
$cfgPath = Join-Path $PSScriptRoot "servers.cfg"
if (-not (Test-Path $cfgPath)) {
Color "servers.cfg puuttuu." Red
exit 1
}
$servers = Import-Csv $cfgPath
Color "Ladattiin palvelimia: $($servers.Count)" Yellow
#-------------------------------------------------------------
# 4) Komennot
#-------------------------------------------------------------
$cmds = @(
"uptime",
"uname -r",
"cat /etc/os-release",
"free -h",
"swapon -s",
"df -h",
"grep -i error /var/log/syslog | tail -n 20"
)
#-------------------------------------------------------------
# 5) Hyväksy host key täysin hiljaisesti
#-------------------------------------------------------------
function Accept-HostKey {
param(
[string]$ServerHost,
[int]$Port,
[string]$User,
[string]$Password
)
$plink = "C:\Program Files\PuTTY\plink.exe"
if (-not (Test-Path $plink)) { return }
# Täysin hiljainen host key accept
$cmd = "echo y | `"$plink`" -ssh -pw $Password -P $Port -batch $User@$ServerHost exit"
cmd.exe /c $cmd | Out-Null
}
#-------------------------------------------------------------
# 6) Suorita
#-------------------------------------------------------------
$allResults = foreach ($srv in $servers) {
$srvHost = $srv.Host
$port = $srv.Port
$user = $srv.User
$auth = $srv.AuthMethod
$pwdFile = $srv.PasswordFile
Color ""
Color "=== Yhteys: $srvHost (auth=$auth) ===" Cyan
$plainPwd = $null
if ($auth -eq "password") {
$plainPwd = Decrypt-AES $pwdFile
}
# Hyväksy host key automaattisesti
if ($auth -eq "password") {
Accept-HostKey -ServerHost $srvHost -Port $port -User $user -Password $plainPwd
}
foreach ($c in $cmds) {
Color " -> Suoritetaan: $c" DarkGray
$plink = "C:\Program Files\PuTTY\plink.exe"
if ($auth -eq "password") {
$plinkArgs = @(
"-pw", $plainPwd,
"-P", $port,
"-batch",
"$user@$srvHost",
$c
)
$out = & $plink $plinkArgs 2>&1
}
else {
$sshArgs = @(
"-i", "$HOME\.ssh\id_rsa",
"-p", $port,
"-o", "StrictHostKeyChecking=no",
"-o", "BatchMode=yes",
"$user@$srvHost",
$c
)
$out = & ssh.exe $sshArgs 2>&1
}
$success = -not ($out -match "ERROR|Permission denied")
if ($success) {
Color " [OK]" Green
} else {
Color " [VIRHE]" Red
}
[pscustomobject]@{
Host = $srvHost
Command = $c
Output = ($out -join "`n").Trim()
Success = $success
Auth = $auth
}
}
}
#-------------------------------------------------------------
# 7) Raportti
#-------------------------------------------------------------
$csvPath = Join-Path $PSScriptRoot "LinuxInfoReport.csv"
$allResults | Export-Csv $csvPath -NoTypeInformation -Encoding UTF8
Color ""
Color "Raportti tallennettu: $csvPath" Green
Color "=== Valmis $(Get-Date) ===" Cyan
#-------------------------------------------------------------
# 8) HTML-raportti (ASCII-safe, PS 5.1 compatible)
#-------------------------------------------------------------
# HTML-template here-string (ASCII only)
$htmlTemplate = @"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Linux Dashboard</title>
<style>
body {
background-color: #1e1e1e;
color: #e0e0e0;
font-family: Consolas, monospace;
margin: 20px;
}
h1 {
color: #4fc3f7;
}
.server-box {
background-color: #2b2b2b;
padding: 15px;
margin-bottom: 20px;
border-radius: 8px;
}
.command {
background-color: #333;
padding: 10px;
margin-top: 10px;
border-radius: 6px;
}
.success {
color: #00e676;
font-weight: bold;
}
.fail {
color: #ff5252;
font-weight: bold;
}
details {
margin-top: 5px;
}
summary {
cursor: pointer;
color: #4fc3f7;
font-weight: bold;
}
pre {
white-space: pre-wrap;
background-color: #111;
padding: 10px;
border-radius: 6px;
color: #cfcfcf;
}
</style>
</head>
<body>
<h1>Linux Dashboard</h1>
{{CONTENT}}
</body>
</html>
"@
# Luo HTML-sisalto
$sections = ""
foreach ($srv in $servers) {
$srvHost = $srv.Host
$sections += "<div class='server-box'>`n"
$sections += "<h2>Palvelin: $srvHost</h2>`n"
$srvResults = $allResults | Where-Object { $_.Host -eq $srvHost }
foreach ($r in $srvResults) {
$statusClass = if ($r.Success) { "success" } else { "fail" }
$statusText = if ($r.Success) { "OK" } else { "VIRHE" }
$sections += "<div class='command'>`n"
$sections += "<span class='$statusClass'>$statusText</span> - <b>$($r.Command)</b><br>`n"
# HTML-escape output
$escaped = HtmlEscape $r.Output
$sections += "<details><summary>Nayta tulos</summary>`n"
$sections += "<pre>$escaped</pre>`n"
$sections += "</details>`n"
$sections += "</div>`n"
}
$sections += "</div>`n"
}
# Korvaa placeholder
$html = $htmlTemplate.Replace("{{CONTENT}}", $sections)
# Tallenna HTML
$outFile = Join-Path $PSScriptRoot "LinuxDashboard.html"
Set-Content -Path $outFile -Value $html -Encoding UTF8
Color "HTML dashboard tallennettu: $outFile" Green
Keskitetty tiedonkeruu useilta Linux-palvelimilta
Kun palvelimien konfigurointi ja turvallinen tunnusten hallinta on toteutettu, seuraava askel on automatisoitu tiedonkeruu. Tässä vaiheessa PowerShellin ja Plink-ohjelman yhdistelmä näyttää todellisen voimansa.
Esimerkkiskripti hae_tietoa_linux_palvelimista.ps1 käy automaattisesti läpi kaikki servers.cfg-tiedostossa määritellyt Linux-palvelimet, muodostaa SSH-yhteyden ja suorittaa ennalta määritellyt komennot. Tulokset kerätään keskitetysti sekä CSV– että HTML-raporteiksi.
Tämä mahdollistaa käytännössä oman kevyen valvonta- ja inventointijärjestelmän rakentamisen ilman raskaita kaupallisia ratkaisuja.
Mitä tietoa palvelimilta voidaan kerätä?
Skriptissä suoritetaan esimerkiksi seuraavia Linux-komentoja:
uptime
uname -r
free -h
df -h
cat /etc/os-release
Näillä voidaan kerätä:
- palvelimen uptime
- kernel-versio
- käyttöjärjestelmän tiedot
- muistin käyttö
- swap-tila
- levytilan käyttöaste
- lokien virheilmoituksia
Koska komennot määritellään taulukkoon ($cmds), uusia tarkistuksia voidaan lisätä helposti ilman suuria muutoksia itse skriptiin.
CSV-raportit jatkokäsittelyyn
Kaikki kerätty tieto tallennetaan automaattisesti CSV-muotoon:
$allResults | Export-Csv LinuxInfoReport.csv
CSV-raporttia voidaan hyödyntää esimerkiksi:
- Excel-analyysissä
- Power BI -raportoinnissa
- historiatietojen vertailussa
- kapasiteettiseurannassa
- automaattisissa hälytyksissä
Tämä tekee ratkaisusta erittäin joustavan yritysympäristöihin.
HTML-dashboard yhdellä skriptillä
Yksi mielenkiintoisimmista ominaisuuksista on automaattinen HTML-dashboardin generointi.
Skripti rakentaa modernin selainpohjaisen raportin, jossa:
- jokainen palvelin näkyy omana osionaan
- komentojen tulokset voidaan avata ja sulkea
- onnistuneet ja epäonnistuneet komennot erotellaan väreillä
- virhelokit näkyvät helposti luettavassa muodossa
Käytännössä tämä tarkoittaa sitä, että ylläpitäjä voi avata raportin selaimella ja tarkastaa koko Linux-ympäristön tilanteen yhdellä näkymällä.
Turvallisuus myös tiedonkeruussa
Esimerkkiskriptissä turvallisuuteen on kiinnitetty huomiota myös tiedonkeruun aikana.
Tärkeitä ratkaisuja ovat esimerkiksi:
- AES-salattujen salasanojen käyttö
- SSH BatchMode automaatiossa
- host key -hallinta
- SecureString-käsittely
- virheiden tunnistus (
Permission denied,ERROR) - HTML-escaping raporttigeneroinnissa
Erityisen tärkeä yksityiskohta on HtmlEscape-funktio. Sen avulla Linux-palvelimilta tuleva sisältö muunnetaan turvalliseen HTML-muotoon ennen raportin generointia. Tämä estää mahdolliset HTML- tai script-injektiot raporttinäkymään.
Skaalautuva ratkaisu ylläpitoon
Tämän tyyppinen ratkaisu toimii hyvin pienissä ympäristöissä, mutta skaalautuu myös suuriin palvelinympäristöihin. Samalla skriptillä voidaan hallita:
- 5 palvelinta
- 50 palvelinta
- satoja/tuhansia Linux-koneita
Koska kaikki perustuu PowerShelliin ja SSH-yhteyksiin, ratkaisu ei vaadi raskaita agentteja tai erillisiä hallintapalvelimia.
Yhteenveto
PowerShell ja Plink tarjoavat erittäin tehokkaan tavan automatisoida Linux-palvelimien tiedonkeruuta Windows-ympäristöstä käsin.
Kun mukaan yhdistetään:
- AES-salatut tunnukset
- keskitetty palvelinkonfiguraatio
- automaattinen raportointi
- HTML-dashboardit
- SSH-automaatiot
saadaan kevyt mutta erittäin tehokas ylläpitoratkaisu, joka soveltuu niin pienille IT-ympäristöille kuin suuremmillekin palvelininfrastruktuureille.
Jatkokehitysajatukset
Onko mahdollista antaa “pääsalasanaa”, jolla AES key tiedoston voisi kryptata?
Nykyisessä mallissa aes.key toimii käytännössä “master keynä”. Jos hyökkääjä saa haltuunsa:
aes.key.enc-salasanatiedostot- skriptit
hän pystyy purkamaan kaikki tallennetut salasanat.
Siksi seuraava luonnollinen kehitysaskel on suojata itse aes.key pääsalasanalla (master password).
Pääsalasanalla suojattu AES-avain
Ajatus toimii näin:
- Käyttäjä antaa käynnistyksen yhteydessä pääsalasanan
- Pääsalasanasta johdetaan kryptografinen avain (PBKDF2)
- Tällä avaimella puretaan salattu
aes.key.enc - Varsinaisia palvelinsalasanoja voidaan käyttää vasta tämän jälkeen
Tämä vastaa käytännössä password manager -tyyppistä toimintamallia.
Miksi tämä on huomattavasti turvallisempi?
Ilman pääsalasanaa hyökkääjä ei voi käyttää:
- palvelinsalasanoja
- AES-avainta
- automaatiota
vaikka kaikki tiedostot vuotaisivat.
Tämä estää erityisesti:
- varastettujen backupien hyödyntämisen
- Git-vuodot
- tiedostopalvelinmurrot
- vahingossa jaetut skriptihakemistot
Suositeltu rakenne
Nykyinen:
aes.key
pwd-server1.enc
pwd-server2.enc
servers.cfg
Turvallisempi versio:
aes.key.enc
master.salt
pwd-server1.enc
pwd-server2.enc
servers.cfg
Tekninen toteutus PowerShellissä
Paras ratkaisu olisi käyttää:
- PBKDF2-avainjohdantoa
- SHA-256 hajautusta
- satunnaista salt-arvoa
- AES-256 salausta
PowerShell tukee näitä suoraan .NET-kirjastojen kautta.
Pääsalasana kysyttäisiin esimerkiksi:
$master = Read-Host "Anna paasalasana" -AsSecureString
ja siitä johdettaisiin avain PBKDF2:lla:
$rfc = New-Object Security.Cryptography.Rfc2898DeriveBytes(
$plainPassword,
$salt,
100000
)
100 000+ iterointia tekee brute-force -hyökkäyksistä huomattavasti hitaampia.
Miten jatkokehittää tätä tiedonkeruu järjestelmä ajatusta eteenpäin?
1. SSH-avaimet ensisijaisiksi
Paras turvallisuus saavutetaan poistamalla salasanakirjautuminen kokonaan:
- vain SSH key auth
- salasanoja ei tallenneta lainkaan
- mahdollinen passphrase SSH-avaimelle
Tämä on kaikkein turvallisin malli.
2. Keskitetty dashboard
HTML-raportti voisi muuttua oikeaksi web-dashboardiksi:
- hakutoiminnot
- palvelinkohtaiset hälytykset
- historiatiedot
- värikoodattu health status
- automaattinen refresh
Esimerkiksi:
- Flask
- PowerShell Universal
- Node.js
- Grafana
3. Ajastettu automaatio
Skripti voidaan ajaa:
- Windows Task Schedulerilla
- Jenkinsillä
- GitLab Runnerilla
- Azure Automationilla
Tällöin raportit päivittyvät automaattisesti.
4. Tietokantaintegraatio
CSV toimii hyvin aluksi, mutta myöhemmin tiedot voisi tallentaa:
- SQLite
- PostgreSQL
- MariaDB
- InfluxDB
Tällöin saadaan:
- trendiseuranta
- historiatiedot
- kapasiteettiennusteet
- SLA-raportointi
5. Hälytykset ja automaattinen valvonta
Esimerkiksi:
- levytila alle 10 %
- load average liian korkea
- swap käytössä
- lokissa ERROR-rivejä
→ automaattinen sähköposti tai Teams/Slack-ilmoitus.
6. Credential Vault -integraatio
Yritysympäristöissä seuraava iso askel olisi integroida:
- Windows Credential Manager
- HashiCorp Vault
- CyberArk
- Azure Key Vault
Tällöin salasanoja ei tarvitse säilyttää tiedostoissa lainkaan.
Lopputulos
Tässä ideassa on paljon potentiaalia. Se ei ole enää pelkkä “PowerShell-skripti”, vaan kevyt keskitetty Linux-hallintajärjestelmä Windows-ympäristöön.
Erityisen vahvoja puolia ovat:
- ei agentteja Linux-palvelimille
- toimii puhtaalla SSH:lla
- helposti laajennettava
- turvallinen AES-malli
- kevyt ylläpitää
- toimii myös suljetuissa sisäverkoissa
Ja kyllä — pääsalasanalla suojattu aes.key olisi erittäin suositeltava seuraava vaihe turvallisuuden kannalta.