From 1b7a5462a9169e1c94e125b15c2998f34552378c Mon Sep 17 00:00:00 2001 From: John Bachir Date: Sun, 5 Jun 2016 21:19:28 -0400 Subject: [PATCH 1/2] option to require secret --- README.md | 31 +++++++++++++++++++++++++++++++ server.rb | 9 +++++++++ 2 files changed, 40 insertions(+) diff --git a/README.md b/README.md index 411b175..0d861a3 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,37 @@ heroku apps:create ${COMPANY_NAME}-deploy-hook-forker heroku addons:create deployhooks:http --url=https://${COMPANY_NAME}-deploy-hook-forker.herokuapp.com ``` +### Securing with a secret + +As deployed, anyone on the internet can POST to your deploy-hook-forker instance +and trick you into thinking your project has been deployed. + +To avoid this, you can optionally require a secret be present when your apps POST to your +deploy-hook-forker instance. To do so, add a secret to your app: + +``` +➔ heroku config:set secret=`hexdump /dev/random | head | md5` --app ${COMPANY_NAME}-deploy-hook-forker +Setting secret and restarting ⬢ company-name-deploy-hook-forker... done, v7 +secret: e4b9c3c27ad5a3b6f0c9b0291eeccc28 +``` + +Now, when pointing an app's deploy hook to your deploy hook forker, use the secret in the url: + +```sh +heroku addons:create deployhooks:http --url=https://${COMPANY_NAME}-deploy-hook-forker.herokuapp.com?secret=e4b9c3c27ad5a3b6f0c9b0291eeccc28 +``` + + +## Development + +```ruby +bundle +bundle exec rackup + +# in another terminal... +curl http://localhost:9292 +curl -d ... http://localhost:9292 +``` ## References diff --git a/server.rb b/server.rb index 59c380c..ab21fe2 100644 --- a/server.rb +++ b/server.rb @@ -19,11 +19,20 @@ def config end get '/' do + if ENV["SECRET"] && params.delete("secret") == ENV["SECRET"] + content_type :json + status 200 + return JSON.pretty_generate(settings.config) + end status 200 "ok" end post '/' do + if ENV["SECRET"] && params.delete("secret") != ENV["SECRET"] + status 401 + return + end logger.info "RECIEVED POST: #{params.inspect}" forwardable_params = params.dup forwardable_params.delete('splat') From 137ad122e3d9d27791b79ccee03256511f29becd Mon Sep 17 00:00:00 2001 From: Jared Grippe Date: Mon, 6 Jun 2016 10:15:14 -0700 Subject: [PATCH 2/2] upgraded ruby & added support for .env in development --- .gitignore | 1 + Gemfile | 5 +++-- Gemfile.lock | 21 +++++++++++++++------ server.rb | 40 ++++++++++++++++++++++++++++------------ 4 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/Gemfile b/Gemfile index 3a78de5..fc1e96f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,12 @@ source "https://rubygems.org" -ruby '2.0.0' +ruby '2.2.3' gem 'sinatra' gem 'httparty' group :development do gem 'shotgun' - gem 'pry' + gem 'pry-byebug' + gem 'dotenv' end diff --git a/Gemfile.lock b/Gemfile.lock index d9525dc..00dbeb0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,17 +1,22 @@ GEM remote: https://rubygems.org/ specs: - coderay (1.1.0) + byebug (9.0.5) + coderay (1.1.1) + dotenv (2.1.1) httparty (0.12.0) json (~> 1.8) multi_xml (>= 0.5.2) json (1.8.1) method_source (0.8.2) multi_xml (0.5.5) - pry (0.9.12.4) - coderay (~> 1.0) - method_source (~> 0.8) + pry (0.10.3) + coderay (~> 1.1.0) + method_source (~> 0.8.1) slop (~> 3.4) + pry-byebug (3.4.0) + byebug (~> 9.0) + pry (~> 0.10) rack (1.5.2) rack-protection (1.5.1) rack @@ -21,14 +26,18 @@ GEM rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) - slop (3.4.7) + slop (3.6.0) tilt (1.4.1) PLATFORMS ruby DEPENDENCIES + dotenv httparty - pry + pry-byebug shotgun sinatra + +BUNDLED WITH + 1.11.2 diff --git a/server.rb b/server.rb index ab21fe2..a4db411 100644 --- a/server.rb +++ b/server.rb @@ -1,3 +1,8 @@ +ENV['RACK_ENV'] ||= 'development' + +require 'bundler' +Bundler.require + require 'sinatra' require 'yaml' require 'uri' @@ -6,37 +11,48 @@ use Rack::Logger -set :config_path, File.expand_path('../config.yml', __FILE__) -set :config, ->{ YAML.load(ERB.new(File.read(config_path)).result) } +configure :development do + require 'dotenv' + Dotenv.load +end + +configure do + set :config_path, File.expand_path('../config.yml', __FILE__) + set :config, ->{ YAML.load(ERB.new(File.read(config_path)).result) } + set :secret, ENV["SECRET"] + puts "SECRET=#{ENV["SECRET"]}" + puts settings.config.inspect +end + helpers do def logger request.logger end + def config settings.config[params['app']] || {} end end -get '/' do - if ENV["SECRET"] && params.delete("secret") == ENV["SECRET"] - content_type :json - status 200 - return JSON.pretty_generate(settings.config) +before do + if settings.secret && params["secret"] != settings.secret + halt 401, "Unauthorized" end +end + +get '/' do + content_type :json status 200 - "ok" + JSON.pretty_generate(settings.config) end post '/' do - if ENV["SECRET"] && params.delete("secret") != ENV["SECRET"] - status 401 - return - end logger.info "RECIEVED POST: #{params.inspect}" forwardable_params = params.dup forwardable_params.delete('splat') forwardable_params.delete('captures') + forwardable_params.delete('secret') config.values.each do |url| uri = URI.parse(url)