Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
**Bug Fixes:**
* Add support to dynamically connect peered services based on enabled status ([#892](https://github.com/wardenenv/warden/issues/892) by @bap14, [#919](https://github.com/wardenenv/warden/issues/919) by @xinsodev)
* Fix WARDEN_DOCKER_SOCK error running `warden sign-certificate` ([#907](https://github.com/wardenenv/warden/issues/907) by @bap14)
* Automatically trust the Warden root CA in the Windows CurrentUser Root store when `warden install` is run inside WSL, allowing Windows browsers to trust local Warden certificates without manual import

## Version [0.16.0](https://github.com/wardenenv/warden/tree/0.16.0) (2026-02-12)

Expand Down
11 changes: 11 additions & 0 deletions commands/install.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ then
-k /Library/Keychains/System.keychain "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem"
fi

if hasWindowsCertificateBridge; then
echo "==> Trusting root certificate in Windows CurrentUser store"
if ! windows_trust_status="$(trustRootCaInWindows "${WARDEN_SSL_DIR}/rootca/certs/ca.cert.pem")"; then
warning "Unable to trust the Warden root certificate in Windows. Windows browsers may continue to warn until it is imported manually."
elif [[ "${windows_trust_status}" == "imported" ]]; then
echo "==> Root certificate imported into Windows CurrentUser Root store"
elif [[ "${windows_trust_status}" == "replaced" ]]; then
echo "==> Root certificate replaced in Windows CurrentUser Root store"
fi
Comment thread
ilnytskyi marked this conversation as resolved.
Outdated
fi

## configure resolver for .test domains on Mac OS only as Linux lacks support
## for BSD like per-TLD configuration as is done at /etc/resolver/test on Mac
if [[ "$OSTYPE" == "darwin"* ]]; then
Expand Down
68 changes: 68 additions & 0 deletions utils/install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,74 @@
#!/usr/bin/env bash
[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1

source "${WARDEN_DIR}/utils/core.sh"

function isWsl () {
[[ -n "${WSL_DISTRO_NAME:-}" ]] && return 0
[[ -r /proc/sys/kernel/osrelease ]] && grep -qiE '(microsoft|wsl)' /proc/sys/kernel/osrelease && return 0
[[ -r /proc/version ]] && grep -qiE '(microsoft|wsl)' /proc/version && return 0
return 1
}

function hasWindowsCertificateBridge () {
isWsl && command -v powershell.exe >/dev/null 2>&1
}

function trustRootCaInWindows () {
local cert_path="${1}"
local windows_cert_path powershell_script trust_status

[[ -f "${cert_path}" ]] || return 1

windows_cert_path="$(wslpath -w "${cert_path}")" || return 1
windows_cert_path="${windows_cert_path//\'/\'\'}"

read -r -d '' powershell_script <<-EOT || true
& {
\$certPath = '${windows_cert_path}'
Comment thread
ilnytskyi marked this conversation as resolved.
Outdated
if (-not (Test-Path \$certPath)) {
throw "Certificate path not found: \$certPath"
}

\$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(\$certPath)
\$store = New-Object System.Security.Cryptography.X509Certificates.X509Store('Root', 'CurrentUser')
\$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)

try {
\$existing = \$store.Certificates | Where-Object { \$_.Thumbprint -eq \$cert.Thumbprint }
if (\$existing) {
Write-Output 'present'
return
}

\$staleWardenRoots = @(
\$store.Certificates | Where-Object {
\$_.Thumbprint -ne \$cert.Thumbprint -and
\$_.Subject -like '*O=Warden.dev*' -and
\$_.Subject -like '*CN=Warden Proxy Local CA*'
}
)
\$store.Add(\$cert)
foreach (\$staleCert in \$staleWardenRoots) {
\$store.Remove(\$staleCert)
}
if (\$staleWardenRoots.Count -gt 0) {
Write-Output 'replaced'
} else {
Write-Output 'imported'
}
} finally {
\$store.Close()
}
}
EOT

trust_status="$(powershell.exe -NoProfile -NonInteractive -Command "${powershell_script}" | tr -d '\r')" || return 1
[[ "${trust_status}" =~ ^(present|imported|replaced)$ ]] || return 1

echo "${trust_status}"
}

function installSshConfig () {
if ! grep '## WARDEN START ##' /etc/ssh/ssh_config >/dev/null; then
echo "==> Configuring sshd tunnel in host ssh_config (requires sudo privileges)"
Expand Down
Loading