namespace :heroku_ssl do
task :update_certs do update_certs end task :generate_certs do email = (ARGV[1] || '').strip email = get_email if email.blank? puts "Registering #{email}" HerokuSsl::register email domain = ARGV[2..-1] domain = get_domains if domain.blank? puts "Authorizing and generating certificates for #{domain}" certs = HerokuSsl::request_certificate domain if certs.present? STDOUT.puts '~~ GENERATED CERTIFICATES START ~~' STDOUT.puts JSON(certs) STDOUT.puts '~~ GENERATED CERTIFICATES END ~~' end end def update_certs STDOUT.puts 'Once your app has been deployed to Heroku, hit enter.' STDIN.gets email = get_email domains = get_domains app = get_app puts "Attempting to generate ssl certificates for #{app} (registering #{domains} to #{email})" #generate the certs on the server output = heroku_run("run rake heroku_ssl:generate_certs #{email} #{domains} --app #{app}") #read out the certs to temporary files unless output.include? '~~ GENERATED CERTIFICATES START ~~' puts 'Full log: ' puts output puts '' puts 'Could not generate certificates. Please try again later or try running `heroku run rake heroku_ssl:generate_certs` directly' return end output = output.split('~~ GENERATED CERTIFICATES START ~~').last .split('~~ GENERATED CERTIFICATES END ~~').first output = JSON(output).with_indifferent_access unless output['fullchain'].present? && output['privkey'].present? puts 'Output: ' puts output puts '' puts 'Failed to read certificates' return end puts 'Successfully generated certificates! Attempting to update Heroku DNS' File.open('fullchain.pem', 'wb') do |file| file.write output['fullchain'] end File.open('privkey.pem', 'wb') do |file| file.write output['privkey'] end # update heroku certs if heroku_run('certs') =~ /has\sno\sSSL\scertificates/i heroku_run("certs:add fullchain.pem privkey.pem --app #{get_app}") else heroku_run("certs:update fullchain.pem privkey.pem --app #{get_app} --confirm #{get_app}") end # clean up File.delete('fullchain.pem', 'privkey.pem') puts 'Successfully updated Heroku SSL certificates! Now you just need to make sure your DNS is configured to point as follows: ' puts heroku_run('domains').split("\n")[4..-1].join("\n") end def get_email return @email if @email.present? @email = `git config user.email` @email.strip! if @email.present? default_prompt = '' default_prompt = " [#{@email}]" if @email.present? new_email = nil while new_email.blank? STDOUT.puts "Enter your email (used to notify you of expiration)#{default_prompt}: " new_email = STDIN.gets if new_email.blank? new_email = @email else new_email.strip! end end @email = new_email end def heroku_run(command) # RUBYOPT breaks the heroku command for some reason, so you have to unset it result = `unset RUBYOPT; heroku #{command}` if result =~ /rake\saborted/i puts "Don't know how to build task -- make sure you have deployed a version with this gem installed to heroku" end if result =~ /No\ssuch\sfile\sor\sdirectory/i || result =~ /command\snot\sfound/i puts 'Cannot run command heroku -- are you sure you have it installed?' end if result =~ /Bundler::GemNotFound/i puts 'Please log in to heroku by running `heroku login`' end result end def get_domains return @domain if @domain.present? domains = heroku_run('domains').split("\n").select(&:present?)[5..-1] if domains.blank? puts 'Warning: Could not load domains' domains = [] end domains.map! do |domain| domain.split(/\s+/).first end @domain = domains.join ' ' default_prompt = '' default_prompt = " [#{@domain}]" if @domain.present? new_domain = nil while new_domain.blank? STDOUT.puts "Enter the domain to register#{default_prompt}: " new_domain = STDIN.gets if new_domain.blank? new_domain = @domain else new_domain.strip! end end @domain = new_domain end def get_app return @app if @app.present? @apps = @apps || heroku_run('apps').split("\n").map(&:split).map(&:first).select(&:present?) remotes = `git remote -v`.split("\n").map do |r| r.split("\t").last end @apps.each do |app| remotes.each do |remote| if remote.include? app @app = app break end end break if @app.present? end default_prompt = '' default_prompt = " [#{@app}]" if @app.present? new_app = nil while new_app.blank? STDOUT.puts "Enter the heroku app#{default_prompt}: " new_app = STDIN.gets if new_app.blank? new_app = @app else new_app.strip! end end @app = new_app end
end