From 37ee7703df1bc775287feb28c64cbf7fdac7509e Mon Sep 17 00:00:00 2001 From: Josh Spicer Date: Wed, 16 Nov 2022 09:47:27 -0800 Subject: [PATCH] [features test cmd] Write tests with a non-root `remoteUser` (#286) * [features test cmd] Play nice with setting 'remoteUser' in a test Previously, if you set 'remoteUser' in a test, the accompanying test scripts placed into the shared 'workspaceFolder' would not have the appropriate permission bits set to be executed by the exec user. This patch ensure that all files in the workspaceFolder can be read/written/executed by the exec user. A test is added to validate creating a user and setting 'remoteUser' in a scenario, and then running a test within that context to validate. * add new test project * let -> const --- src/spec-node/featuresCLI/testCommandImpl.ts | 23 ++++++++++--------- .../whoisremoteuser/devcontainer-feature.json | 9 ++++++++ .../src/whoisremoteuser/install.sh | 12 ++++++++++ .../whoisremoteuser/different_remote_user.sh | 15 ++++++++++++ .../test/whoisremoteuser/scenarios.json | 15 ++++++++++++ .../test/whoisremoteuser/test.sh | 14 +++++++++++ 6 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/devcontainer-feature.json create mode 100644 src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/install.sh create mode 100644 src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/different_remote_user.sh create mode 100644 src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/scenarios.json create mode 100644 src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/test.sh diff --git a/src/spec-node/featuresCLI/testCommandImpl.ts b/src/spec-node/featuresCLI/testCommandImpl.ts index c1d3583e8..aa79b4193 100644 --- a/src/spec-node/featuresCLI/testCommandImpl.ts +++ b/src/spec-node/featuresCLI/testCommandImpl.ts @@ -10,6 +10,7 @@ import { DockerResolverParameters } from '../utils'; import { DevContainerConfig } from '../../spec-configuration/configuration'; import { FeaturesTestCommandInput } from './test'; import { cpDirectoryLocal } from '../../spec-utils/pfs'; +import { nullLog } from '../../spec-utils/log'; const TEST_LIBRARY_SCRIPT_NAME = 'dev-container-features-test-lib'; @@ -170,7 +171,7 @@ async function doRunAutoTest(feature: string, workspaceFolder: string, params: D await cliHost.writeFile(path.join(workspaceFolder, TEST_LIBRARY_SCRIPT_NAME), Buffer.from(testLibraryScript)); // Execute Test - const result = await execTest(params, 'test.sh', workspaceFolder); + const result = await execTest(params, 'test.sh', workspaceFolder, cliHost); testResults.push({ testName: feature, result, @@ -231,7 +232,7 @@ async function doScenario(pathToTestDir: string, targetFeatureOrGlobal: string, // Execute Test testResults.push({ testName: scenarioName, - result: await execTest(params, `${scenarioName}.sh`, workspaceFolder) + result: await execTest(params, `${scenarioName}.sh`, workspaceFolder, cliHost) }); } return testResults; @@ -267,7 +268,7 @@ const devcontainerTemplate = ` }`; async function createContainerFromWorkingDirectory(params: DockerResolverParameters, workspaceFolder: string, args: FeaturesTestCommandInput): Promise { - const { quiet, remoteUser, disposables } = args; + const { quiet, disposables } = args; log(`workspaceFolder: ${workspaceFolder}`); // 2. Use 'devcontainer-cli up' to build and start a container @@ -282,7 +283,6 @@ async function createContainerFromWorkingDirectory(params: DockerResolverParamet log(`Launched container.`, { prefix: '\nšŸš€', info: true }); log(`containerId: ${containerId}`); - log(`remoteUser: ${remoteUser}`); return launchResult; } @@ -367,6 +367,9 @@ async function generateProjectFromScenario( await cpDirectoryLocal(localPathToAdditionalConfigFolder, `${tmpFolder}/.devcontainer`); } + // Update permissions on the copied files to make them readable/writable/executable by everyone + await cliHost.exec({ cmd: 'chmod', args: ['-R', '777', tmpFolder], output: nullLog }); + // tmpFolder will serve as our auto-generated 'workingFolder' return tmpFolder; } @@ -420,15 +423,13 @@ async function launchProject(params: DockerResolverParameters, workspaceFolder: } } -async function execTest(params: DockerResolverParameters, testFileName: string, workspaceFolder: string) { +async function execTest(params: DockerResolverParameters, testFileName: string, workspaceFolder: string, cliHost: CLIHost) { // Ensure all the tests scripts in the workspace folder are executable - let cmd = 'chmod'; - let args = ['-R', '777', '.']; - await exec(params, cmd, args, workspaceFolder); - + // Update permissions on the copied files to make them readable/writable/executable by everyone + await cliHost.exec({ cmd: 'chmod', args: ['-R', '777', workspaceFolder], output: nullLog }); - cmd = `./${testFileName}`; - args = []; + const cmd = `./${testFileName}`; + const args: string[] = []; return await exec(params, cmd, args, workspaceFolder); } diff --git a/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/devcontainer-feature.json b/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/devcontainer-feature.json new file mode 100644 index 000000000..cae37a41d --- /dev/null +++ b/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/devcontainer-feature.json @@ -0,0 +1,9 @@ +{ + "id": "whoisremoteuser", + "version": "0.0.0", + "name": "Stores and echoes original value of _REMOTE_USER", + "options": {}, + "installsAfter": [ + "ghcr.io/devcontainers/features/common-utils" + ] +} \ No newline at end of file diff --git a/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/install.sh b/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/install.sh new file mode 100644 index 000000000..5e3b4b432 --- /dev/null +++ b/src/test/container-features/example-v2-features-sets/not-root-remote-user/src/whoisremoteuser/install.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +echo "Activating feature 'whoisremoteuser'" + +cat > /usr/local/bin/whoisremoteuser \ +<< EOF +#!/bin/sh +echo -n "$_REMOTE_USER" +EOF + +chmod +x /usr/local/bin/whoisremoteuser \ No newline at end of file diff --git a/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/different_remote_user.sh b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/different_remote_user.sh new file mode 100644 index 000000000..6b17de0a3 --- /dev/null +++ b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/different_remote_user.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "ensure i am user codespace" bash -c "whoami | grep 'codespace'" + +check "_REMOTE_USER was equal to codespace" bash -c "whoisremoteuser | grep 'codespace'" + + +# Report result +reportResults \ No newline at end of file diff --git a/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/scenarios.json b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/scenarios.json new file mode 100644 index 000000000..666bf0ab3 --- /dev/null +++ b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/scenarios.json @@ -0,0 +1,15 @@ +{ + "different_remote_user": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "remoteUser": "codespace", + "features": { + "ghcr.io/devcontainers/features/common-utils:1": { + "installZsh": false, + "installOhMyZsh": false, + "upgradePackages": false, + "username": "codespace" + }, + "whoisremoteuser": {} + } + } +} \ No newline at end of file diff --git a/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/test.sh b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/test.sh new file mode 100644 index 000000000..632320a32 --- /dev/null +++ b/src/test/container-features/example-v2-features-sets/not-root-remote-user/test/whoisremoteuser/test.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "ensure i am root" bash -c "whoami | grep 'root'" + +check "_REMOTE_USER was equal to root" bash -c "whoisremoteuser | grep 'root'" + +# Report result +reportResults \ No newline at end of file