summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--certs/app/controllers/certs_controller.rb11
-rw-r--r--certs/app/models/client_certificate.rb19
-rw-r--r--certs/test/functional/certs_controller_test.rb37
-rw-r--r--certs/test/unit/client_certificate_test.rb23
-rw-r--r--config/defaults.yml2
-rw-r--r--core/test/support/with_config_helper.rb16
6 files changed, 85 insertions, 23 deletions
diff --git a/certs/app/controllers/certs_controller.rb b/certs/app/controllers/certs_controller.rb
index 6db270c..977e03e 100644
--- a/certs/app/controllers/certs_controller.rb
+++ b/certs/app/controllers/certs_controller.rb
@@ -1,11 +1,16 @@
class CertsController < ApplicationController
- before_filter :authorize
+ before_filter :logged_in_or_free_certs
# GET /cert
def show
- @cert = ClientCertificate.new
- render :text => @cert.key + @cert.cert, :content_type => 'text/plain'
+ @cert = ClientCertificate.new(free: !logged_in?)
+ render text: @cert.to_s, content_type: 'text/plain'
end
+ protected
+
+ def logged_in_or_free_certs
+ authorize unless APP_CONFIG[:free_certs_enabled]
+ end
end
diff --git a/certs/app/models/client_certificate.rb b/certs/app/models/client_certificate.rb
index be0ac63..1bc34c6 100644
--- a/certs/app/models/client_certificate.rb
+++ b/certs/app/models/client_certificate.rb
@@ -1,5 +1,5 @@
#
-# Model for certificates stored in CouchDB.
+# Model for certificates
#
# This file must be loaded after Config has been loaded.
#
@@ -17,11 +17,11 @@ class ClientCertificate
#
# generate the private key and client certificate
#
- def initialize
+ def initialize(options = {})
cert = CertificateAuthority::Certificate.new
# set subject
- cert.subject.common_name = random_common_name
+ cert.subject.common_name = common_name(options[:free])
# set expiration
cert.not_before = yesterday
@@ -35,8 +35,12 @@ class ClientCertificate
cert.parent = ClientCertificate.root_ca
cert.sign! client_signing_profile
- self.key = cert.key_material.private_key.to_pem
- self.cert = cert.to_pem
+ self.key = cert.key_material.private_key
+ self.cert = cert
+ end
+
+ def to_s
+ self.key.to_pem + self.cert.to_pem
end
private
@@ -61,6 +65,11 @@ class ClientCertificate
Digest::MD5.hexdigest("#{rand(10**10)} -- #{Time.now}").to_i(16)
end
+ def common_name(for_free_cert = false)
+ random_common_name +
+ (for_free_cert ? APP_CONFIG[:free_cert_postfix] : '')
+ end
+
#
# for the random common name, we need a text string that will be unique across all certs.
# ruby 1.8 doesn't have a built-in uuid generator, or we would use SecureRandom.uuid
diff --git a/certs/test/functional/certs_controller_test.rb b/certs/test/functional/certs_controller_test.rb
index 75256ca..7826dd6 100644
--- a/certs/test/functional/certs_controller_test.rb
+++ b/certs/test/functional/certs_controller_test.rb
@@ -1,21 +1,40 @@
require 'test_helper'
class CertsControllerTest < ActionController::TestCase
- setup do
- end
- test "should require login" do
+ test "send free cert without login" do
+ cert = stub :to_s => "free cert"
+ ClientCertificate.expects(:new).with(free: true).returns(cert)
get :show
- assert_response :redirect
- assert_redirected_to login_url
+ assert_response :success
+ assert_equal cert.to_s, @response.body
end
- test "should send cert" do
+ test "send cert" do
login
- cert = stub :cert => "adsf", :key => "key"
- ClientCertificate.expects(:new).returns(cert)
+ cert = stub :to_s => "real cert"
+ ClientCertificate.expects(:new).with(free: false).returns(cert)
get :show
assert_response :success
- assert_equal cert.key + cert.cert, @response.body
+ assert_equal cert.to_s, @response.body
+ end
+
+ test "login required if free certs disabled" do
+ with_config free_certs_enabled: false do
+ get :show
+ assert_response :redirect
+ end
end
+
+ test "get paid cert if free certs disabled" do
+ with_config free_certs_enabled: false do
+ login
+ cert = stub :to_s => "real cert"
+ ClientCertificate.expects(:new).with(free: false).returns(cert)
+ get :show
+ assert_response :success
+ assert_equal cert.to_s, @response.body
+ end
+ end
+
end
diff --git a/certs/test/unit/client_certificate_test.rb b/certs/test/unit/client_certificate_test.rb
index 71a1d90..bcc61cc 100644
--- a/certs/test/unit/client_certificate_test.rb
+++ b/certs/test/unit/client_certificate_test.rb
@@ -2,17 +2,28 @@ require 'test_helper'
class ClientCertificateTest < ActiveSupport::TestCase
- setup do
- @sample = ClientCertificate.new
+ test "new cert has all we need" do
+ sample = ClientCertificate.new
+ assert sample.key
+ assert sample.cert
+ assert sample.to_s
end
- test "new cert has all we need" do
- assert @sample.key
- assert @sample.cert
+ test "free cert has configured postfix" do
+ sample = ClientCertificate.new(free: true)
+ postfix = APP_CONFIG[:free_cert_postfix]
+ assert sample.cert.subject.common_name.include?(postfix)
+ end
+
+ test "real cert has no free cert postfix" do
+ sample = ClientCertificate.new
+ postfix = APP_CONFIG[:free_cert_postfix]
+ assert !sample.cert.subject.common_name.include?(postfix)
end
test "cert issuer matches ca subject" do
- cert = OpenSSL::X509::Certificate.new(@sample.cert)
+ sample = ClientCertificate.new
+ cert = OpenSSL::X509::Certificate.new(sample.cert.to_pem)
assert_equal ClientCertificate.root_ca.openssl_body.subject, cert.issuer
end
diff --git a/config/defaults.yml b/config/defaults.yml
index cb8a627..54e4178 100644
--- a/config/defaults.yml
+++ b/config/defaults.yml
@@ -7,6 +7,8 @@ cert_options: &cert_options
client_cert_lifespan: 2
client_cert_bit_size: 2024
client_cert_hash: "SHA256"
+ free_certs_enabled: true
+ free_cert_postfix: "*Free Cert*"
development:
<<: *dev_ca
diff --git a/core/test/support/with_config_helper.rb b/core/test/support/with_config_helper.rb
new file mode 100644
index 0000000..65eb7bc
--- /dev/null
+++ b/core/test/support/with_config_helper.rb
@@ -0,0 +1,16 @@
+module WithConfigHelper
+ extend ActiveSupport::Concern
+
+ def with_config(options)
+ old_config = APP_CONFIG.dup
+ APP_CONFIG.merge! options
+ yield
+ ensure
+ APP_CONFIG.replace old_config
+ end
+
+end
+
+class ActiveSupport::TestCase
+ include WithConfigHelper
+end