keystonejs cloudinary invalid signature error - upload

I have implemented a Cloudinary type in one of my models, but get this error back when I try and save it to Cloudinary:
Image upload failed - Invalid Signature
ea4401c2ebf292208d28f9dc88c5ff1c4e73761d.
String to sign - 'tags=trial-images_image,trial-
images_image_55ba9896c6d05b8704802f0a,dev&timestamp=1438292137'.
I'm not sure what to do about it, anyone experience this?

You should make sure to calculate the signature correctly. Specifically, you should sign both the tags and the timestamp (including your api_secret of course).

I had the exact same issue.
Please double check that you have the configuration parameters(cloud name, api key, api secret) correctly set up. They can be found by going to the management console on your cloudinary account. (Dashboard > Account Details).
As per their documentation:
(http://cloudinary.com/documentation/rails_additional_topics#configuration_options)
Configuration parameters can be globally set using a cloudinary.yml configuration file, located under the config directory of your Rails project. etc...
Here's an example of a cloudinary.yml file:
production:
cloud_name: "sample"
api_key: "874837483274837"
api_secret: "a676b67565c6767a6767d6767f676fe1"
etc...
... Another configuration option is to use a Rails initializer file. You can place a file named cloudinary.rb in the /config/initializers folder of your Rails project. Here's a sample initializer code:
Cloudinary.config do |config|
config.cloud_name = 'sample'
config.api_key = '874837483274837'
config.api_secret = 'a676b67565c6767a6767d6767f676fe1'
config.cdn_subdomain = true
end
One last configuration option allows you to dynamically configure the Cloudinary library by defining the CLOUDINARY_URL environment variable. The configuration URL is available in the Management Console's dashboard of your account. When using Cloudinary through a PaaS add-on (e.g., Heroku), this environment variable is automatically defined in your deployment environment. Here's a sample value:
CLOUDINARY_URL=cloudinary://874837483274837:a676b67565c6767a6767d6767f676fe1#sample
How I actually solved the issue
I solved the issue by adopting (and slightly modifying) the first option, which is to create cloudinary.yml file in config directory and write the following code:
(config/cloudinary.yml)
development:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
test:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
production:
cloud_name: <%= ENV["CLOUD_NAME"] %>
api_key: <%= ENV["API_KEY"] %>
api_secret: <%= ENV["API_SECRET"] %>
Please note that the configuration parameters (cloud name, api key, api secret) are set as environmental variables(CLOUD_NAME, API_KEY, API_SECRET) to prevent them from being exposed when the code is shared publicly. (You don't want to hard code the sensitive information)
You can set environmental variables in bash by editing .bash_profile file, which is located (and hidden) in the home directory:
(.bash_profile)
.....
export CLOUD_NAME="your cloud name"
export API_KEY="your api key"
export API_SECRET="your api secret"
.....
You can check that these environmental variables are correctly set by typing echo $CLOUD_NAME, for example, in your terminal.(You may need to quit and restart the terminal). If it's successful, the output will look something like:
echo $CLOUD_NAME
> your cloud name
Finally, if you are planning to deploy your app to heroku, you may also want to add cloudinary as an addon, which is free for a starter option, by typing the following command in the terminal:
heroku addons:create cloudinary:starter
Putting this all together might solve your issue.
Last but not least, I found the following blog post quite useful:
http://www.uberobert.com/rails_cloudinary_carrierwave/
It explains how you can use cloudinary and carrierwave to upload and manipulate the images on your application.
Hope it helps!

Related

Rails Active Storage push to DigitalOcean Spaces

Hi I'm trying to get active storage to push to a DigitalOcean space. However, I'm finding that the push url is being changed to amazonaws.com even though I've defined the endpoint to digital ocean.
here is what I have in storage.yml
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: sfo2
bucket: redacted_bucket_name
endpoint: https://sfo2.digitaloceanspaces.com
When I try to upload a file, I get the following error:
Aws::Errors::NoSuchEndpointError (Encountered a `SocketError` while attempting to connect to:
https://redacted_bucket_name.s3.sfo2.amazonaws.com/a8278561714955c23ee99
in my gemfile I have: gem 'aws-sdk-s3
I've followed the directions found here, and I'm still getting the error. Is it possible that there's a new way to do this?
I just set something like this up myself a few days ago. When you check the URL https://redacted_bucket_name.s3.sfo2.amazonaws.com/a8278561714955c23ee99 it's different from the actual endpoint you set up https://redacted_bucket_name.sfo2.amazonaws.com/a8278561714955c23ee99
the error is being caused by an invalid endpoint your hitting, the s3 right before the .sfo2 is offsetting the endpoint. Did you happen to add s3 to your spaces config? check your spaces dashboard and try to get the endpoint setup properly.
I had this same challenge when working on a Rails 6 application in Ubuntu 20.04.
Here's how I fixed mine:
Firstly, create a Spaces access keys in your digital ocean console. This link should help - DigitalOcean Spaces API
Secondly, add a new configuration for DigitalOcean Spaces in your config/storage.yml file. Just after the local storage definition:
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
digital_ocean:
service: S3
access_key_id: <%= SPACES_ACCESS_KEY_ID %>
secret_access_key: <%= SPACES_SECRET_ACCESS_KEY %>
region: <%= SPACES_REGION %>
bucket: <%= SPACES_BUCKET_NAME %>
endpoint: <%= SPACES_ENDPOINT %>
Note: You can give your entry any name, say digital_ocean_spaces or something else. For me I named it digital_ocean.
Thirdly, modify the config.active_storage.service configuration in the config/environments/production.rb file from:
config.active_storage.service = :local
to
config.active_storage.service = :digital_ocean
Finally, specify these environment variables file in your config/application.yml file (if you're using the Figaro gem) or your .env file. (if you're using the dotenv gem). In my case I was using the dotenv gem, so my .env file looked looked like this:
SPACES_ACCESS_KEY_ID=E4TFWVPDBLRTLUNZEIFMR
SPACES_SECRET_ACCESS_KEY=BBefjTJTFHYVNThun7GUPCeT2rNDJ4UxGLiSTM70Ac3NR
SPACES_REGION=nyc3
SPACES_BUCKET_NAME=my-spaces
SPACES_ENDPOINT=https://nyc3.digitaloceanspaces.com
That's all.
I hope this helps

OAuth credentials in secrets.yml in development section

My Rails app uses OAuth authentication. For production credentials, I use dotenv gem. config/secrets.yml:
production:
secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
facebook_app_id: <%= ENV['FACEBOOK_APP_ID'] %>
facebook_app_secret: <%= ENV['FACEBOOK_APP_SECRET'] %>
For testing, I use specially registered Facebook app that has "redirect_uri" to http://localhost.
Should I use the same approach for "development" section or I can write creds of apps that are registered for testing? How I understand no one can use it (for fishing websites) because there is "redirect_uri" that pointing on "localhost" in the settings of the app.
It is recommended not to expose the creds, even for the testing. You should follow the same approach for both dev and test. Also, add your file containing all the credentials to .gitignore

How to use secrets.yml for API_KEYS in Rails 4.1?

In one of my recent projects I started out by .gitignoring the files containing secrets and environment variables. So the entire project is committed to the repo except the files that contain third party secrets such as that of Stripe, Twitter API or Facebook Graph or internal api_keys, ala the ./config/initializers/secret_token.rb file.
Now I am at a point where the project is about to go live (excited!) and I need to port all the environment variables on to the production server using Capistrano i.e. cap production deploy.
[Edit 4: Yr, 2018]
In case of initializers/secret_token.rb it is clear that Rails 4.1 has a new way of handling secrets.yml file that pulls in the :secret_key_base value to the production server. Here, I recommend using the capistrano-secrets-yml gem which works right out of the box and is dead simple to use.
What is left is the way to carry other secrets like API_KEYS, APP_IDs etc. to the production server without checking any of those into the repo. How to do this, what is the most recommended/securest way or the best practices?
NOTE: I'll be editing the question as it progresses/I get more clarity.
EDIT1: Server is a Ubuntu/Linux VPS on DigitalOcean [Answer to Denise, below].
EDIT2: Can the env_variables/secrets be carried over to the server via secrets.yml? Secret_token for sessions is not the only secret after all! [Answered on Edit3]
EDIT3: Yes! It's possible to send in the API_keys via secrets.yml according to this blog. Will share my findings in sometime. :-)
First rule: DO NOT CHECK-IN secrets.yml into the repo.
All right, here's how a secret.yml would look:
development:
secret_key_base: 6a1ada9d8e377c8fad5e530d6e0a1daa3d17e43ee...
# Paste output of $ rake secret here for your dev machine.
test:
secret_key_base: _your_secret_ as above
production:
secret_key_base: <%= secure_token %>
STRIPE_PUBLISHABLE_KEY: 'Put your stripe keys for production'
STRIPE_SECRET_KEY: 'Put actual keys for production here'
FB_APP_SECRET: 'same as above'
FB_CALLBACK_URL: 'FB url here'
FB_CALLBACK_UPDATE_URL: 'FB url here'
GOOGLE_KEY: 'Put your keys for production'
GOOGLE_SECRET: 'same as above'
TWITTER_KEY: 'same as above'
TWITTER_SECRET: 'same as above'
TWITTER_USERNAME: 'same as above'
LINKEDIN_KEY: 'same as above'
LINKEDIN_SECRET: 'same as above'
Note the secure_token up there in the production: block. On production server I'm using an initializer to dynamically generate secret_tokens on-the-fly.
sidenote: be careful about spaces and tabs inside the .yml file. It must be properly formatted and spaced (such as having a space after the ':' symbol).
To set it up on production you could then scp the file directly from your local or use the capistrano-secrets-yml gem.
This will not work. See an updated method as per #OddityOverseer's answer below.
To access the environment variables in your app environments/production.rb use:
FB_APP_SECRET = ENV['FB_APP_SECRET']
FB_CALLBACK_URL = ENV['FB_CALLBACK_URL']
FB_CALLBACK_UPDATE_URL = ENV['FB_CALLBACK_UPDATE_URL']
GOOGLE_KEY = ENV['GOOGLE_KEY']
GOOGLE_SECRET = ENV['GOOGLE_SECRET']
TWITTER_KEY = ENV['TWITTER_KEY']
TWITTER_SECRET = ENV['TWITTER_SECRET']
TWITTER_USERNAME = ENV['TWITTER_USERNAME']
LINKEDIN_KEY = ENV['LINKEDIN_KEY']
LINKEDIN_SECRET = ENV['LINKEDIN_SECRET']
UPDATED August-2016:
To access the environment variables in your app environments/production.rb use:
FB_APP_SECRET = Rails.application.secrets.FB_APP_SECRET
FB_CALLBACK_URL = Rails.application.secrets.FB_CALLBACK_URL
FB_CALLBACK_UPDATE_URL = Rails.application.secrets.FB_CALLBACK_UPDATE_URL
GOOGLE_KEY = Rails.application.secrets.GOOGLE_KEY
GOOGLE_SECRET = Rails.application.secrets.GOOGLE_SECRET
TWITTER_KEY = Rails.application.secrets.TWITTER_KEY
TWITTER_SECRET = Rails.application.secrets.TWITTER_SECRET
TWITTER_USERNAME = Rails.application.secrets.TWITTER_USERNAME
LINKEDIN_KEY = Rails.application.secrets.LINKEDIN_KEY
LINKEDIN_SECRET = Rails.application.secrets.LINKEDIN_SECRET
That's about it.
Rails.application.secrets.key_name
One way to do it is to store those secret keys in environment variables. How to set an environment variable is different depending on what operating system you're on. For a linux machine, usually you're editing a .bashrc or .bash_profile file in your home directory and adding a line that looks like:
export API_KEYS=apikeygoeshere
You'll have to edit the file for whatever user will run rails.
Then in production.rb, you can refer to those environment variables as:
ENV["API_KEYS"]
Another option is to use a ruby gem that essentially takes care of that for you, like figaro. The way it works is that you create another file that you don't check in and figaro takes care of setting them up as environment variables, which you can then refer to in your development.rb/production.rb scripts using the ENV["API_KEYS"] above. Because you aren't checking in the file that has all of the environment variables, you'll have to find some way to get that file onto whatever machines are running the code.
I know this question is specific to Rails 4.1, but those who upgrade to Rails 5.1 it now includes built in secret generation. Which seems a much better way to handle sensitive data in your rails app.
See: http://edgeguides.rubyonrails.org/5_1_release_notes.html#encrypted-secrets
A nice approach to deal with different environments would be to:
EDITOR=vim rails credentials:edit
development:
cloudinary:
cloud_name: dxe1hjkoi
api_key: 361019726125669
api_secret: Cn6tHfSf019278367sZoO083eOI
production:
cloudinary:
cloud_name: oiajsu98u
api_key: 091828812791872
api_secret: KJS98182kjaksh89721jhS9812j
Then use it as:
Cloudinary.config do |config|
config.cloud_name =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :cloud_name)
config.api_key =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_key)
config.api_secret =
Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_secret)
end

rails 3: is there a way to put a gem's config params in environment.rb instead of foo.yml?

My rails app uses a gem that requires some config params to be specified in foo.yml:
development:
username: MyDevUserName
password: MyDevPassword
production:
username: MyPRODUserName
password: MyPRODPassword
I dont want the password in my source code and want to do something like:
development:
username: <%= ENV['THE_USERNAME'] %>
password: <%= ENV['THE_PASSWORD'] %>
production:
username: <%= ENV['THE_USERNAME'] %>
password: <%= ENV['THE_PASSWORD'] %>
However, for some reason that <%= ENV['XXX'] %> does work in my Settings.yml file, but does not work in my foo.yml file (I'm guessing however the foo gem loads the .yml file it does not allow interpretation).
So...
I'm wondering if Ruby/Rails has a general-purpose way to specify the variables in environment.rb instead of a foo.yml file?
Can i for example have an empty foo.yml file and add the following to environment.rb:
Foo::_something_._somethingelse =
{
:username => ENV['THE_USERNAME'],
:password => ENV['THE_PASSWORD']
}
EDIT: Since you are on Heroku...
Heroku is a different story. Your use of ENV may be conflicting with some functionality built into Heroku for handling config vars such as the ones you are working with. You need (drumroll, please)... CONFIG VARS. See this page in the Heroku Dev Center for information on how to set config vars in your Heroku deployment, how to access them from your app, and how to make it all work locally as well.
EDIT: Below is the original answer, still applicable in the general (non-heroku) case
Even if you put it in environment.rb, it will still be in your source code.
The correct way to do this is to ignore the foo.yml file in your version control (for instance, in git you would add the file to the .gitignore file). That way, you have the file locally where you need it, but it never gets committed to your repository, so your creds aren't exposed. On your deployment server, you will have to manually create that file as well, since when you deploy from source code the deployment won't have it.
If you are using capistrano for deployment, a common approach would be to put the file in [app]/shared/config/foo.yml, then add a deployment task to softlink from [sharedpath] into [releasepath]. Such a task in capistrano might look like this:
task :after_update_code do
run "ln -s #{shared_path}/config/foo.yml #{release_path}/config/foo.yml"
end

Set environment variable (ENV) for use in Rails

Experimenting with MongoID on a Rails server and confused about how/where to set the environment variables.
config/mongoid.yml default template provides:
defaults: &defaults
host: localhost
...
# set these environment variables on your prod server
production:
host: <%= ENV['MONGOID_HOST'] %>
port: <%= ENV['MONGOID_PORT'] %>
username: <%= ENV['MONGOID_USERNAME'] %>
password: <%= ENV['MONGOID_PASSWORD'] %>
database: <%= ENV['MONGOID_DATABASE'] %>
My question is are these set in Rails somewhere? or are they at the system level? and if so where/how to set so that no user account needs to be logged in for them to be valid?
The ENV hash will have values from the system environment from when the rails process was started.
These can be set on the command line prior to starting the server or program. For example in bash:
export MONGOID_USERNAME='username'
These are only good for the life of your shell, unless you add them to your profile, but it is likely that your web server won't use that profile, so it is only useful for local development.
They can also be set, for example, in Apache with SetEnv. For example:
<Location /app >
SetEnv MONGOID_HOST 'localhost'
SetEnv MONGOID_PORT '8883'
SetEnv MONGOID_USERNAME 'username'
</Location>
This could be anywhere SetEnv is legal in your apache config, and that is the same context that your application lives under.
Regarding you comment about best practices, some people put an example yml config file in source control, and ignore the config/*.yml files from source control. When cloning a repository, copying and correcting the examples to the correct values is part of the setup, like running rake tmp:create to make the tmp folder structure.
I wanted to add another option here. On boot, Rails will attempt to read DATABASE_URL as a url and connect to a database from that env variable (ignoring database.yml). You should specify the database as:
DATABASE_URL="mysql2://user:pass#localhost/app_development" rails server
and you can verify this via:
DATABASE_URL="..." rails runner "p ActiveRecord::Base.connection_config"
This is just another option instead of putting erb settings into database.yml.

Resources