in reply to DBD::mysql w/SSL certs extracted from variables

G'day wwinfrey,

"The same DSN works if I provide filesystem paths."

Although you're naming those variables as $xxx_file_location, they're not locations at all: they're filehandles which will stringify to something like GLOB(0xffffffffffff):

$ perl -wE 'my $x; open my $f, "<", \$x; say $f' GLOB(0x7fb509805480)

As a basic debugging technique, print questionable strings before using them. In this case, I imagine $dsn contains parts that look like:

...mysql_ssl=1;mysql_ssl_ca_file=GLOB(0xffffffffffff);...

Purely as a suggestion, because I have no way of testing this, you could look at the core module File::Temp.

— Ken

Replies are listed 'Best First'.
Re^2: DBD::mysql w/SSL certs extracted from variables
by wwinfrey (Acolyte) on Dec 09, 2015 at 22:24 UTC
    Yeah, I usually print my variables out using Data::Dumper, and I think I can see the issue (although, not the solution). I'm passing a filehandle in the DSN string, not a file location, which is why my DSN looks like this:
    $VAR1 = 'dbi:mysql:database=database;host=localhost;port=3306;mysql_ss +l=1;mysql_ssl_ca_file=GLOB(0x1008060e8);mysql_ssl_client_key=GLOB(0x1 +0082e750);mysql_ssl_client_cert=GLOB(0x100806268)';
    as opposed to this:
    $VAR1 = 'dbi:mysql:database=database;host=localhost;port=3306;mysql_ss +l=1;mysql_ssl_ca_file=/path/to/my/ca-cert.pem;mysql_ssl_client_key=/p +ath/to/my/client-key.pem;mysql_ssl_client_cert=/path/to/my/client-cer +t.pem';
    I'm currently using File::Temp, but it writes temp files out to the filesystem, which I'm trying to avoid. Having these certs in the source and present in the running process is one thing. I'm trying to avoid introducing another vector by writing them out to a third location. I'm looking into the named pipe solution, which will be tricky given that we're wrapping this code into a binary using PerlApp, and that it needs to run on Solaris, Linux and Windows.
      I've got this working on the Unix-y platforms, but of course Windows is giving me issues.

      Using File::Temp to write the certs to the filesystem works just fine, but when I try to pass them in as a connection string with $file_temp->filename, the drive letter is stripped and the path is, in general, unusable.

      For example, if I write the cert out using:

      my $mysql_ssl_ca_fh = File::Temp->new( UNLINK => 1, SUFFIX => '.pem'); my $mysql_ssl_ca_file = $mysql_ssl_ca_fh->filename; print $mysql_ssl_ca_fh $SSL_CA_FILE_STRING;

      I'll get a randomly-named file (for the purpose of this post, let's call it "foo.pem") in C:\ that contains the contents of $SSL_CA_FILE_STRING.

      However, when I try to read it back in, like so:

      sub dbconnect { my $engine = shift; my $dsn = q{dbi:mysql:database=database;} . q{host=} . $engine . q{;port=3306} . q{;mysql_ssl=1} . q{;mysql_ssl_ca_file=} . $mysql_ssl_ca_file . q{;mysql_ssl_client_cert=} . $mysql_ssl_cert_file . q{;mysql_ssl_client_key=} . $mysql_ssl_key_file . q{;mysql_ssl_cipher=} . $SSL_CIPHER; my $dbuser = q{supportclient}; my $dbpw = q{}; my $dbh = DBI->connect( $dsn, $dbuser, $dbpw ) || confess; return $dbh; }

      I would expect $mysql_ssl_ca_file to contain the value "C:\foo.pem", but it instead contains "\foo.pem", so perhaps File::Temp isn't compatible with Windows paths. Not that it matters. When I try to debug the DSN connection string using dbish, as I normally do, it doesn't seem to understand Windows paths either, so I'm at a loss.

      Anyone have any suggestions for how I can create a path to a file on a Windows filesystem that will work in a DBD::mysql DSN? It's not clear from the docs (or maybe I'm not looking in the right place) what the expected format is. The only thing that seems to work (dbish-wise) is being in the same directory as the cert files, and not using any paths.