I'm trying to move my application to Heroku but I'm having problems accessing the database via PHP. I'm able to access the AWS database from my machine locally, but when I deploy to Heroku it fails.
I've followed directions from the main page: https://devcenter.heroku.com/articles/amazon-rds
And I've tried other threads on SO/AWS:
Getting Mysql2::Error (SSL connection error: ASN: bad other signature confirmation) on Heroku App with AWS RDS
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.SSLSupport
I also saw instructions here:
https://devcenter.heroku.com/articles/getting-started-with-php#provision-a-database
But I'm trying to port an existing application so I need to stick with my existing PDO syntax. I'm trying to get this to work:
$dbInfo = getenv('DATABASE_URL');
try{
$dbh = new PDO($dbInfo);
echo json_encode(array('outcome' => true));
}
catch(PDOException $ex){
echo json_encode(array('outcome' => false, 'message' => 'Unable to connect'));
}
I have the environmental variable setup properly and can run parse_url to access all of the array items; I also have the amazon-rds-ca-cert.pem located in the config folder.
I'm able to login remotely (via SequelPro) and have run the following in the query manager to try to force SSL cert:
GRANT USAGE ON *.* TO 'username'#'%' REQUIRE SSL;
But when I intentionally misspell the cert name my local database can still connect, which makes me think maybe I am missing something with the requirement.
Figured it out; needed to manually specify the SSL certificate within the PDO connection. Also had minor errors in the PDO syntax.
try{
$dbh = new PDO("mysql:host=$pdohost;dbname=$pdodb", $pdouser, $pdopass, array(
PDO::MYSQL_ATTR_SSL_CA =>'path/to/combined-cert.pem'
));
echo json_encode(array('outcome' => true));
}
catch(PDOException $ex){
echo $ex;
echo json_encode(array('outcome' => false, 'message' => 'Unable to connect'));
}
Also needed to be sure to update the AWS inbound rules to 0.0.0.0/0 to allow for Heroku to access.
Related
I am trying to connect to my Google Cloud SQL instance using PHP PDO. If I don't enforce SSL, everything works fine. But if I enforce SQL, I am unable to connect.
I have downloaded the server certificate from my Google Cloud SQL instance, as well as the client certificate (and matching key that I created). I know they're OK, because the following line works fine from the command shell:
mysql -h[myHostIp] -uroot -p --ssl-ca=settings/server-ca.pem --ssl-cert=settings/client-cert.pem --ssl-key=settings/client-key.pem [myDatabase]
However, from the same folder in a standalone PHP file run from the command line, the following PHP code does not:
<?php
$myHostIp = '[myHostIp]';
$myDbName = 'qabtk';
$myDbUser = 'root';
$myDbPassword = '[myPassword]';
$db = new PDO("mysql:host=$myHostIp;dbname=$myDbName", $myDbUser, $myDbPassword, [
PDO::MYSQL_ATTR_INIT_COMMAND => "set names 'utf8'",
PDO::MYSQL_ATTR_SSL_KEY =>'settings/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'settings/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA =>'settings/server-ca.pem',
]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'show databases';
$stmt = $db->prepare($sql);
$stmt->execute([]);
$answer = $stmt->fetchObject();
$stmt->closeCursor();
var_dump($answer);
exit;
Running that code gives the following error:
Trace/BPT trap: 5
If I remove both the client key and client certificate, leaving in only the server certificate, the error changes to:
Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user 'root'#'[client IP address]' (using password: YES)
I've tried the recommendation of adding a PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false, which doesn't make any difference.
Help please!
UPDATE 2022-04-12: I am using this on an Apple silicon Macbook Pro, both directly using MacOS, and inside a Docker container running Ubuntu 18.04. The problem has now disappeared for no apparent reason - there's been much rebooting of many of the components and I didn't track exactly when it went away. However, it requires the line PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false to work which it really shouldn't do. I believe this may be to do with the way Google sets the CN in its certificates for Cloud SQL, but I'm not certain.
I am developing an web application using PHP. I am storing the user credentials on the AWS Cognito service. I am logging in the user to the Cognito using PHP SDK.
I developed the feature successfully. I tested it locally on my machine, it was working. Then I deployed it onto the staging server, it was working on the staging server as well. But when I deployed it on to the live server, it gave me this error:
(1/1) CredentialsException
Error retrieving credentials from the instance profile metadata server. (cURL error 7: Failed to connect to 169.254.169.254 port 80: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html))
This is my code
try{
$client = new CognitoIdentityProviderClient([
'version' => 'latest',
'region' => 'eu-west-2'// env('AWS_REGION', '')
]);
$result = $client->adminInitiateAuth([
'AuthFlow' => 'ADMIN_NO_SRP_AUTH',
'ClientId' => COGNITO_APP_CLIENT_ID,
'UserPoolId' => COGNITO_USER_POOL_ID,
'AuthParameters' => [
'USERNAME' => $request->email,
'PASSWORD' => $request->password,
],
]);
$auth_result = $result->get('AuthenticationResult');
$cognito_access_token = $auth_result['AccessToken'];
if(!empty($cognito_access_token))
{
//register the user
$reg_user = $this->accRepo->register($request);
if($reg_user)
{
Auth::login($reg_user);
$token = $reg_user->createToken($this->tokenTag)->accessToken;
unset($reg_user->password);
return response()->json([ 'success' => true, 'access_token' => $token, 'account' => $reg_user ], SUCCESS_RESPONSE_CODE);
}
}
}
catch(Exception $e)
{
}
I am using the exact code and setting and credentials as the local machine and the staging server for the live server. But it does not work on the live server. Working on the other environments. What might be the error? I am deploying it on Heroku.
I am not familiar with Cognito, but the error you're seeing is that your code is attempting to access the Instance Metadata available in EC2. The AWS PHP SDK has a specific order in which it attempts to locate credentials. Here is an outline of different credential methods using the PHP SDK.
So, I suspect it works on your local machine because you have an IAM profile configured using the AWS CLI aws configure command.
It most likely works on your staging server because that server has an IAM Role attached to the EC2 instance. The PHP doesn't find a locally configured IAM profile, so it then skips to attempting to access the EC2 metadata, which it does successfully, so it gets authenticated.
Now, when you deploy to Heroku, it is no longer on an EC2 instance, or in your local environment. So, your CredentialProvider fails. My suggestion would be to utilize Config Vars in Heroku, then change your code to use CredentialProvider::env() as outlined here. You would need to create an IAM user with the same role as your EC2 instance that works (or enough permissions to do what you need to do). This would allow your application to securely access Cognito from an environment external to AWS.
I'm using Microsoft Azure SQL for my database and I'm trying to connect it to my project on my localhost using XAMPP. When I try to connect to the database using the connect string they provided:
try {
$conn = new PDO("sqlsrv:server = tcp:app.database.windows.net,1433; Database = mydatabase", "{myusername}", "{your_password_here}");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e) {
print("Error connecting to SQL Server.");
die(print_r($e));
}
I keep getting this error:
Error connecting to SQL Server.PDOException Object ( [message:protected] => could not find driver
The error is longer but I think it's related to the driver mentioned at the end. I'm using a mac so any driver I need to install would need to be compatible with it. Thank you for the help in advance.
Azure SQL Database is built on the Microsoft SQL Server engine. So you might consider using pdo-dblib to connect to SQL Server using the PDO on a Mac. You can check out a Stack Overflow question about it here or refer to this setup documentation.
After the driver having been installed, Azure SQL won’t actually accept connection from your local yet. And you might get the following error:
Client with IP address '167.xxx.xxx.xxx' is not allowed to access the
server.
That’s because there is a firewall in the way by default. To enable access, go to the Azure portal, click on All Resources, select your SQL service, click on Firewall in the SETTING menu.
Your client address is conveniently included in the list, so you can just click on Add client IP followed by Save.
Well, when you run your code now, it should connect.
I'm trying to access a remote MySQL Database which is only reachable locally (localhost).
My Code looks like this:
$connection = ssh2_connect('IP to Server', 22);
if (ssh2_auth_password($connection, 'User', 'Password')) {
echo "Authentication Successful!\n";
} else {
die('Authentication Failed...');
}
$tunnel = ssh2_tunnel($connection, '127.0.0.1', 3306);
try {
$this->_connection = new PDO($dsn, $config['login'], $config['password'], $flags);
$this->connected = true;
if (! empty($config['settings'])) {
foreach ($config['settings'] as $key => $value) {
$this->_execute("SET $key=$value");
}
}
} catch (PDOException $e) {
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
The script is successful till $tunnel. The PDO connection fails with "Connection refused". I think PDO is trying to connect to MAMP? The $dsn variable looks like "mysql:host=127.0.0.1;port=3306;dbname=mydb".
How can I tell MAMP, that 127.0.0.1 is on the remote server connected through SSH?
Thank you!
As you already noted, your script is attempting to connect to your local MySQL server instead of the remote one. In order for PDO to establish a connection with the remote server, you could establish an SSH tunnel and forward a local port to the server port. As shown here https://brettrawlins.com/blog/mysql-ssh-tunnel.
To run the ssh command in php: shell_exec(ssh code here)
You might want to see: Connect to a MySQL server over SSH in PHP
However as noted in there as well, this method is relatively slow as you will have to create a new tunnel each time you query the database, making your queries take quite a bit longer. I suppose for a development environment it's a valid option since you don't have a static IP, but I don't see this working in production.
If you are trying to do this for the sake of encryption, I would recommend connecting to your database with SSL. However note that SSL for PDO might not be supported by all PHP versions.
I created a FB app hosted on Heroku.
Instead of Heroku's database I use a mysql database. I made the chage using this code:
heroku config:add DATABASE_URL=mysql://user:pass#server:port/database_name
So far everything is ok but now I have an issue connecting to the database in my index.php file.
I don't know ho to do.
I tried to connect to the DB as I do on my website
try {
$bdd = new PDO('mysql:host=host;dbname=database_name', 'user', 'pass');
}
catch (Exception $e) {
die('Erreur : ' . $e->getMessage());
}
But I have an error in my app:
Application Error
An error occurred in the application and your page could not be served. Please try again in a few moments.
Thank you
Check whether your remote database port is opened for external connection. Look for bind-address configuration of your remote mysql server.