diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index a7a4a0bf..f8fce960 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -88,6 +88,7 @@ jobs: - name: Output logs if: ${{ always() }} run: | - [[ -f "/opt/easyengine/logs/install.log" ]] && cat /opt/easyengine/logs/install.log || echo 'No install log.' - [[ -f "/opt/easyengine/logs/ee.log" ]] && cat /opt/easyengine/logs/ee.log || echo 'No run log.' + # The logs directory is readable by root only. + sudo test -f /opt/easyengine/logs/install.log && sudo cat /opt/easyengine/logs/install.log || echo 'No install log.' + sudo test -f /opt/easyengine/logs/ee.log && sudo cat /opt/easyengine/logs/ee.log || echo 'No run log.' diff --git a/src/helper/site-utils.php b/src/helper/site-utils.php index 3515b11c..fc51ca8c 100644 --- a/src/helper/site-utils.php +++ b/src/helper/site-utils.php @@ -108,6 +108,11 @@ function get_site_info( $args, $site_enabled_check = true, $exit_if_not_found = return false; } + // Keeps this site's credentials out of the logs of whatever the command runs next. + if ( method_exists( 'EE', 'obfuscate' ) ) { + EE::obfuscate( [ $data->db_password, $data->db_root_password, $data->app_admin_password ] ); + } + if ( ! $data->site_enabled && $site_enabled_check ) { \EE::error( sprintf( 'Site %1$s is not enabled. Use `ee site enable %1$s` to enable it.', $data->site_url ) ); } @@ -182,11 +187,12 @@ function sql_quote_identifier( $value ) { * * The SQL goes through a file, so names and passwords never pass through a shell. * - * @param string $sql SQL statements to run. + * @param string $sql SQL statements to run. + * @param array $obfuscate Secrets in the SQL, masked in the logged output. * * @return bool|object Result of EE::launch(), or false if the SQL could not be copied to the container. */ -function run_global_db_sql( $sql ) { +function run_global_db_sql( $sql, $obfuscate = [] ) { $sql_path = tempnam( \EE\Utils\get_temp_dir(), 'ee-db-' ); file_put_contents( $sql_path, $sql ); @@ -197,9 +203,10 @@ function run_global_db_sql( $sql ) { return false; } - $script = sprintf( 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -N -B < %1$s; rc=$?; rm -f %1$s; exit $rc', $container_path ); + // The client echoes a failing statement to STDERR, which is logged; `--loose-` only warns on clients without the option. + $script = sprintf( 'mysql --loose-skip-print-query-on-error -uroot -p"$MYSQL_ROOT_PASSWORD" -N -B < %1$s; rc=$?; rm -f %1$s; exit $rc', $container_path ); - return EE::launch( sprintf( 'docker exec %s sh -c %s', GLOBAL_DB_CONTAINER, escapeshellarg( $script ) ) ); + return EE::launch( sprintf( 'docker exec %s sh -c %s', GLOBAL_DB_CONTAINER, escapeshellarg( $script ) ), false, true, $obfuscate ); } /** @@ -338,13 +345,13 @@ function create_user_in_db( $db_host, $db_name = '', $db_user = '', $db_pass = ' $user = sql_quote_string( $db_user ) . "@'%'"; $database = sql_quote_identifier( $db_name ); - $ok = function ( $sql ) { - $result = run_global_db_sql( $sql ); + $ok = function ( $sql, $obfuscate = [] ) { + $result = run_global_db_sql( $sql, $obfuscate ); return $result && 0 === $result->return_code; }; - if ( ! $ok( sprintf( 'CREATE USER %s IDENTIFIED BY %s;', $user, sql_quote_string( $db_pass ) ) ) ) { + if ( ! $ok( sprintf( 'CREATE USER %s IDENTIFIED BY %s;', $user, sql_quote_string( $db_pass ) ), [ sql_quote_string( $db_pass ), $db_pass ] ) ) { return false; } if ( ! $ok( sprintf( 'CREATE DATABASE %s;', $database ) ) ) { diff --git a/src/site-type/HTML.php b/src/site-type/HTML.php index fc434913..ad06ba07 100644 --- a/src/site-type/HTML.php +++ b/src/site-type/HTML.php @@ -186,7 +186,8 @@ public function info( $args, $assoc_args ) { if ( 'json' === $format ) { $site = (array) Site::find( $this->site_data['site_url'] ); $site = reset( $site ); - EE::log( json_encode( $site ) ); + // Printed for the user only: it holds the site's credentials. + EE::line( json_encode( $site ) ); return; }