Excon gem SSL issue
I got this issue while trying to get CarrierWave to upload pictures to S3 from an EC2 instance:
ERROR: Excon::Errors::SocketError: Unable to verify certificate,
please set Excon.defaults[:ssl_ca_path] = path_to_certs,
Excon.defaults[:ssl_ca_file] = path_to_file, or
Excon.defaults[:ssl_verify_peer] = false
This problem came about when an action in a controller wasn’t working properly.
The most frustrating part of solving this issue was a 500 Internal Server Error
was recorded in the logs with no explanation! To fix this, I went into
app/config/environments/production.rb
and made the following change:
config.consider_all_requests_local = true
By setting config.consider_all_requests_local = true
, the logs finally reported
the previously mentioned Excon error.
I booted my EC2 instance with a custom AMI that I had created. It turns out my custom AMI didn’t have any CA certificates, so it was necessary to run the following commands:
$ sudo update-ca-certificates
$ sudo apt-get remove -y --force-yes --purge ec2-ami-tools
$ sudo apt-get install -y --force-yes ec2-ami-tools
The first command is a Debian/Ubuntu command to update the CA certificates. The second two commands remove and reinstall the ec2-ami-tools to retrieve the CA certificates for Amazon.
Finally, I went into my Rails console, and used the following command to determine the location of the Excon gem it was using.
> $:.grep(/excon/)
["/path/to/excon/gem"]
I changed into /path/to/excon/gem
and modified excon/ssl_socket.rb
. Specifically,
I modified the params hash so that the Excon gem could find the CA certificates.
# create ssl context
ssl_context = OpenSSL::SSL::SSLContext.new
params[:ssl_ca_path] = '/etc/ssl/certs' # <--- Line I added
if params[:ssl_verify_peer]
...
This change allowed CarrierWave to upload pictures to S3 successfully because now my EC2 instance could verify it was communicating with S3. I also could have modified params in a different way:
params[:ssl_verify_peer] = false
This tells Excon to not verify its peer, which is not secure, so I stuck with my first solution.