From 64f884144fcdab9e25c1eea65981a397a99b3fff Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Mon, 14 Aug 2023 22:18:16 -0500 Subject: [PATCH 01/10] Add config support for ssl cert, key, ports Still need to add Apache mod_ssl support --- .wp-env.json | 12 +++++ packages/env/.gitignore | 1 + .../env/lib/build-docker-compose-config.js | 20 +++++-- .../get-config-from-environment-vars.js | 4 ++ packages/env/lib/config/parse-config.js | 49 ++++++++++++++++- .../env/lib/config/post-process-config.js | 54 ++++++++++++++++++- packages/env/lib/config/validate-config.js | 2 +- 7 files changed, 135 insertions(+), 7 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 79810b194b667c..c87911b3bd5aed 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -3,7 +3,19 @@ "plugins": [ "." ], "themes": [ "./test/emptytheme" ], "env": { + "development": { + "ssl": { + "cert": "packages/env/ssl/localhost.crt", + "key": "packages/env/ssl/localhost.key", + "port": 8993 + } + }, "tests": { + "ssl": { + "cert": "packages/env/ssl/localhost.crt", + "key": "packages/env/ssl/localhost.key", + "port": 8994 + }, "mappings": { "wp-content/plugins/gutenberg": ".", "wp-content/mu-plugins": "./packages/e2e-tests/mu-plugins", diff --git a/packages/env/.gitignore b/packages/env/.gitignore index 9a1c1f1a146573..3424bf21569ea1 100644 --- a/packages/env/.gitignore +++ b/packages/env/.gitignore @@ -1,2 +1,3 @@ # Build /lib/docker-compose.yml +/ssl \ No newline at end of file diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index 5336f8690cca85..899011a4ad9ba6 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -165,8 +165,20 @@ module.exports = function buildDockerComposeConfig( config ) { } // Set the default ports based on the config values. - const developmentPorts = `\${WP_ENV_PORT:-${ config.env.development.port }}:80`; - const testsPorts = `\${WP_ENV_TESTS_PORT:-${ config.env.tests.port }}:80`; + const developmentPorts = [ + `\${WP_ENV_PORT:-${ config.env.development.port }}:80`, + ]; + const testsPorts = [ + `\${WP_ENV_TESTS_PORT:-${ config.env.tests.port }}:80`, + ]; + + // Set the default SSL ports based on the config values. + if ( config.env.development.ssl !== undefined && config.env.development.ssl.cert && config.env.development.ssl.port ) { + developmentPorts.push( `\${WP_ENV_PORT:-${ config.env.development.ssl.port }}:443` ); + } + if ( config.env.tests.ssl !== undefined && config.env.tests.ssl.cert && config.env.tests.ssl.port ) { + testsPorts.push( `\${WP_ENV_TESTS_PORT:-${ config.env.tests.ssl.port }}:443` ); + } return { version: '3.7', @@ -200,7 +212,7 @@ module.exports = function buildDockerComposeConfig( config ) { dockerfile: 'WordPress.Dockerfile', args: imageBuildArgs, }, - ports: [ developmentPorts ], + ports: developmentPorts, environment: { APACHE_RUN_USER: '#' + hostUser.uid, APACHE_RUN_GROUP: '#' + hostUser.gid, @@ -218,7 +230,7 @@ module.exports = function buildDockerComposeConfig( config ) { dockerfile: 'Tests-WordPress.Dockerfile', args: imageBuildArgs, }, - ports: [ testsPorts ], + ports: testsPorts, environment: { APACHE_RUN_USER: '#' + hostUser.uid, APACHE_RUN_GROUP: '#' + hostUser.gid, diff --git a/packages/env/lib/config/get-config-from-environment-vars.js b/packages/env/lib/config/get-config-from-environment-vars.js index 8a4608b859b7f7..360cd27c790ede 100644 --- a/packages/env/lib/config/get-config-from-environment-vars.js +++ b/packages/env/lib/config/get-config-from-environment-vars.js @@ -34,6 +34,10 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) { const environmentConfig = { port: getPortFromEnvironmentVariable( 'WP_ENV_PORT' ), testsPort: getPortFromEnvironmentVariable( 'WP_ENV_TESTS_PORT' ), + ssl: { + port: getPortFromEnvironmentVariable( 'WP_ENV_SSL_PORT' ), + testPort: getPortFromEnvironmentVariable( 'WP_ENV_SSL_TESTS_PORT' ), + }, lifecycleScripts: getLifecycleScriptOverrides(), }; diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 743db978963443..55bf370a198b89 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -14,6 +14,7 @@ const { } = require( './parse-source-string' ); const { ValidationError, + checkString, checkPort, checkStringArray, checkObjectWithValues, @@ -35,6 +36,7 @@ const mergeConfigs = require( './merge-configs' ); * @typedef WPRootConfigOptions * @property {number} port The port to use in the development environment. * @property {number} testsPort The port to use in the tests environment. + * @property {Object} ssl The ssl certificate, key, and port numbers. * @property {Object.} lifecycleScripts The scripts to run at certain points in the command lifecycle. * @property {Object.} lifecycleScripts.afterStart The script to run after the "start" command has completed. * @property {Object.} lifecycleScripts.afterClean The script to run after the "clean" command has completed. @@ -50,6 +52,7 @@ const mergeConfigs = require( './merge-configs' ); * @property {WPSource[]} pluginSources Plugins to load in the environment. * @property {WPSource[]} themeSources Themes to load in the environment. * @property {number} port The port to use. + * @property {Object} ssl The ssl certificate, key, and port number. * @property {Object} config Mapping of wp-config.php constants to their desired values. * @property {Object.} mappings Mapping of WordPress directories to local directories which should be mounted. * @property {string|null} phpVersion Version of PHP to use in the environments, of the format 0.0. @@ -85,6 +88,12 @@ const DEFAULT_ENVIRONMENT_CONFIG = { themes: [], port: 8888, testsPort: 8889, + ssl: { + cert: null, + key: null, + port: 8883, + testsPort: 8884 + }, mappings: {}, config: { FS_METHOD: 'direct', @@ -232,8 +241,19 @@ async function getDefaultConfig( afterDestroy: null, }, env: { - development: {}, + development: { + ssl: { + /* cert: DEFAULT_ENVIRONMENT_CONFIG.ssl.cert, + key: DEFAULT_ENVIRONMENT_CONFIG.ssl.key, */ + port: DEFAULT_ENVIRONMENT_CONFIG.ssl.port, + }, + }, tests: { + ssl: { + /* cert: DEFAULT_ENVIRONMENT_CONFIG.ssl.cert, + key: DEFAULT_ENVIRONMENT_CONFIG.ssl.key, */ + port: DEFAULT_ENVIRONMENT_CONFIG.ssl.testsPort, + }, config: { WP_DEBUG: false, SCRIPT_DEBUG: false, @@ -281,6 +301,16 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) { overrideConfig.env.tests.port = overrides.testsPort; } + if ( overrides.ssl.port ) { + overrideConfig.ssl.port = overrides.ssl.port; + overrideConfig.env.development.ssl.port = overrides.ssl.port; + } + + if ( overrides.ssl.testsPort ) { + overrideConfig.ssl.testsPort = overrides.ssl.testsPort; + overrideConfig.env.tests.ssl.port = overrides.ssl.testsPort; + } + if ( overrides.coreSource ) { overrideConfig.coreSource = overrides.coreSource; overrideConfig.env.development.coreSource = overrides.coreSource; @@ -436,6 +466,23 @@ async function parseEnvironmentConfig( parsedConfig.port = config.port; } + if ( config.ssl !== undefined ) { + parsedConfig.ssl = config.ssl; + if ( config.ssl.port !== undefined ) { + checkPort( configFile, `${ environmentPrefix }ssl.port`, config.ssl.port ); + parsedConfig.ssl.port = config.ssl.port; + } + if ( config.ssl.key !== undefined && config.ssl.key !== null ) { + checkString( configFile, `${ environmentPrefix }ssl.key`, config.ssl.key ); + parsedConfig.ssl.key = config.ssl.key; + } + parsedConfig.ssl.key = config.ssl.key; + if ( config.ssl.cert !== undefined && config.ssl.cert !== null ) { + checkString( configFile, `${ environmentPrefix }ssl.cert`, config.ssl.cert ); + parsedConfig.ssl.cert = config.ssl.cert; + } + } + if ( config.phpVersion !== undefined ) { // Support null as a valid input. if ( config.phpVersion !== null ) { diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index d09843893ea69f..a491d6a63d2581 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -59,6 +59,24 @@ function mergeRootToEnvironments( config ) { config.env.tests.port = config.testsPort; delete config.testsPort; } + if ( config.ssl !== undefined ) { + if ( + config.ssl.port !== undefined && + config.env.development.ssl.port === undefined + ) { + removedRootOptions.ssl.port = config.ssl.port; + config.env.development.ssl.port = config.ssl.port; + delete config.ssl.port; + } + if ( + config.ssl.testsPort !== undefined && + config.env.tests.ssl.port === undefined + ) { + removedRootOptions.ssl.testsPort = config.ssl.testsPort; + config.env.tests.ssl.port = config.ssl.testsPort; + delete config.ssl.testsPort; + } + } if ( config.lifecycleScripts !== undefined ) { removedRootOptions.lifecycleScripts = config.lifecycleScripts; delete config.lifecycleScripts; @@ -110,9 +128,16 @@ function appendPortToWPConfigs( config ) { continue; } + let port = config.env[ env ].port; + if ( config.env[ env ].ssl ) { + port = config.env[ env ].ssl.port; + if ( config.env[ env ].config[ option ].startsWith( 'http://' ) ) { + config.env[ env ].config[ option ] = 'https://' + config.env[ env ].config[ option ].substring( 7 ); + } + } config.env[ env ].config[ option ] = addOrReplacePort( config.env[ env ].config[ option ], - config.env[ env ].port, + port, // Don't replace the port if one is already set on WP_HOME. option !== 'WP_HOME' ); @@ -131,6 +156,7 @@ function validatePortUniqueness( config ) { // We're going to build a map of the environments and their port // so we can accomodate root-level config options more easily. const environmentPorts = {}; + const environmentSSLPorts = {}; // Add all of the environments to the map. This will // overwrite any root-level options if necessary. @@ -140,8 +166,20 @@ function validatePortUniqueness( config ) { `The "${ env }" environment has an invalid port.` ); } + if ( + config.env[ env ].ssl !== undefined && + config.env[ env ].ssl.port === undefined + ) { + throw new ValidationError( + `The "${ env }" environment has an invalid SSL port.` + ); + } environmentPorts[ env ] = config.env[ env ].port; + + if ( config.env[ env ].ssl !== undefined ) { + environmentSSLPorts[ env ] = config.env[ env ].ssl.port; + } } // This search isn't very performant, but, we won't ever be @@ -159,6 +197,20 @@ function validatePortUniqueness( config ) { } } } + + for ( const env in environmentSSLPorts ) { + for ( const check in environmentSSLPorts ) { + if ( env === check ) { + continue; + } + + if ( environmentSSLPorts[ env ] === environmentSSLPorts[ check ] ) { + throw new ValidationError( + `The "${ env }" and "${ check }" environments may not have the same SSL port.` + ); + } + } + } } /** diff --git a/packages/env/lib/config/validate-config.js b/packages/env/lib/config/validate-config.js index 4aa62cb4571557..61d1b9f3f29005 100644 --- a/packages/env/lib/config/validate-config.js +++ b/packages/env/lib/config/validate-config.js @@ -15,7 +15,7 @@ class ValidationError extends Error {} * * @param {string} configFile The configuration file we're validating. * @param {string} configKey The configuration key we're validating. - * @param {number} value The value to check. + * @param {string} value The value to check. */ function checkString( configFile, configKey, value ) { if ( typeof value !== 'string' ) { From 67be3159a82e24a551dabb8fcf3f3501ceeb0df9 Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Wed, 16 Aug 2023 23:05:40 -0500 Subject: [PATCH 02/10] Add docker support for ssl --- .../env/lib/build-docker-compose-config.js | 3 + packages/env/lib/init-config.js | 70 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index 899011a4ad9ba6..57cdc97fac2c1b 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -54,6 +54,8 @@ function getMounts( ? `user-home:/home/${ hostUsername }` : `tests-user-home:/home/${ hostUsername }`; + const sslMount = workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl` + const corePHPUnitMount = `${ path.join( workDirectoryPath, wordpressDefault === 'wordpress' @@ -72,6 +74,7 @@ function getMounts( coreMount, // Must be first because of some operations later that expect it to be! corePHPUnitMount, userHomeMount, + sslMount, ...directoryMounts, ...pluginMounts, ...themeMounts, diff --git a/packages/env/lib/init-config.js b/packages/env/lib/init-config.js index efde002dc58389..35c18b4be5391a 100644 --- a/packages/env/lib/init-config.js +++ b/packages/env/lib/init-config.js @@ -4,7 +4,7 @@ */ const path = require( 'path' ); const { writeFile, mkdir } = require( 'fs' ).promises; -const { existsSync } = require( 'fs' ); +const { mkdirSync, existsSync, copyFileSync, accessSync, constants } = require( 'fs' ); const yaml = require( 'js-yaml' ); /** @@ -206,7 +206,10 @@ RUN apt-get -qy install git # Set up sudo so they can have root access. RUN apt-get -qy install sudo -RUN echo "#$HOST_UID ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers`; +RUN echo "#$HOST_UID ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Enable SSL support +${ enableSSL( config.env[ env ].ssl.cert, config.env[ env ].ssl.key, config.workDirectoryPath ) }`; break; } case 'cli': { @@ -303,3 +306,66 @@ RUN echo 'xdebug.start_with_request=yes' >> /usr/local/etc/php/php.ini RUN echo 'xdebug.mode=${ xdebugMode }' >> /usr/local/etc/php/php.ini RUN echo 'xdebug.client_host="host.docker.internal"' >> /usr/local/etc/php/php.ini`; } + +/** + * Enable SSL support. + * + * @param {string} certPath Path of the certificate file on the host. + * @param {string} keyPath Path of the key file on the host. + * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env. + * @returns {string} Dockerfile content to enable SSL support + */ +function enableSSL( certPath, keyPath, workDirectoryPath ) { + + if ( typeof certPath !== 'string' && typeof keyPath !== 'string' ) { + return ''; + } + + // If SSL certificates are defined, try to copy them to the working directory. + copySSLCertificates( certPath, keyPath, workDirectoryPath ); + + const certName = path.basename( certPath ); + const keyName = path.basename( keyPath ); + const certFile = workDirectoryPath + '/' + certName; + const keyFile = workDirectoryPath + '/' + keyName; + + return ` +RUN sed -i "s\/\\\/etc\\\/ssl\\\/certs\\\/ssl-cert-snakeoil.pem\/\\\/home\\\/$HOST_USERNAME\\\/ssl\\\/${ certName }\/" /etc/apache2/sites-available/default-ssl.conf +RUN sed -i "s\/\\\/etc\\\/ssl\\\/private\\\/ssl-cert-snakeoil.key\/\\\/home\\\/$HOST_USERNAME\\\/ssl\\\/${ keyName }\/" /etc/apache2/sites-available/default-ssl.conf +RUN a2enmod ssl +RUN a2ensite default-ssl +`; +} + +/** + * Try to copy the SSL certificates to the work directory. + * @param {string} certPath Path of the certificate file on the host. + * @param {string} keyPath Path of the key file on the host. + * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env. + */ +function copySSLCertificates( certPath, keyPath, workDirectoryPath ) { + + // Check that paths exist and is readable. + accessSync( certPath, constants.F_OK | constants.R_OK, error => { + if ( error ) throw new Error( `File does not exist or is not readable: "${ certPath }"` ); + } ); + accessSync( keyPath, constants.F_OK | constants.R_OK, error => { + if ( error ) throw new Error( `File does not exist or is not readable: "${ keyPath }"` ); + } ); + + const sslDir = workDirectoryPath + '/ssl'; + + if ( !existsSync( sslDir ) ) { + mkdirSync( sslDir ); + } + + // Get filenames and destinations + const certName = path.basename( certPath ); + const keyName = path.basename( keyPath ); + const certDestination = sslDir + '/' + certName; + const keyDestination = sslDir + '/' + keyName; + + // Copy files + copyFileSync( certPath, certDestination ); + copyFileSync( keyPath, keyDestination ); +} \ No newline at end of file From 617f8e246e3d375050a97c8a6ddd67c55ef4eb8a Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Sat, 19 Aug 2023 09:37:16 -0500 Subject: [PATCH 03/10] Remove modifications to .wp-env and .gitignore --- .wp-env.json | 12 ------------ packages/env/.gitignore | 3 +-- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index c87911b3bd5aed..79810b194b667c 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -3,19 +3,7 @@ "plugins": [ "." ], "themes": [ "./test/emptytheme" ], "env": { - "development": { - "ssl": { - "cert": "packages/env/ssl/localhost.crt", - "key": "packages/env/ssl/localhost.key", - "port": 8993 - } - }, "tests": { - "ssl": { - "cert": "packages/env/ssl/localhost.crt", - "key": "packages/env/ssl/localhost.key", - "port": 8994 - }, "mappings": { "wp-content/plugins/gutenberg": ".", "wp-content/mu-plugins": "./packages/e2e-tests/mu-plugins", diff --git a/packages/env/.gitignore b/packages/env/.gitignore index 3424bf21569ea1..76d84452072ff4 100644 --- a/packages/env/.gitignore +++ b/packages/env/.gitignore @@ -1,3 +1,2 @@ # Build -/lib/docker-compose.yml -/ssl \ No newline at end of file +/lib/docker-compose.yml \ No newline at end of file From 799dd2f96e6936df6fee83ec97c2485ddc93edcc Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Tue, 22 Aug 2023 20:58:39 -0500 Subject: [PATCH 04/10] Apply js lint fixes to ./packages/env/lib --- .../env/lib/build-docker-compose-config.js | 22 +++++++--- packages/env/lib/config/parse-config.js | 20 +++++++-- .../env/lib/config/post-process-config.js | 8 +++- packages/env/lib/init-config.js | 42 +++++++++++-------- 4 files changed, 63 insertions(+), 29 deletions(-) diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index 57cdc97fac2c1b..bdd65e3f48d602 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -54,7 +54,7 @@ function getMounts( ? `user-home:/home/${ hostUsername }` : `tests-user-home:/home/${ hostUsername }`; - const sslMount = workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl` + const sslMount = workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl`; const corePHPUnitMount = `${ path.join( workDirectoryPath, @@ -176,11 +176,23 @@ module.exports = function buildDockerComposeConfig( config ) { ]; // Set the default SSL ports based on the config values. - if ( config.env.development.ssl !== undefined && config.env.development.ssl.cert && config.env.development.ssl.port ) { - developmentPorts.push( `\${WP_ENV_PORT:-${ config.env.development.ssl.port }}:443` ); + if ( + config.env.development.ssl !== undefined && + config.env.development.ssl.cert && + config.env.development.ssl.port + ) { + developmentPorts.push( + `\${WP_ENV_PORT:-${ config.env.development.ssl.port }}:443` + ); } - if ( config.env.tests.ssl !== undefined && config.env.tests.ssl.cert && config.env.tests.ssl.port ) { - testsPorts.push( `\${WP_ENV_TESTS_PORT:-${ config.env.tests.ssl.port }}:443` ); + if ( + config.env.tests.ssl !== undefined && + config.env.tests.ssl.cert && + config.env.tests.ssl.port + ) { + testsPorts.push( + `\${WP_ENV_TESTS_PORT:-${ config.env.tests.ssl.port }}:443` + ); } return { diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 55bf370a198b89..385a96ce8c7fd4 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -92,7 +92,7 @@ const DEFAULT_ENVIRONMENT_CONFIG = { cert: null, key: null, port: 8883, - testsPort: 8884 + testsPort: 8884, }, mappings: {}, config: { @@ -469,16 +469,28 @@ async function parseEnvironmentConfig( if ( config.ssl !== undefined ) { parsedConfig.ssl = config.ssl; if ( config.ssl.port !== undefined ) { - checkPort( configFile, `${ environmentPrefix }ssl.port`, config.ssl.port ); + checkPort( + configFile, + `${ environmentPrefix }ssl.port`, + config.ssl.port + ); parsedConfig.ssl.port = config.ssl.port; } if ( config.ssl.key !== undefined && config.ssl.key !== null ) { - checkString( configFile, `${ environmentPrefix }ssl.key`, config.ssl.key ); + checkString( + configFile, + `${ environmentPrefix }ssl.key`, + config.ssl.key + ); parsedConfig.ssl.key = config.ssl.key; } parsedConfig.ssl.key = config.ssl.key; if ( config.ssl.cert !== undefined && config.ssl.cert !== null ) { - checkString( configFile, `${ environmentPrefix }ssl.cert`, config.ssl.cert ); + checkString( + configFile, + `${ environmentPrefix }ssl.cert`, + config.ssl.cert + ); parsedConfig.ssl.cert = config.ssl.cert; } } diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index a491d6a63d2581..c6863195675d9b 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -131,8 +131,12 @@ function appendPortToWPConfigs( config ) { let port = config.env[ env ].port; if ( config.env[ env ].ssl ) { port = config.env[ env ].ssl.port; - if ( config.env[ env ].config[ option ].startsWith( 'http://' ) ) { - config.env[ env ].config[ option ] = 'https://' + config.env[ env ].config[ option ].substring( 7 ); + if ( + config.env[ env ].config[ option ].startsWith( 'http://' ) + ) { + config.env[ env ].config[ option ] = + 'https://' + + config.env[ env ].config[ option ].substring( 7 ); } } config.env[ env ].config[ option ] = addOrReplacePort( diff --git a/packages/env/lib/init-config.js b/packages/env/lib/init-config.js index 35c18b4be5391a..150ac724943f29 100644 --- a/packages/env/lib/init-config.js +++ b/packages/env/lib/init-config.js @@ -4,7 +4,13 @@ */ const path = require( 'path' ); const { writeFile, mkdir } = require( 'fs' ).promises; -const { mkdirSync, existsSync, copyFileSync, accessSync, constants } = require( 'fs' ); +const { + mkdirSync, + existsSync, + copyFileSync, + accessSync, + constants, +} = require( 'fs' ); const yaml = require( 'js-yaml' ); /** @@ -209,7 +215,11 @@ RUN apt-get -qy install sudo RUN echo "#$HOST_UID ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # Enable SSL support -${ enableSSL( config.env[ env ].ssl.cert, config.env[ env ].ssl.key, config.workDirectoryPath ) }`; +${ enableSSL( + config.env[ env ].ssl.cert, + config.env[ env ].ssl.key, + config.workDirectoryPath +) }`; break; } case 'cli': { @@ -309,14 +319,13 @@ RUN echo 'xdebug.client_host="host.docker.internal"' >> /usr/local/etc/php/php.i /** * Enable SSL support. - * - * @param {string} certPath Path of the certificate file on the host. - * @param {string} keyPath Path of the key file on the host. + * + * @param {string} certPath Path of the certificate file on the host. + * @param {string} keyPath Path of the key file on the host. * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env. - * @returns {string} Dockerfile content to enable SSL support + * @return {string} Dockerfile content to enable SSL support */ function enableSSL( certPath, keyPath, workDirectoryPath ) { - if ( typeof certPath !== 'string' && typeof keyPath !== 'string' ) { return ''; } @@ -326,8 +335,6 @@ function enableSSL( certPath, keyPath, workDirectoryPath ) { const certName = path.basename( certPath ); const keyName = path.basename( keyPath ); - const certFile = workDirectoryPath + '/' + certName; - const keyFile = workDirectoryPath + '/' + keyName; return ` RUN sed -i "s\/\\\/etc\\\/ssl\\\/certs\\\/ssl-cert-snakeoil.pem\/\\\/home\\\/$HOST_USERNAME\\\/ssl\\\/${ certName }\/" /etc/apache2/sites-available/default-ssl.conf @@ -339,23 +346,22 @@ RUN a2ensite default-ssl /** * Try to copy the SSL certificates to the work directory. - * @param {string} certPath Path of the certificate file on the host. - * @param {string} keyPath Path of the key file on the host. + * @param {string} certPath Path of the certificate file on the host. + * @param {string} keyPath Path of the key file on the host. * @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env. */ function copySSLCertificates( certPath, keyPath, workDirectoryPath ) { - // Check that paths exist and is readable. - accessSync( certPath, constants.F_OK | constants.R_OK, error => { - if ( error ) throw new Error( `File does not exist or is not readable: "${ certPath }"` ); + accessSync( certPath, constants.F_OK, ( error ) => { + if ( error ) throw new Error( `File does not exist: "${ certPath }"` ); } ); - accessSync( keyPath, constants.F_OK | constants.R_OK, error => { - if ( error ) throw new Error( `File does not exist or is not readable: "${ keyPath }"` ); + accessSync( keyPath, constants.F_OK, ( error ) => { + if ( error ) throw new Error( `File does not exist: "${ keyPath }"` ); } ); const sslDir = workDirectoryPath + '/ssl'; - if ( !existsSync( sslDir ) ) { + if ( ! existsSync( sslDir ) ) { mkdirSync( sslDir ); } @@ -368,4 +374,4 @@ function copySSLCertificates( certPath, keyPath, workDirectoryPath ) { // Copy files copyFileSync( certPath, certDestination ); copyFileSync( keyPath, keyDestination ); -} \ No newline at end of file +} From 6259389556da14892bef204e467aeee473203ae0 Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Tue, 22 Aug 2023 21:15:28 -0500 Subject: [PATCH 05/10] Fix wp-env ssl root config not being transferred to env --- packages/env/lib/config/parse-config.js | 30 +++++++-------- .../env/lib/config/post-process-config.js | 38 +++++++++++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 385a96ce8c7fd4..2b1a5bedcae65d 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -36,7 +36,7 @@ const mergeConfigs = require( './merge-configs' ); * @typedef WPRootConfigOptions * @property {number} port The port to use in the development environment. * @property {number} testsPort The port to use in the tests environment. - * @property {Object} ssl The ssl certificate, key, and port numbers. + * @property {Object.} ssl The ssl certificate, key, and port numbers. * @property {Object.} lifecycleScripts The scripts to run at certain points in the command lifecycle. * @property {Object.} lifecycleScripts.afterStart The script to run after the "start" command has completed. * @property {Object.} lifecycleScripts.afterClean The script to run after the "clean" command has completed. @@ -52,12 +52,21 @@ const mergeConfigs = require( './merge-configs' ); * @property {WPSource[]} pluginSources Plugins to load in the environment. * @property {WPSource[]} themeSources Themes to load in the environment. * @property {number} port The port to use. - * @property {Object} ssl The ssl certificate, key, and port number. + * @property {WPSSLConfig} ssl The ssl certificate, key, and port number. * @property {Object} config Mapping of wp-config.php constants to their desired values. * @property {Object.} mappings Mapping of WordPress directories to local directories which should be mounted. * @property {string|null} phpVersion Version of PHP to use in the environments, of the format 0.0. */ +/** + * The SSL configuration options. + * + * @typedef WPSSLConfig + * @property {string} cert The path to the SSL certificate. + * @property {string} key The path to the SSL key. + * @property {number} port The port to use for SSL. + */ + /** * The root configuration options. * @@ -241,19 +250,8 @@ async function getDefaultConfig( afterDestroy: null, }, env: { - development: { - ssl: { - /* cert: DEFAULT_ENVIRONMENT_CONFIG.ssl.cert, - key: DEFAULT_ENVIRONMENT_CONFIG.ssl.key, */ - port: DEFAULT_ENVIRONMENT_CONFIG.ssl.port, - }, - }, + development: {}, tests: { - ssl: { - /* cert: DEFAULT_ENVIRONMENT_CONFIG.ssl.cert, - key: DEFAULT_ENVIRONMENT_CONFIG.ssl.key, */ - port: DEFAULT_ENVIRONMENT_CONFIG.ssl.testsPort, - }, config: { WP_DEBUG: false, SCRIPT_DEBUG: false, @@ -301,12 +299,12 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) { overrideConfig.env.tests.port = overrides.testsPort; } - if ( overrides.ssl.port ) { + if ( overrides.ssl && overrides.ssl.port ) { overrideConfig.ssl.port = overrides.ssl.port; overrideConfig.env.development.ssl.port = overrides.ssl.port; } - if ( overrides.ssl.testsPort ) { + if ( overrides.ssl && overrides.ssl.testsPort ) { overrideConfig.ssl.testsPort = overrides.ssl.testsPort; overrideConfig.env.tests.ssl.port = overrides.ssl.testsPort; } diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index c6863195675d9b..1e1158dfc9437c 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -60,8 +60,12 @@ function mergeRootToEnvironments( config ) { delete config.testsPort; } if ( config.ssl !== undefined ) { + removedRootOptions.ssl = {}; + config.env.development.ssl = {}; + config.env.tests.ssl = {}; if ( config.ssl.port !== undefined && + config.env.development.ssl !== undefined && config.env.development.ssl.port === undefined ) { removedRootOptions.ssl.port = config.ssl.port; @@ -70,12 +74,46 @@ function mergeRootToEnvironments( config ) { } if ( config.ssl.testsPort !== undefined && + config.env.tests.ssl !== undefined && config.env.tests.ssl.port === undefined ) { removedRootOptions.ssl.testsPort = config.ssl.testsPort; config.env.tests.ssl.port = config.ssl.testsPort; delete config.ssl.testsPort; } + if ( config.ssl.cert !== undefined ) { + if ( + config.env.development.ssl !== undefined && + config.env.development.ssl.cert === undefined + ) { + config.env.development.ssl.cert = config.ssl.cert; + } + if ( + config.env.tests.ssl !== undefined && + config.env.tests.ssl.cert === undefined + ) { + config.env.tests.ssl.cert = config.ssl.cert; + } + removedRootOptions.ssl.cert = config.ssl.cert; + delete config.ssl.cert; + } + if ( config.ssl.key !== undefined ) { + if ( + config.env.development.ssl !== undefined && + config.env.development.ssl.key === undefined + ) { + config.env.development.ssl.key = config.ssl.key; + } + if ( + config.env.tests.ssl !== undefined && + config.env.tests.ssl.key === undefined + ) { + config.env.tests.ssl.key = config.ssl.key; + } + removedRootOptions.ssl.key = config.ssl.key; + delete config.ssl.key; + } + delete config.ssl; } if ( config.lifecycleScripts !== undefined ) { removedRootOptions.lifecycleScripts = config.lifecycleScripts; From 205b5445755f062af317257bf1e7439e26d89c11 Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Tue, 22 Aug 2023 22:33:06 -0500 Subject: [PATCH 06/10] Fix wp-env incorrect ports when no ssl defined --- .../env/lib/build-docker-compose-config.js | 7 ++- packages/env/lib/config/parse-config.js | 4 +- .../env/lib/config/post-process-config.js | 43 ++++++++++++++----- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index bdd65e3f48d602..28208817efa225 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -54,7 +54,10 @@ function getMounts( ? `user-home:/home/${ hostUsername }` : `tests-user-home:/home/${ hostUsername }`; - const sslMount = workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl`; + const sslMount = []; + if (config.ssl !== undefined && config.ssl.cert) { + sslMount.push(workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl`); + } const corePHPUnitMount = `${ path.join( workDirectoryPath, @@ -74,7 +77,7 @@ function getMounts( coreMount, // Must be first because of some operations later that expect it to be! corePHPUnitMount, userHomeMount, - sslMount, + ...sslMount, ...directoryMounts, ...pluginMounts, ...themeMounts, diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 2b1a5bedcae65d..436b3295bf82f9 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -474,7 +474,7 @@ async function parseEnvironmentConfig( ); parsedConfig.ssl.port = config.ssl.port; } - if ( config.ssl.key !== undefined && config.ssl.key !== null ) { + if ( config.ssl.key ) { checkString( configFile, `${ environmentPrefix }ssl.key`, @@ -483,7 +483,7 @@ async function parseEnvironmentConfig( parsedConfig.ssl.key = config.ssl.key; } parsedConfig.ssl.key = config.ssl.key; - if ( config.ssl.cert !== undefined && config.ssl.cert !== null ) { + if ( config.ssl.cert ) { checkString( configFile, `${ environmentPrefix }ssl.cert`, diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index 1e1158dfc9437c..2aa4aa6b888f69 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -59,7 +59,17 @@ function mergeRootToEnvironments( config ) { config.env.tests.port = config.testsPort; delete config.testsPort; } - if ( config.ssl !== undefined ) { + if ( config.lifecycleScripts !== undefined ) { + removedRootOptions.lifecycleScripts = config.lifecycleScripts; + delete config.lifecycleScripts; + } + + // Check if ssl is set and if it is, move it to the environment configs. + if ( + config.ssl !== undefined && + config.ssl.cert && + config.ssl.key + ) { removedRootOptions.ssl = {}; config.env.development.ssl = {}; config.env.tests.ssl = {}; @@ -81,7 +91,7 @@ function mergeRootToEnvironments( config ) { config.env.tests.ssl.port = config.ssl.testsPort; delete config.ssl.testsPort; } - if ( config.ssl.cert !== undefined ) { + if ( config.ssl.cert ) { if ( config.env.development.ssl !== undefined && config.env.development.ssl.cert === undefined @@ -97,7 +107,7 @@ function mergeRootToEnvironments( config ) { removedRootOptions.ssl.cert = config.ssl.cert; delete config.ssl.cert; } - if ( config.ssl.key !== undefined ) { + if ( config.ssl.key ) { if ( config.env.development.ssl !== undefined && config.env.development.ssl.key === undefined @@ -114,10 +124,13 @@ function mergeRootToEnvironments( config ) { delete config.ssl.key; } delete config.ssl; - } - if ( config.lifecycleScripts !== undefined ) { - removedRootOptions.lifecycleScripts = config.lifecycleScripts; - delete config.lifecycleScripts; + } else if ( + config.ssl !== undefined && + config.ssl.cert === undefined && + config.ssl.key === undefined + ) { + removedRootOptions.ssl = config.ssl; + delete config.ssl; } // Merge the root config and the environment configs together so that @@ -167,7 +180,11 @@ function appendPortToWPConfigs( config ) { } let port = config.env[ env ].port; - if ( config.env[ env ].ssl ) { + if ( + config.env[ env ].ssl && + config.env[ env ].ssl.cert && + config.env[ env ].ssl.key + ) { port = config.env[ env ].ssl.port; if ( config.env[ env ].config[ option ].startsWith( 'http://' ) @@ -210,7 +227,7 @@ function validatePortUniqueness( config ) { } if ( config.env[ env ].ssl !== undefined && - config.env[ env ].ssl.port === undefined + ! config.env[ env ].ssl.port ) { throw new ValidationError( `The "${ env }" environment has an invalid SSL port.` @@ -219,7 +236,12 @@ function validatePortUniqueness( config ) { environmentPorts[ env ] = config.env[ env ].port; - if ( config.env[ env ].ssl !== undefined ) { + if ( + config.env[ env ].ssl !== undefined && + config.env[ env ].ssl.port && + config.env[ env ].ssl.cert && + config.env[ env ].ssl.key + ) { environmentSSLPorts[ env ] = config.env[ env ].ssl.port; } } @@ -247,6 +269,7 @@ function validatePortUniqueness( config ) { } if ( environmentSSLPorts[ env ] === environmentSSLPorts[ check ] ) { + console.log(config); throw new ValidationError( `The "${ env }" and "${ check }" environments may not have the same SSL port.` ); From e6e8893f0a6ecceac289ba607f4bbde1fbed842d Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Wed, 23 Aug 2023 18:15:55 -0500 Subject: [PATCH 07/10] Add ssl to wp-env test/parse-config.js --- packages/env/lib/config/test/parse-config.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/env/lib/config/test/parse-config.js b/packages/env/lib/config/test/parse-config.js index ee808b973b16a4..b415b2151df7f9 100644 --- a/packages/env/lib/config/test/parse-config.js +++ b/packages/env/lib/config/test/parse-config.js @@ -23,6 +23,12 @@ const DEFAULT_CONFIG = { port: 8888, testsPort: 8889, phpVersion: null, + ssl: { + cert: null, + key: null, + port: 8883, + testsPort: 8884, + }, coreSource: { type: 'git', url: 'https://github.com/WordPress/WordPress.git', From a40fbefd0803cc02f6d855aaf53bf0be641bf0ac Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Wed, 23 Aug 2023 19:51:07 -0500 Subject: [PATCH 08/10] Update wp-env README to include SSL support --- packages/env/README.md | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/env/README.md b/packages/env/README.md index fb9e9751d9c666..606c269a08e644 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -183,7 +183,7 @@ Out of the box `wp-env` includes the [WordPress' PHPUnit test files](https://dev While we do provide a default `wp-tests-config.php` file within the environment, there may be cases where you want to use your own. WordPress provides a `WP_TESTS_CONFIG_FILE_PATH` constant that you can use to change the `wp-config.php` file used for testing. Set this to a desired path in your `bootstrap.php` file and the file you've chosen will be used instead of the one included in the environment. -## Using `composer`, `phpunit`, and `wp-cli` tools. +## Using `composer`, `phpunit`, and `wp-cli` tools For ease of use, Composer, PHPUnit, and wp-cli are available for in the environment. To run these executables, use `wp-env run `. For example, `wp-env run cli composer install`, or `wp-env run tests-cli phpunit`. You can also access various shells like `wp-env run cli bash` or `wp-env run cli wp shell`. @@ -262,6 +262,41 @@ Here is a summary: 4. Launch the debugger and put a breakpoint on any line of PHP code. 5. Refresh the URL wp-env is running at and the breakpoint should trigger. +## HTTPS/TLS/SSL Support + +In order to easily add a certificate for HTTPS, configuration options have been added to pass a TLS certificate and key, as well as the ability to define their separate ports, which default to `8883` for development and `8884` for test. This way, you can use whatever tool you like to create a TLS certificate and use it in your environments. + +By using `.wp-env.override.json`, you can define a personal TLS certificate without disrupting a projects `.wp-env.json` configuration. + +This can be defined as root settings, as shown here, which will get moved to the development and tests environments when parsed. + +```json +{ + "ssl": { + "cert": "\etc\ssl\certs\localhost.crt", + "key": "\etc\ssl\certs\localhost.key", + "port": 8883, + "testsPort": 8884, + } +} +``` + +Or it can be defined per environment: + +```json +{ + "env": { + "development": { + "ssl": { + "cert": "\etc\ssl\certs\localhost.crt", + "key": "\etc\ssl\certs\localhost.key", + "port": 8883, + } + } + } +} +``` + ## Command reference `wp-env` creates generated files in the `wp-env` home directory. By default, this is `~/.wp-env`. The exception is Linux, where files are placed at `~/wp-env` [for compatibility with Snap Packages](https://github.com/WordPress/gutenberg/issues/20180#issuecomment-587046325). The `wp-env` home directory contains a subdirectory for each project named `/$md5_of_project_path`. To change the `wp-env` home directory, set the `WP_ENV_HOME` environment variable. For example, running `WP_ENV_HOME="something" wp-env start` will download the project files to the directory `./something/$md5_of_project_path` (relative to the current directory). @@ -487,6 +522,7 @@ You can customize the WordPress installation, plugins and themes that the develo | `"themes"` | `string[]` | `[]` | A list of themes to install in the environment. | | `"port"` | `integer` | `8888` (`8889` for the tests instance) | The primary port number to use for the installation. You'll access the instance through the port: 'http://localhost:8888'. | | `"testsPort"` | `integer` | `8889` | The port number for the test site. You'll access the instance through the port: 'http://localhost:8889'. | +| `"ssl"` | `Object` | `{ "cert": null, "key": null, "port": 8883, "testsPort": 8884 }` | Defines options for SSL/TLS/HTTPS support. Providing a path for `cert` and `key` will enable HTTPS. | | `"config"` | `Object` | See below. | Mapping of wp-config.php constants to their desired values. | | `"mappings"` | `Object` | `"{}"` | Mapping of WordPress directories to local directories to be mounted in the WordPress instance. | From a099f01bbed202b4f5510208645e05d2511cf93f Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Thu, 24 Aug 2023 17:49:35 -0500 Subject: [PATCH 09/10] Fix missing env ssl object if ports undefined. Should use default ports if a cert and key are defined. --- .../env/lib/build-docker-compose-config.js | 4 +- packages/env/lib/config/merge-configs.js | 4 + .../env/lib/config/post-process-config.js | 75 +++++++------------ packages/env/lib/init-config.js | 22 ++++-- 4 files changed, 50 insertions(+), 55 deletions(-) diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index 28208817efa225..4f623ad2994194 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -55,8 +55,8 @@ function getMounts( : `tests-user-home:/home/${ hostUsername }`; const sslMount = []; - if (config.ssl !== undefined && config.ssl.cert) { - sslMount.push(workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl`); + if ( config.ssl !== undefined && config.ssl.cert ) { + sslMount.push( workDirectoryPath + `/ssl:/home/${ hostUsername }/ssl` ); } const corePHPUnitMount = `${ path.join( diff --git a/packages/env/lib/config/merge-configs.js b/packages/env/lib/config/merge-configs.js index bccfcc4da3e0dd..4cf50f06da105c 100644 --- a/packages/env/lib/config/merge-configs.js +++ b/packages/env/lib/config/merge-configs.js @@ -53,6 +53,10 @@ function mergeConfig( config, toMerge ) { ); break; } + case 'ssl': { + config.ssl = Object.assign( config.ssl, toMerge.ssl ); + break; + } // Environment-specific config options are recursively merged. case 'env': { diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index 2aa4aa6b888f69..d48d8cbd01c677 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -65,64 +65,44 @@ function mergeRootToEnvironments( config ) { } // Check if ssl is set and if it is, move it to the environment configs. - if ( - config.ssl !== undefined && - config.ssl.cert && - config.ssl.key - ) { + if ( config.ssl !== undefined && config.ssl.cert && config.ssl.key ) { removedRootOptions.ssl = {}; - config.env.development.ssl = {}; - config.env.tests.ssl = {}; - if ( - config.ssl.port !== undefined && - config.env.development.ssl !== undefined && - config.env.development.ssl.port === undefined - ) { - removedRootOptions.ssl.port = config.ssl.port; - config.env.development.ssl.port = config.ssl.port; - delete config.ssl.port; + + // Create ssl objects if they don't exist. + if ( config.env.development.ssl === undefined ) { + config.env.development.ssl = {}; } - if ( - config.ssl.testsPort !== undefined && - config.env.tests.ssl !== undefined && - config.env.tests.ssl.port === undefined - ) { - removedRootOptions.ssl.testsPort = config.ssl.testsPort; - config.env.tests.ssl.port = config.ssl.testsPort; - delete config.ssl.testsPort; + if ( config.env.tests.ssl === undefined ) { + config.env.tests.ssl = {}; } - if ( config.ssl.cert ) { + + // Move the ssl options to the environment configs. + if ( config.ssl.port !== undefined ) { if ( config.env.development.ssl !== undefined && - config.env.development.ssl.cert === undefined + config.env.development.ssl.port === undefined ) { + config.env.development.ssl = {}; config.env.development.ssl.cert = config.ssl.cert; - } - if ( - config.env.tests.ssl !== undefined && - config.env.tests.ssl.cert === undefined - ) { - config.env.tests.ssl.cert = config.ssl.cert; - } - removedRootOptions.ssl.cert = config.ssl.cert; - delete config.ssl.cert; - } - if ( config.ssl.key ) { - if ( - config.env.development.ssl !== undefined && - config.env.development.ssl.key === undefined - ) { config.env.development.ssl.key = config.ssl.key; + config.env.development.ssl.port = config.ssl.port; + removedRootOptions.ssl.port = config.ssl.port; } + } + if ( config.ssl.testsPort !== undefined ) { if ( config.env.tests.ssl !== undefined && - config.env.tests.ssl.key === undefined + config.env.tests.ssl.port === undefined ) { + config.env.tests.ssl = {}; + config.env.tests.ssl.cert = config.ssl.cert; config.env.tests.ssl.key = config.ssl.key; + config.env.tests.ssl.port = config.ssl.testsPort; + removedRootOptions.ssl.testsPort = config.ssl.testsPort; } - removedRootOptions.ssl.key = config.ssl.key; - delete config.ssl.key; } + removedRootOptions.ssl.cert = config.ssl.cert; + removedRootOptions.ssl.key = config.ssl.key; delete config.ssl; } else if ( config.ssl !== undefined && @@ -181,10 +161,10 @@ function appendPortToWPConfigs( config ) { let port = config.env[ env ].port; if ( - config.env[ env ].ssl && + config.env[ env ].ssl && config.env[ env ].ssl.cert && config.env[ env ].ssl.key - ) { + ) { port = config.env[ env ].ssl.port; if ( config.env[ env ].config[ option ].startsWith( 'http://' ) @@ -227,6 +207,8 @@ function validatePortUniqueness( config ) { } if ( config.env[ env ].ssl !== undefined && + config.env[ env ].ssl.cert && + config.env[ env ].ssl.key && ! config.env[ env ].ssl.port ) { throw new ValidationError( @@ -238,7 +220,7 @@ function validatePortUniqueness( config ) { if ( config.env[ env ].ssl !== undefined && - config.env[ env ].ssl.port && + config.env[ env ].ssl.port && config.env[ env ].ssl.cert && config.env[ env ].ssl.key ) { @@ -269,7 +251,6 @@ function validatePortUniqueness( config ) { } if ( environmentSSLPorts[ env ] === environmentSSLPorts[ check ] ) { - console.log(config); throw new ValidationError( `The "${ env }" and "${ check }" environments may not have the same SSL port.` ); diff --git a/packages/env/lib/init-config.js b/packages/env/lib/init-config.js index 150ac724943f29..aa70dd3ce29fc2 100644 --- a/packages/env/lib/init-config.js +++ b/packages/env/lib/init-config.js @@ -197,6 +197,21 @@ function installDependencies( service, env, config ) { // At times we may need to evaluate the environment. This is because the // WordPress image uses Ubuntu while the CLI image uses Alpine. + // Determine support for SSL + let SSLSupport = ''; + if ( + config.env[ env ].ssl && + config.env[ env ].ssl.cert && + config.env[ env ].ssl.key + ) { + SSLSupport = '# Enable SSL support\n'; + SSLSupport += enableSSL( + config.env[ env ].ssl.cert, + config.env[ env ].ssl.key, + config.workDirectoryPath + ); + } + // Start with some environment-specific dependency installations. switch ( service ) { case 'wordpress': { @@ -214,12 +229,7 @@ RUN apt-get -qy install git RUN apt-get -qy install sudo RUN echo "#$HOST_UID ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers -# Enable SSL support -${ enableSSL( - config.env[ env ].ssl.cert, - config.env[ env ].ssl.key, - config.workDirectoryPath -) }`; +${ SSLSupport }`; break; } case 'cli': { From c8fd24c5d44ad6426ba3ee30bd96e8757fc6e192 Mon Sep 17 00:00:00 2001 From: Brennan Goewert Date: Fri, 25 Aug 2023 16:59:58 -0500 Subject: [PATCH 10/10] Fix env ssl environment variable overrides not overriding --- packages/env/README.md | 2 +- .../get-config-from-environment-vars.js | 2 +- packages/env/lib/config/parse-config.js | 21 ++++++++++++------- .../env/lib/config/post-process-config.js | 12 +++-------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/env/README.md b/packages/env/README.md index 606c269a08e644..5742146bdcabb6 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -526,7 +526,7 @@ You can customize the WordPress installation, plugins and themes that the develo | `"config"` | `Object` | See below. | Mapping of wp-config.php constants to their desired values. | | `"mappings"` | `Object` | `"{}"` | Mapping of WordPress directories to local directories to be mounted in the WordPress instance. | -_Note: the port number environment variables (`WP_ENV_PORT` and `WP_ENV_TESTS_PORT`) take precedent over the .wp-env.json values._ +_Note: the port number environment variables (`WP_ENV_PORT`, `WP_ENV_TESTS_PORT`, `WP_ENV_SSL_PORT`, `WP_ENV_SSL_TESTS_PORT`) take precedent over the .wp-env.json values._ Several types of strings can be passed into the `core`, `plugins`, `themes`, and `mappings` fields. diff --git a/packages/env/lib/config/get-config-from-environment-vars.js b/packages/env/lib/config/get-config-from-environment-vars.js index 360cd27c790ede..ea7ca97c4a6c40 100644 --- a/packages/env/lib/config/get-config-from-environment-vars.js +++ b/packages/env/lib/config/get-config-from-environment-vars.js @@ -36,7 +36,7 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) { testsPort: getPortFromEnvironmentVariable( 'WP_ENV_TESTS_PORT' ), ssl: { port: getPortFromEnvironmentVariable( 'WP_ENV_SSL_PORT' ), - testPort: getPortFromEnvironmentVariable( 'WP_ENV_SSL_TESTS_PORT' ), + testsPort: getPortFromEnvironmentVariable( 'WP_ENV_SSL_TESTS_PORT' ), }, lifecycleScripts: getLifecycleScriptOverrides(), }; diff --git a/packages/env/lib/config/parse-config.js b/packages/env/lib/config/parse-config.js index 436b3295bf82f9..32bf33d7a622d7 100644 --- a/packages/env/lib/config/parse-config.js +++ b/packages/env/lib/config/parse-config.js @@ -299,14 +299,19 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) { overrideConfig.env.tests.port = overrides.testsPort; } - if ( overrides.ssl && overrides.ssl.port ) { - overrideConfig.ssl.port = overrides.ssl.port; - overrideConfig.env.development.ssl.port = overrides.ssl.port; - } - - if ( overrides.ssl && overrides.ssl.testsPort ) { - overrideConfig.ssl.testsPort = overrides.ssl.testsPort; - overrideConfig.env.tests.ssl.port = overrides.ssl.testsPort; + if ( overrides.ssl ) { + overrideConfig.ssl = {}; + overrideConfig.env.development.ssl = {}; + overrideConfig.env.tests.ssl = {}; + + if ( overrides.ssl.port ) { + overrideConfig.ssl.port = overrides.ssl.port; + overrideConfig.env.development.ssl.port = overrides.ssl.port; + } + if ( overrides.ssl.testsPort ) { + overrideConfig.ssl.testsPort = overrides.ssl.testsPort; + overrideConfig.env.tests.ssl.port = overrides.ssl.testsPort; + } } if ( overrides.coreSource ) { diff --git a/packages/env/lib/config/post-process-config.js b/packages/env/lib/config/post-process-config.js index d48d8cbd01c677..53ef712a1c64bf 100644 --- a/packages/env/lib/config/post-process-config.js +++ b/packages/env/lib/config/post-process-config.js @@ -79,10 +79,8 @@ function mergeRootToEnvironments( config ) { // Move the ssl options to the environment configs. if ( config.ssl.port !== undefined ) { if ( - config.env.development.ssl !== undefined && - config.env.development.ssl.port === undefined + config.env.development.ssl !== undefined ) { - config.env.development.ssl = {}; config.env.development.ssl.cert = config.ssl.cert; config.env.development.ssl.key = config.ssl.key; config.env.development.ssl.port = config.ssl.port; @@ -91,10 +89,8 @@ function mergeRootToEnvironments( config ) { } if ( config.ssl.testsPort !== undefined ) { if ( - config.env.tests.ssl !== undefined && - config.env.tests.ssl.port === undefined + config.env.tests.ssl !== undefined ) { - config.env.tests.ssl = {}; config.env.tests.ssl.cert = config.ssl.cert; config.env.tests.ssl.key = config.ssl.key; config.env.tests.ssl.port = config.ssl.testsPort; @@ -105,9 +101,7 @@ function mergeRootToEnvironments( config ) { removedRootOptions.ssl.key = config.ssl.key; delete config.ssl; } else if ( - config.ssl !== undefined && - config.ssl.cert === undefined && - config.ssl.key === undefined + config.ssl !== undefined && Object.keys( config.ssl ).length === 0 ) { removedRootOptions.ssl = config.ssl; delete config.ssl;