Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move validation until after the block is called #5

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions lib/passkit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,70 @@ class << self
def self.configure
self.configuration ||= Configuration.new
yield(configuration) if block_given?
configuration.validate!
end

class Configuration
attr_accessor :available_passes,
:web_service_host,
:certificate_key,
:private_p12_certificate,
:apple_intermediate_certificate,
:p12_password,
:p12_certificate,
:p12_key,
:wwdc_cert,
:apple_team_identifier,
:pass_type_identifier
:pass_type_identifier,
:format_version,
:dashboard_username,
:dashboard_password

DEFAULT_AUTHENTICATION = proc do
authenticate_or_request_with_http_basic("Passkit Dashboard. Login required") do |username, password|
username == ENV["PASSKIT_DASHBOARD_USERNAME"] && password == ENV["PASSKIT_DASHBOARD_PASSWORD"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are loosing the default taken from the ENV variable with this change. Can you please set both dashboard_username and dashboard_password to the ENV variables as default?

end
end
def authenticate_dashboard_with(&block)
@authenticate = block if block
@authenticate || DEFAULT_AUTHENTICATION
@authenticate || proc do
authenticate_or_request_with_http_basic("Passkit Dashboard. Login required") do |username, password|
username == dashboard_username && password == dashboard_password
end
end
end

def initialize
@available_passes = {"Passkit::ExampleStoreCard" => -> {}}
@web_service_host = ENV["PASSKIT_WEB_SERVICE_HOST"] || (raise "Please set PASSKIT_WEB_SERVICE_HOST")
raise("PASSKIT_WEB_SERVICE_HOST must start with https://") unless @web_service_host.start_with?("https://")
@certificate_key = ENV["PASSKIT_CERTIFICATE_KEY"] || (raise "Please set PASSKIT_CERTIFICATE_KEY")
@private_p12_certificate = ENV["PASSKIT_PRIVATE_P12_CERTIFICATE"] || (raise "Please set PASSKIT_PRIVATE_P12_CERTIFICATE")
@apple_intermediate_certificate = ENV["PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE"] || (raise "Please set PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE")
@apple_team_identifier = ENV["PASSKIT_APPLE_TEAM_IDENTIFIER"] || (raise "Please set PASSKIT_APPLE_TEAM_IDENTIFIER")
@pass_type_identifier = ENV["PASSKIT_PASS_TYPE_IDENTIFIER"] || (raise "Please set PASSKIT_PASS_TYPE_IDENTIFIER")
@web_service_host = ENV["PASSKIT_WEB_SERVICE_HOST"]
@p12_password = ENV["PASSKIT_P12_PASSWORD"] || ENV["PASSKIT_CERTIFICATE_KEY"]
@p12_certificate = ENV["PASSKIT_P12_CERTIFICATE"] || ENV["PASSKIT_PRIVATE_P12_CERTIFICATE"]
@p12_key = ENV["PASSKIT_P12_KEY"]
@wwdc_cert = ENV["PASSKIT_WWDC_CERT"] || ENV["PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE"]
@apple_team_identifier = ENV["PASSKIT_APPLE_TEAM_IDENTIFIER"]
@pass_type_identifier = ENV["PASSKIT_PASS_TYPE_IDENTIFIER"]
@format_version = ENV["PASSKIT_FORMAT_VERSION"] || 1
end

def validate!
raise "Please set PASSKIT_WEB_SERVICE_HOST" unless web_service_host
raise("PASSKIT_WEB_SERVICE_HOST must start with https://") unless web_service_host.start_with?("https://")

if wwdc_cert
intermediate_certificate = OpenSSL::X509::Certificate.new(File.read(Rails.root.join(wwdc_cert)))
else
raise "Please set PASSKIT_WWDC_CERT"
end

raise "Please set PASSKIT_P12_CERTIFICATE" unless p12_certificate
raise "Please set PASSKIT_P12_PASSWORD" unless p12_password

if p12_key
key = OpenSSL::PKey::RSA.new(File.read(Rails.root.join(p12_key)), p12_password)
cert = OpenSSL::X509::Certificate.new(File.read(Rails.root.join(p12_certificate)))
else
p12_certificate = OpenSSL::PKCS12.new(File.read(Rails.root.join(p12_certificate)), p12_password)
key = p12_certificate.key
cert = p12_certificate.certificate
end

flag = OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
OpenSSL::PKCS7.sign(cert, key, 'test', [intermediate_certificate], flag) # If this runs, all good

raise "Please set PASSKIT_APPLE_TEAM_IDENTIFIER" unless apple_team_identifier
raise "Please set PASSKIT_PASS_TYPE_IDENTIFIER" unless pass_type_identifier
end
end
end
9 changes: 4 additions & 5 deletions lib/passkit/base_pass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ def initialize(generator = nil)
end

def format_version
ENV["PASSKIT_FORMAT_VERSION"] || 1
Passkit.configuration.format_version
end

def apple_team_identifier
ENV["PASSKIT_APPLE_TEAM_IDENTIFIER"] || raise(Error.new("Missing environment variable: PASSKIT_APPLE_TEAM_IDENTIFIER"))
Passkit.configuration.apple_team_identifier
end

def pass_type_identifier
ENV["PASSKIT_PASS_TYPE_IDENTIFIER"] || raise(Error.new("Missing environment variable: PASSKIT_PASS_TYPE_IDENTIFIER"))
Passkit.configuration.pass_type_identifier
end

def language
Expand All @@ -40,8 +40,7 @@ def pass_type
end

def web_service_url
raise Error.new("Missing environment variable: PASSKIT_WEB_SERVICE_HOST") unless ENV["PASSKIT_WEB_SERVICE_HOST"]
"#{ENV["PASSKIT_WEB_SERVICE_HOST"]}/passkit/api"
"#{Passkit.configuration.web_service_host}/passkit/api"
end

def foreground_color
Expand Down
20 changes: 11 additions & 9 deletions lib/passkit/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,21 @@ def generate_json_manifest
File.write(@manifest_url, manifest.to_json)
end

CERTIFICATE = Rails.root.join(ENV["PASSKIT_PRIVATE_P12_CERTIFICATE"])
INTERMEDIATE_CERTIFICATE = Rails.root.join(ENV["PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE"])
CERTIFICATE_PASSWORD = ENV["PASSKIT_CERTIFICATE_KEY"]

# :nocov:
def sign_manifest
p12_certificate = OpenSSL::PKCS12.new(File.read(CERTIFICATE), CERTIFICATE_PASSWORD)
intermediate_certificate = OpenSSL::X509::Certificate.new(File.read(INTERMEDIATE_CERTIFICATE))
intermediate_certificate = OpenSSL::X509::Certificate.new(File.read(Rails.root.join(Passkit.configuration.wwdc_cert)))

if Passkit.configuration.p12_key
key = OpenSSL::PKey::RSA.new(File.read(Rails.root.join(Passkit.configuration.p12_key)), Passkit.configuration.p12_password)
cert = OpenSSL::X509::Certificate.new(File.read(Rails.root.join(Passkit.configuration.p12_certificate)))
else
p12_certificate = OpenSSL::PKCS12.new(File.read(Rails.root.join(Passkit.configuration.p12_certificate)), Passkit.configuration.p12_password)
key = p12_certificate.key
cert = p12_certificate.certificate
end

flag = OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
signed = OpenSSL::PKCS7.sign(p12_certificate.certificate,
p12_certificate.key, File.read(@manifest_url),
[intermediate_certificate], flag)
signed = OpenSSL::PKCS7.sign(cert, key, File.read(@manifest_url), [intermediate_certificate], flag)

@signature_url = @temporary_path.join("signature")
File.open(@signature_url, "w") { |f| f.syswrite signed.to_der }
Expand Down
2 changes: 1 addition & 1 deletion lib/passkit/url_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class UrlGenerator
include Passkit::Engine.routes.url_helpers

def initialize(pass_class, generator = nil)
@url = passes_api_url(host: ENV["PASSKIT_WEB_SERVICE_HOST"],
@url = passes_api_url(host: Passkit.configuration.web_service_host,
payload: PayloadGenerator.encrypted(pass_class, generator))
end

Expand Down
6 changes: 3 additions & 3 deletions test/api/v1/test_passes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ def test_show
_pkpass = Passkit::Factory.create_pass(Passkit::ExampleStoreCard)
assert_equal 1, Passkit::Pass.count
pass = Passkit::Pass.last
get pass_path(pass_type_id: ENV["PASSKIT_PASS_TYPE_IDENTIFIER"], serial_number: pass.serial_number)
get pass_path(pass_type_id: Passkit.configuration.pass_type_identifier, serial_number: pass.serial_number)
assert_response :unauthorized

get pass_path(pass_type_id: ENV["PASSKIT_PASS_TYPE_IDENTIFIER"], serial_number: pass.serial_number),
get pass_path(pass_type_id: Passkit.configuration.pass_type_identifier, serial_number: pass.serial_number),
headers: {"Authorization" => "ApplePass #{pass.authentication_token}"}

assert_response :success

get pass_path(pass_type_id: ENV["PASSKIT_PASS_TYPE_IDENTIFIER"], serial_number: pass.serial_number),
get pass_path(pass_type_id: Passkit.configuration.pass_type_identifier, serial_number: pass.serial_number),
headers: {"Authorization" => "ApplePass #{pass.authentication_token}", "If-Modified-Since" => Time.zone.now.httpdate}

assert_equal "", response.body
Expand Down
2 changes: 1 addition & 1 deletion test/system/logs_dashboard_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class LogsDashboardTest < ActionDispatch::SystemTestCase
end

def authorize
visit "http://#{ENV["PASSKIT_DASHBOARD_USERNAME"]}:#{ENV["PASSKIT_DASHBOARD_PASSWORD"]}@#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}/passkit/dashboard/logs"
visit "http://#{Passkit.configuration.dashboard_username}:#{Passkit.configuration.dashboard_password}@#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}/passkit/dashboard/logs"
end

test "visiting the logs dashboard" do
Expand Down