diff --git a/CHANGELOG.md b/CHANGELOG.md index 23fdbc5c8..998c33d2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }}) +* Fixed bug causing some `run-elevated` commands to fail on older Powershell versions +* Removed `admin` requirement to install Lando Development CA on `win32` from `wsl` + ## v3.23.15 - [December 3, 2024](https://github.com/lando/core/releases/tag/v3.23.15) * Disabled `DOCKER_CLI_HINTS` on `lando` diff --git a/examples/setup-windows/README.md b/examples/setup-windows/README.md index 92406643b..65255c6d0 100644 --- a/examples/setup-windows/README.md +++ b/examples/setup-windows/README.md @@ -16,8 +16,8 @@ lando plugin-add "@lando/core@file:../.." lando setup -y --skip-networking --skip-common-plugins # Should have installed Docker Desktop -Test-Path "$Env:ProgramFiles\Docker\Docker\Docker Desktop.exe" -& "$Env:ProgramFiles\Docker\Docker\resources\bin\docker.exe" --version +Test-Path "$env:ProgramFiles\\Docker\\Docker\\Docker Desktop.exe" +& "$env:ProgramFiles\\Docker\\Docker\\resources\\bin\\docker.exe" --version # Should have installed Docker Compose Get-ChildItem -Path "$HOME/.lando/bin" -Filter "docker-compose-v2*" -Recurse | ForEach-Object { & $_.FullName version } diff --git a/hooks/lando-setup-build-engine-win32.js b/hooks/lando-setup-build-engine-win32.js index 2d16ec83a..3761bce3c 100644 --- a/hooks/lando-setup-build-engine-win32.js +++ b/hooks/lando-setup-build-engine-win32.js @@ -176,14 +176,20 @@ module.exports = async (lando, options) => { // check one last time incase this was added by a dependee or otherwise if (require('../utils/is-group-member')('docker-users')) return {code: 0}; - try { - const command = ['net', 'localgroup', 'docker-users', lando.config.username, '/ADD']; - const response = await require('../utils/run-elevated')(command, {debug}); - task.title = `Added ${lando.config.username} to docker-users`; - return response; - } catch (error) { + const command = ['net', 'localgroup', 'docker-users', lando.config.username, '/ADD']; + const {code, stdout, stderr} = await require('../utils/run-elevated')(command, {ignoreReturnCode: true, debug}); + + // fail on anything except 1378 which is user already exists + if (code !== 0 && (!stderr.includes('1378') || !stderr.includes('already a member'))) { + const error = new Error(`Error adding ${lando.config.username} to the docker-users group!`); + error.code = code; + error.stdout = stdout; + error.stderr = stderr; throw error; } + + task.title = `Added ${lando.config.username} to docker-users`; + return {code, stdout, stderr}; }, }); }; diff --git a/hooks/lando-setup-install-ca-wsl.js b/hooks/lando-setup-install-ca-wsl.js index ee82637f2..438ee04f5 100644 --- a/hooks/lando-setup-install-ca-wsl.js +++ b/hooks/lando-setup-install-ca-wsl.js @@ -1,7 +1,6 @@ 'use strict'; const os = require('os'); -const getWinEnvar = require('../utils/get-win32-envvar-from-wsl'); const path = require('path'); /** @@ -118,17 +117,6 @@ module.exports = async (lando, options) => { } }, canRun: async () => { - // get windows user - const user = await getWinEnvar('USERNAME'); - - // Check for admin privileges - if (!await require('../utils/is-admin-user')(user, {platform: 'win32'})) { - throw new Error([ - `User "${user}" does not have permission to trust the CA!`, - 'Contact your system admin for permission and then rerun setup.', - ].join(os.EOL)); - } - return true; }, task: async (ctx, task) => { diff --git a/package-lock.json b/package-lock.json index 74f9181ab..1714fa328 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@lando/core", - "version": "3.23.14", + "version": "3.23.15", "license": "GPL-3.0", "dependencies": { "@lando/argv": "^1.1.2", diff --git a/scripts/run-elevated.ps1 b/scripts/run-elevated.ps1 index 3d1ea2242..cbe27ac65 100644 --- a/scripts/run-elevated.ps1 +++ b/scripts/run-elevated.ps1 @@ -16,8 +16,8 @@ $debug = If ($DebugPreference -eq "Continue") {$true} Else {$false} # figure out the command and setup fake fds $command = $cmd.split(',') -$stdoutfile = Join-Path $Env:Temp $(New-Guid) -$stderrfile = Join-Path $Env:Temp $(New-Guid) +$stdoutfile = Join-Path $Env:Temp $([guid]::NewGuid().ToString()) +$stderrfile = Join-Path $Env:Temp $([guid]::NewGuid().ToString()) # DEBUG Write-Debug "running elevated command:" diff --git a/utils/is-admin-user.js b/utils/is-admin-user.js index 4a8ac9e63..acea6c77a 100644 --- a/utils/is-admin-user.js +++ b/utils/is-admin-user.js @@ -16,7 +16,8 @@ module.exports = (user, {platform = process.platform} = {}) => { || require('./is-group-member')('wheel', user, platform) || require('./is-group-member')('adm', user, platform); case 'win32': - return require('./is-group-member')('administrators', user, platform); + return require('./is-group-member')('S-1-5-32-544', user, platform) + || require('./is-group-member')('administrators', user, platform); default: return false; } diff --git a/utils/is-group-member.js b/utils/is-group-member.js index 4216d2250..fe2b6d121 100644 --- a/utils/is-group-member.js +++ b/utils/is-group-member.js @@ -31,12 +31,15 @@ module.exports = (group, user, platform = process.platform) => { // if windows we have a long command to check if (platform === 'win32') { - const groups = stdout + const ids = stdout .split(os.EOL) .map(group => group.trim()) .filter(group => group !== 'Name' && group !== '----') .map(group => group.toUpperCase()); - return groups.includes(group.toUpperCase()); + + const matches = ids.filter(id => id === group.toUpperCase() || id.endsWith(group.toUpperCase())); + + return matches.length > 0; } // otherwise false? diff --git a/utils/run-elevated.js b/utils/run-elevated.js index f2c24ef3b..e9d725c7a 100644 --- a/utils/run-elevated.js +++ b/utils/run-elevated.js @@ -95,9 +95,17 @@ module.exports = (command, options, stdout = '', stderr = '') => { debug('elevated command %o done with code %o', command, code); // with run-elevate we want to clean up stderr a bit if we can eg remove the powershell shit if (options.method === 'run-elevated') { + const raw = stderr; + stderr = stderr.split('. At line')[0]; stderr = stderr.split(`${os.EOL}At `)[0]; + // add nse if we have one + if (raw.split('NativeCommandError')[1]) { + const nse = raw.split('NativeCommandError')[1]; + stderr = `${stderr}. ${nse.trim()}`; + } + // simplify the UAC cancel error if (stderr.includes('The operation was canceled by the user.')) { stderr = 'The operation was canceled by the user.';