skip to Main Content

I’m new to PHP and having issue with database.php. Basically i’m trying to retrieve the password to connect the DB from PHP. The password stored in AWS secret Manager and have a code to get the secret. This is working fine and trying to assign the secret to the database.php config but got the error

Error: Fatal Error (64): Constant expression contains invalid
operations in [/var/www/myapp/Config/database.php.

The variable $mypassword contains the secret and couldn’t pass it to DB.

this is the database.php config:

<?php
$conf = require ("/var/www/myapp/Config/test.php");
class DATABASE_CONFIG {
          public $default = array(
                  'datasource' => 'Database/Mysql',
                  //'datasource' => 'Database/Postgres',
                  'persistent' => 'false',
                 'host' => '.rds.amazonaws.com',
                 'login' => 'admin',
                  'port' => '3306',
                 'password' => $conf["$mypassword"],
                  'database' => 'test',
                  'prefix' => '',
                  'encoding' => 'utf8',
             
          );
}

Code from test.php to get the secret form AWS Secret Manager and i was able to print the secret.

<?php

/**
 * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * This file is licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 * http://aws.amazon.com/apache2.0/
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

// snippet-start:[secretsmanager.php.get_secret_value.complete]
// snippet-start:[secretsmanager.php.get_secret_value.import]
require 'vendor/autoload.php';

use AwsSecretsManagerSecretsManagerClient;
use AwsExceptionAwsException;

// snippet-end:[secretsmanager.php.get_secret_value.import]

/**
 * In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
 * See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
 * We rethrow the exception by default.
 *
 * This code expects that you have AWS credentials set up per:
 * https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html
 */

// Create a Secrets Manager Client
// snippet-start:[secretsmanager.php.get_secret_value.main]
$client = new SecretsManagerClient([
    'profile' => 'default',
    'version' => '2017-10-17',
    'region' => 'us-east-1',
]);

$secretName = 'MySecretName';

try {
    $result = $client->getSecretValue([
        'SecretId' => $secretName,
    ]);
} catch (AwsException $e) {
    $error = $e->getAwsErrorCode();
    if ($error == 'DecryptionFailureException') {
        // Secrets Manager can't decrypt the protected secret text using the provided AWS KMS key.
        // Handle the exception here, and/or rethrow as needed.
        throw $e;
    }
    if ($error == 'InternalServiceErrorException') {
        // An error occurred on the server side.
        // Handle the exception here, and/or rethrow as needed.
        throw $e;
    }
    if ($error == 'InvalidParameterException') {
        // You provided an invalid value for a parameter.
        // Handle the exception here, and/or rethrow as needed.
        throw $e;
    }
    if ($error == 'InvalidRequestException') {
        // You provided a parameter value that is not valid for the current state of the resource.
        // Handle the exception here, and/or rethrow as needed.
        throw $e;
    }
    if ($error == 'ResourceNotFoundException') {
        // We can't find the resource that you asked for.
        // Handle the exception here, and/or rethrow as needed.
        throw $e;
    }
}
// Decrypts secret using the associated KMS CMK.
// Depending on whether the secret is a string or binary, one of these fields will be populated.
if (isset($result['SecretString'])) {
    $secret = $result['SecretString'];
} else {
    $secret = base64_decode($result['SecretBinary']);
}
print $secret;
$secretArray = json_decode($secret, true);
$username = $secretArray['username'];
$mypassword = $secretArray['password'];

// Your code goes here;
// snippet-end:[secretsmanager.php.get_secret_value.main]
// snippet-end:[secretsmanager.php.get_secret_value.complete]

2

Answers


  1. Maybe you can try something like this (very naive solution).

    Your mistake is that $conf does not exist when you are defining your class. $conf exists only at "run time"

    <?php
    class DatabaseConfiguration {
        // should probably be private
        public $default = array(
            'datasource' => 'Database/Mysql',
            //'datasource' => 'Database/Postgres',
            'persistent' => 'false',
            'host' => '.rds.amazonaws.com',
            'login' => 'admin',
            'port' => '3306',
            'password' => null,
            'database' => 'test',
            'prefix' => '',
            'encoding' => 'utf8',
        );
    
        public function __construct(array $configuration)
        {
            if(array_key_exists('mypassword', $configuration)) {
                throw new Exception(
                    'Invalid configuration. You have to provide a password for the database'
                );
            }
            $this->default['password'] = $configuration['mypassword'];
        }
    }
    
    $conf = require ("/var/www/myapp/Config/test.php");
    $configurationInstance = new DatabaseConfiguration($conf);
    
    Login or Signup to reply.
  2. You need to do everything inside the DATABASE_CONFIG class to set the necessary values. (You can’t pass values in through the constructor easily because CakePHP controls instantiating the class.) I’ve taken the script to get the secrets and encapsulated it in a function inside the class. The constructor then calls this function and uses the returned secret in the database configuration array, which it then assigns as the default configuration.

    <?php
    
    require 'vendor/autoload.php';
    
    use AwsSecretsManagerSecretsManagerClient;
    use AwsExceptionAwsException;
    
    class DATABASE_CONFIG {
        public $default; 
        public function __construct() {
            $secretArray = $this->getSecrets();
            $config = array(
                      'datasource' => 'Database/Mysql',
                      //'datasource' => 'Database/Postgres',
                      'persistent' => 'false',
                     'host' => '.rds.amazonaws.com',
                     'login' => 'admin',
                      'port' => '3306',
                     'password' => $secretArray['password'],
                      'database' => 'test',
                      'prefix' => '',
                      'encoding' => 'utf8',
                 
              );        
            $this->default = $config;
        }
    
        private function getSecrets()
        {
        
            $client = new SecretsManagerClient([
                'profile' => 'default',
                'version' => '2017-10-17',
                'region' => 'us-east-1',
            ]);
    
            $secretName = 'MySecretName';
    
            try {
                $result = $client->getSecretValue([
                    'SecretId' => $secretName,
                ]);
            } catch (AwsException $e) {
                $error = $e->getAwsErrorCode();
                if ($error == 'DecryptionFailureException') {
                    // Secrets Manager can't decrypt the protected secret text using the provided AWS KMS key.
                    // Handle the exception here, and/or rethrow as needed.
                    throw $e;
                }
                if ($error == 'InternalServiceErrorException') {
                    // An error occurred on the server side.
                    // Handle the exception here, and/or rethrow as needed.
                    throw $e;
                }
                if ($error == 'InvalidParameterException') {
                    // You provided an invalid value for a parameter.
                    // Handle the exception here, and/or rethrow as needed.
                    throw $e;
                }
                if ($error == 'InvalidRequestException') {
                    // You provided a parameter value that is not valid for the current state of the resource.
                    // Handle the exception here, and/or rethrow as needed.
                    throw $e;
                }
                if ($error == 'ResourceNotFoundException') {
                    // We can't find the resource that you asked for.
                    // Handle the exception here, and/or rethrow as needed.
                    throw $e;
                }
            }
            if (isset($result['SecretString'])) {
                $secret = $result['SecretString'];
            } else {
                $secret = base64_decode($result['SecretBinary']);
            }
            //print $secret;
            $secretArray = json_decode($secret, true);
            return $secretArray;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search