• Resolved rmayer

    (@rmayer)


    HI,

    first, thank you for all your work on this plugin.

    I had a fatal error, which I think is an issue regarding the WP docker-image.

    The problem is when I update the core from 4.4.1 to 4.7.2 the way to declare DB connection on wp-config.php changed drastically and I think it seriously affects this plugin.

    I usually had string in the defines of Eg: DB_NAME.

    But now:
    define( ‘DB_NAME’, getenv_docker(‘WORDPRESS_DB_NAME’, ‘wordpress’) );

    this is something you are aware or there is a way to solve it?
    thanks!

Viewing 4 replies - 1 through 4 (of 4 total)
  • Plugin Author nintechnet

    (@nintechnet)

    That breaks the Full WAF mode. The firewall can work in WordPress WAF mode though.

    The problem is how NinjaFirewall can retrieve the DB_NAME value?

    I can see this code: https://github.com/docker-library/wordpress/blob/master/wp-config-docker.php

    // ** MySQL settings - You can get this info from your web host ** //
    /** The name of the database for WordPress */
    define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
    
    /** MySQL database username */
    define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'example username') );
    
    /** MySQL database password */
    define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'example password') );
    

    Does that mean that ‘wordpress’ is the DB_NAME, ‘example username’ is DB_USER and ‘example password’ is DB_PASSWORD?

    Thread Starter rmayer

    (@rmayer)

    Hey, thanks for your answer,

    Does that mean that ‘wordpress’ is the DB_NAME, ‘example username’ is DB_USER and ‘example password’ is DB_PASSWORD?

    NO, that is used if there is no env variable.
    I expect to use the value inside those variables, for that I redeclare the function that takes care of that.

    Further research and beta implementations:

    The issue is that NF [ninjafirewall] needs to initialize a DB connection before WordPress is initiated.

    That was done with some regex that looks for those string connections in wp-config but now it’s broken due the wordpress docker image consume a enviroment variable instead of hardcoded strings.

    I made a quick patch but I would like to have something more “reliable”.
    I apply this as a composer patch with cwegans and this allows me to upgrade core.

    https://gist.githubusercontent.com/renzit/4a7f1f17c7635c8f703d616fa02a2cdc/raw/37998098354b9010f37719bb32f242e9435e9ea8/gistfile1.patch

    diff --git a/lib/firewall.php b/lib/firewall.php
    index 8ed362b33..30e7e2568 100644
    --- a/lib/firewall.php
    +++ b/lib/firewall.php
    @@ -387,7 +387,32 @@ function nfw_connect() {
     		} elseif ( preg_match('/^\s*\$table_prefix\s*=\s*[\'"](.+?)[\'"]/', $nfw_['line'], $nfw_['match']) ) {
     			$nfw_['table_prefix'] = $nfw_['match'][1];
     		}
    +		if( strpos( $nfw_['line'], 'getenv_docker' )){
    +			if(preg_match("/define\( '(DB_.*?)', getenv_docker\(\'(.*WORDPRESS.*)\', \'(.*)'\)/", $nfw_['line'], $nfw_['match'])){
    +
    +				if (!function_exists('getenv_docker')) {
    +					// https://github.com/docker-library/wordpress/issues/588 (WP-CLI will load this file 2x)
    +					function getenv_docker($env, $default) {
    +						if ($fileEnv = getenv($env . '_FILE')) {
    +							return rtrim(file_get_contents($fileEnv), "\r\n");
    +						}
    +						else if (($val = getenv($env)) !== false) {
    +							return $val;
    +						}
    +						else {
    +							return $default;
    +						}
    +					}
    +				}
    +				$key_string_connection = $nfw_['match'][1];
    +				$env_constant = $nfw_['match'][2];
    +				$env_default =  $nfw_['match'][3];
    +				$nfw_[$key_string_connection] = getenv_docker($env_constant, $env_default);
    +				$nfw_['table_prefix'] = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
    +			}
    +		}
     	}
    +
     	fclose($nfw_['fh']);
     	unset($wp_config);
     	if ( (! isset($nfw_['DB_NAME'])) || (! isset($nfw_['DB_USER'])) || (! isset($nfw_['DB_PASSWORD'])) ||	(! isset($nfw_['DB_HOST'])) || (! isset($nfw_['table_prefix'])) ) {
    • This reply was modified 3 years, 7 months ago by rmayer.
    • This reply was modified 3 years, 7 months ago by rmayer.
    Plugin Author nintechnet

    (@nintechnet)

    That may work but will be very slow to parse.
    I would recommend to use the .htninja and pass the SQL link to the firewall: https://blog.nintechnet.com/ninjafirewall-wp-edition-the-htninja-configuration-file/
    Scroll down to the “Giving NinjaFirewall a MySQLi link identifier” section.
    Here’s an example:

    <?php
    /*
     +===========================================================================================+
     | NinjaFirewall optional configuration file                                                 |
     |                                                                                           |
     | See: https://blog.nintechnet.com/ninjafirewall-wp-edition-the-htninja-configuration-file/ |
     +===========================================================================================+
    */
    if (!function_exists('getenv_docker')) {
       // https://github.com/docker-library/wordpress/issues/588 (WP-CLI will load this file 2x)
       function getenv_docker($env, $default) {
          if ($fileEnv = getenv($env . '_FILE')) {
             return rtrim(file_get_contents($fileEnv), "\r\n");
          } else if (($val = getenv($env)) !== false) {
             return $val;
          } else {
             return $default;
          }
       }
    }
    // Connect to the DB and store the link into "$GLOBALS['nfw_mysqli']":
    $GLOBALS['nfw_mysqli'] = new mysqli(
       getenv_docker('WORDPRESS_DB_HOST', 'mysql'),
       getenv_docker('WORDPRESS_DB_USER', 'example username'),
       getenv_docker('WORDPRESS_DB_PASSWORD', 'example password'),
       getenv_docker('WORDPRESS_DB_NAME', 'wordpress')
    );
    // We need the table prefix too:
    $GLOBALS['nfw_table_prefix'] = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
    
    

    Then, log in to WP, go to “NinjaFirewall > Dashboard” and make sure the firewall detected the link:

    If that works, I’ll add a warning to the firewall when upgrading to Full WAF with a link to this post if it detects Docker (I’m not sure yet what is the best way to detect it though).

    Thread Starter rmayer

    (@rmayer)

    Hey, thank you.

    That works as expected!

    And I agree, a warning would be nice to have!

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Fatal error Cannot retrieve WordPress credentials using docker-image’ is closed to new replies.