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/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..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,21 +11,40 @@ 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 +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 @@ -28,6 +52,7 @@ def config 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)