ror-rubycas-server 1.0.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/CHANGELOG +292 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +26 -0
  4. data/README.textile +129 -0
  5. data/Rakefile +1 -0
  6. data/bin/rubycas-server +16 -0
  7. data/lib/casserver.rb +11 -0
  8. data/lib/casserver/authenticators/active_directory_ldap.rb +19 -0
  9. data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
  10. data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
  11. data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
  12. data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +59 -0
  13. data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
  14. data/lib/casserver/authenticators/base.rb +67 -0
  15. data/lib/casserver/authenticators/client_certificate.rb +47 -0
  16. data/lib/casserver/authenticators/google.rb +58 -0
  17. data/lib/casserver/authenticators/ldap.rb +147 -0
  18. data/lib/casserver/authenticators/ntlm.rb +88 -0
  19. data/lib/casserver/authenticators/open_id.rb +22 -0
  20. data/lib/casserver/authenticators/sql.rb +133 -0
  21. data/lib/casserver/authenticators/sql_authlogic.rb +93 -0
  22. data/lib/casserver/authenticators/sql_encrypted.rb +75 -0
  23. data/lib/casserver/authenticators/sql_md5.rb +19 -0
  24. data/lib/casserver/authenticators/sql_rest_auth.rb +85 -0
  25. data/lib/casserver/authenticators/test.rb +22 -0
  26. data/lib/casserver/cas.rb +315 -0
  27. data/lib/casserver/localization.rb +91 -0
  28. data/lib/casserver/model.rb +270 -0
  29. data/lib/casserver/options_hash.rb +44 -0
  30. data/lib/casserver/server.rb +706 -0
  31. data/lib/casserver/utils.rb +32 -0
  32. data/lib/casserver/views/_login_form.erb +42 -0
  33. data/lib/casserver/views/layout.erb +18 -0
  34. data/lib/casserver/views/login.erb +30 -0
  35. data/lib/casserver/views/proxy.builder +12 -0
  36. data/lib/casserver/views/proxy_validate.builder +25 -0
  37. data/lib/casserver/views/service_validate.builder +18 -0
  38. data/lib/casserver/views/validate.erb +2 -0
  39. data/po/de_DE/rubycas-server.po +127 -0
  40. data/po/es_ES/rubycas-server.po +123 -0
  41. data/po/fr_FR/rubycas-server.po +128 -0
  42. data/po/ja_JP/rubycas-server.po +126 -0
  43. data/po/pl_PL/rubycas-server.po +123 -0
  44. data/po/pt_BR/rubycas-server.po +123 -0
  45. data/po/ru_RU/rubycas-server.po +118 -0
  46. data/po/rubycas-server.pot +112 -0
  47. data/po/zh_CN/rubycas-server.po +113 -0
  48. data/po/zh_TW/rubycas-server.po +113 -0
  49. data/public/themes/cas.css +121 -0
  50. data/public/themes/notice.png +0 -0
  51. data/public/themes/ok.png +0 -0
  52. data/public/themes/simple/bg.png +0 -0
  53. data/public/themes/simple/favicon.png +0 -0
  54. data/public/themes/simple/login_box_bg.png +0 -0
  55. data/public/themes/simple/logo.png +0 -0
  56. data/public/themes/simple/theme.css +28 -0
  57. data/public/themes/urbacon/bg.png +0 -0
  58. data/public/themes/urbacon/login_box_bg.png +0 -0
  59. data/public/themes/urbacon/logo.png +0 -0
  60. data/public/themes/urbacon/theme.css +33 -0
  61. data/public/themes/warning.png +0 -0
  62. data/resources/init.d.sh +58 -0
  63. data/rubycas-server.gemspec +57 -0
  64. data/setup.rb +1585 -0
  65. data/spec/alt_config.yml +50 -0
  66. data/spec/authenticators/ldap_spec.rb +53 -0
  67. data/spec/casserver_spec.rb +141 -0
  68. data/spec/database.yml +5 -0
  69. data/spec/default_config.yml +73 -0
  70. data/spec/model_spec.rb +42 -0
  71. data/spec/options_hash_spec.rb +146 -0
  72. data/spec/spec.opts +4 -0
  73. data/spec/spec_helper.rb +90 -0
  74. data/spec/utils_spec.rb +53 -0
  75. data/tasks/bundler.rake +4 -0
  76. data/tasks/db/migrate.rake +12 -0
  77. data/tasks/localization.rake +13 -0
  78. data/tasks/spec.rake +10 -0
  79. metadata +356 -0
@@ -0,0 +1,50 @@
1
+ server: webrick
2
+ port: 6543
3
+ #ssl_cert: test.pem
4
+ uri_path: /test
5
+ #bind_address: 0.0.0.0
6
+
7
+ # database:
8
+ # adapter: mysql
9
+ # database: casserver
10
+ # username: root
11
+ # password:
12
+ # host: localhost
13
+ # reconnect: true
14
+ database:
15
+ adapter: sqlite3
16
+ database: spec/casserver_spec.db
17
+
18
+ disable_auto_migrations: true
19
+
20
+ quiet: true
21
+
22
+ authenticator:
23
+ class: CASServer::Authenticators::Test
24
+ password: spec_password
25
+
26
+ theme: simple
27
+
28
+ organization: "RSPEC-TEST"
29
+
30
+ infoline: "This is an rspec test."
31
+
32
+ #custom_views: /path/to/custom/views
33
+
34
+ default_locale: en
35
+
36
+ log:
37
+ file: casserver_spec.log
38
+ level: DEBUG
39
+
40
+ #db_log:
41
+ # file: casserver_spec_db.log
42
+
43
+ enable_single_sign_out: true
44
+
45
+ #maximum_unused_login_ticket_lifetime: 300
46
+ #maximum_unused_service_ticket_lifetime: 300
47
+
48
+ #maximum_session_lifetime: 172800
49
+
50
+ #downcase_username: true
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ require 'casserver/authenticators/ldap'
5
+
6
+ describe CASServer::Authenticators::LDAP do
7
+ before do
8
+ @ldap_entry = mock(Net::LDAP::Entry.new)
9
+ @ldap_entry.stub!(:[]).and_return("Test")
10
+
11
+ @ldap = mock(Net::LDAP)
12
+ @ldap.stub!(:host=)
13
+ @ldap.stub!(:port=)
14
+ @ldap.stub!(:encryption)
15
+ @ldap.stub!(:bind_as).and_return(true)
16
+ @ldap.stub!(:authenticate).and_return(true)
17
+ @ldap.stub!(:search).and_return([@ldap_entry])
18
+
19
+ Net::LDAP.stub!(:new).and_return(@ldap)
20
+ end
21
+
22
+ describe '#validate' do
23
+
24
+ it 'validate with preauthentication and with extra attributes' do
25
+ auth = CASServer::Authenticators::LDAP.new
26
+
27
+ auth_config = HashWithIndifferentAccess.new(
28
+ :ldap => {
29
+ :host => "ad.example.net",
30
+ :port => 389,
31
+ :base => "dc=example,dc=net",
32
+ :filter => "(objectClass=person)",
33
+ :auth_user => "authenticator",
34
+ :auth_password => "itsasecret"
35
+ },
36
+ :extra_attributes => [:full_name, :address]
37
+ )
38
+
39
+ auth.configure(auth_config.merge('auth_index' => 0))
40
+ auth.validate(
41
+ :username => 'validusername',
42
+ :password => 'validpassword',
43
+ :service => 'test.service',
44
+ :request => {}
45
+ ).should == true
46
+
47
+ auth.extra_attributes.should == {:full_name => 'Test', :address => 'Test'}
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,141 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ $LOG = Logger.new(File.basename(__FILE__).gsub('.rb','.log'))
5
+
6
+ RSpec.configure do |config|
7
+ config.include Capybara
8
+ end
9
+
10
+ VALID_USERNAME = 'spec_user'
11
+ VALID_PASSWORD = 'spec_password'
12
+
13
+ INVALID_PASSWORD = 'invalid_password'
14
+
15
+ describe 'CASServer' do
16
+
17
+ before do
18
+ @target_service = 'http://my.app.test'
19
+ end
20
+
21
+ describe "/login" do
22
+ before do
23
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
24
+ reset_spec_database
25
+ end
26
+
27
+ it "logs in successfully with valid username and password without a target service" do
28
+ visit "/login"
29
+
30
+ fill_in 'username', :with => VALID_USERNAME
31
+ fill_in 'password', :with => VALID_PASSWORD
32
+ click_button 'login-submit'
33
+
34
+ page.should have_content("You have successfully logged in")
35
+ end
36
+
37
+ it "fails to log in with invalid password" do
38
+ visit "/login"
39
+ fill_in 'username', :with => VALID_USERNAME
40
+ fill_in 'password', :with => INVALID_PASSWORD
41
+ click_button 'login-submit'
42
+
43
+ page.should have_content("Incorrect username or password")
44
+ end
45
+
46
+ it "logs in successfully with valid username and password and redirects to target service" do
47
+ visit "/login?service="+CGI.escape(@target_service)
48
+
49
+ fill_in 'username', :with => VALID_USERNAME
50
+ fill_in 'password', :with => VALID_PASSWORD
51
+
52
+ click_button 'login-submit'
53
+
54
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
55
+ end
56
+
57
+ it "preserves target service after invalid login" do
58
+ visit "/login?service="+CGI.escape(@target_service)
59
+
60
+ fill_in 'username', :with => VALID_USERNAME
61
+ fill_in 'password', :with => INVALID_PASSWORD
62
+ click_button 'login-submit'
63
+
64
+ page.should have_content("Incorrect username or password")
65
+ page.should have_xpath('//input[@id="service"]', :value => @target_service)
66
+ end
67
+
68
+ it "uses appropriate localization when 'lang' prameter is given (make sure you've run `rake localization:mo` first!!)" do
69
+ visit "/login?lang=pl"
70
+ page.should have_content("Użytkownik")
71
+
72
+ visit "/login?lang=pt_BR"
73
+ page.should have_content("Usuário")
74
+
75
+ visit "/login?lang=en"
76
+ page.should have_content("Username")
77
+ end
78
+
79
+ end # describe '/login'
80
+
81
+
82
+ describe '/logout' do
83
+
84
+ before do
85
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
86
+ reset_spec_database
87
+ end
88
+
89
+ it "logs out successfully" do
90
+ visit "/logout"
91
+
92
+ page.should have_content("You have successfully logged out")
93
+ end
94
+
95
+ it "logs out successfully and redirects to target service" do
96
+ visit "/logout?gateway=true&service="+CGI.escape(@target_service)
97
+
98
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?/
99
+ end
100
+
101
+ end # describe '/logout'
102
+
103
+ describe 'Configuration' do
104
+ it "uri_path value changes prefix of routes" do
105
+ load_server(File.dirname(__FILE__) + "/alt_config.yml")
106
+ @target_service = 'http://my.app.test'
107
+
108
+ visit "/test/login"
109
+ page.status_code.should_not == 404
110
+
111
+ visit "/test/logout"
112
+ page.status_code.should_not == 404
113
+ end
114
+ end
115
+
116
+ describe "proxyValidate" do
117
+ before do
118
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
119
+ reset_spec_database
120
+
121
+ visit "/login?service="+CGI.escape(@target_service)
122
+
123
+ fill_in 'username', :with => VALID_USERNAME
124
+ fill_in 'password', :with => VALID_PASSWORD
125
+
126
+ click_button 'login-submit'
127
+
128
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
129
+ @ticket = page.current_url.match(/ticket=(.*)$/)[1]
130
+ end
131
+
132
+ it "should have extra attributes in proper format" do
133
+ visit "/serviceValidate?service=#{CGI.escape(@target_service)}&ticket=#{@ticket}"
134
+
135
+ encoded_utf_string = "Ютф" # actual string is "Ютф"
136
+ page.body.should match("<test_utf_string>#{encoded_utf_string}</test_utf_string>")
137
+ page.body.should match("<test_numeric>123.45</test_numeric>")
138
+ page.body.should match("<test_utf_string>&#1070;&#1090;&#1092;</test_utf_string>")
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,5 @@
1
+ development:
2
+ adapter: sqlite3
3
+
4
+ production:
5
+ adapter: postgresql
@@ -0,0 +1,73 @@
1
+ all: &all
2
+ server: webrick
3
+ port: 6543
4
+ #ssl_cert: test.pem
5
+ #uri_path: /cas
6
+ #bind_address: 0.0.0.0
7
+
8
+ # database:
9
+ # adapter: mysql
10
+ # database: casserver
11
+ # username: root
12
+ # password:
13
+ # host: localhost
14
+ # reconnect: true
15
+ database:
16
+ adapter: sqlite3
17
+ database: spec/casserver_spec.db
18
+
19
+ disable_auto_migrations: true
20
+
21
+ quiet: true
22
+
23
+ authenticator:
24
+ class: CASServer::Authenticators::Test
25
+ password: spec_password
26
+ database:
27
+ adapter: mysql
28
+
29
+ theme: simple
30
+
31
+ organization: "RSPEC-TEST"
32
+
33
+ infoline: "This is an rspec test."
34
+
35
+ #custom_views: /path/to/custom/views
36
+
37
+ default_locale: en
38
+
39
+ log:
40
+ file: casserver_spec.log
41
+ level: DEBUG
42
+
43
+ #db_log:
44
+ # file: casserver_spec_db.log
45
+
46
+ enable_single_sign_out: true
47
+
48
+ #maximum_unused_login_ticket_lifetime: 300
49
+ #maximum_unused_service_ticket_lifetime: 300
50
+
51
+ #maximum_session_lifetime: 172800
52
+
53
+ #downcase_username: true
54
+
55
+
56
+ production:
57
+ <<: *all
58
+ server: thin
59
+ authenticator:
60
+ class: CASServer::Authenticators::SQL
61
+ database: inherit
62
+ user_table: users
63
+ username_column: email
64
+ password_column: password
65
+
66
+
67
+ test:
68
+ <<: *all
69
+ server: mongrel
70
+
71
+ development:
72
+ <<: *all
73
+ server: apache
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ module CASServer
5
+ end
6
+ require 'casserver/model'
7
+
8
+ describe CASServer::Model::LoginTicket, '.cleanup(max_lifetime, max_unconsumed_lifetime)' do
9
+ let(:max_lifetime) { -1 }
10
+ let(:max_unconsumed_lifetime) { -2 }
11
+
12
+ before do
13
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
14
+ reset_spec_database
15
+
16
+ CASServer::Model::LoginTicket.create :ticket => 'test', :client_hostname => 'test.local'
17
+ end
18
+
19
+ it 'should destroy all tickets created before the max lifetime' do
20
+ expect {
21
+ CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
22
+ }.to change(CASServer::Model::LoginTicket, :count).by(-1)
23
+ end
24
+
25
+ it 'should destroy all unconsumed tickets not exceeding the max lifetime' do
26
+ expect {
27
+ CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
28
+ }.to change(CASServer::Model::LoginTicket, :count).by(-1)
29
+ end
30
+ end
31
+
32
+ describe CASServer::Model::LoginTicket, '#to_s' do
33
+ let(:ticket) { 'test' }
34
+
35
+ before do
36
+ @login_ticket = CASServer::Model::LoginTicket.new :ticket => ticket
37
+ end
38
+
39
+ it 'should delegate #to_s to #ticket' do
40
+ @login_ticket.to_s.should == ticket
41
+ end
42
+ end
@@ -0,0 +1,146 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ # Hmmm.. Should I need to do this?
4
+ require 'casserver/options_hash'
5
+
6
+ describe OptionsHash do
7
+
8
+ describe "creation" do
9
+ it "should not raise" do
10
+ lambda {OptionsHash.new}.should_not raise_error
11
+ end
12
+ end
13
+
14
+ describe "environment method" do
15
+ before :each do
16
+ @options = OptionsHash.new
17
+ end
18
+ it "should store an environment attribute" do
19
+ @options.environment = :development
20
+ @options.environment.should == :development
21
+ end
22
+ end
23
+
24
+ describe "load_config method," do
25
+ before :each do
26
+ @options = OptionsHash.new
27
+ end
28
+ it "should raise when it doesn't know the environment" do
29
+ lambda {@options.load_config "spec/default_config.yml"}.should raise_error(OptionsHash::EnvironmentMissing)
30
+ end
31
+ describe "given a set environment," do
32
+ before :each do
33
+ @options.environment = :development
34
+ end
35
+ it "should raise an argument error when you pass something silly in" do
36
+ lambda {@options.load_config :silly}.should raise_error(ArgumentError)
37
+ lambda {@options.load_config 51117}.should raise_error(ArgumentError)
38
+ end
39
+ it "should load a config file string without error" do
40
+ lambda {@options.load_config "spec/default_config.yml"}.should_not raise_error
41
+ end
42
+ it "should load a config file without error" do
43
+ file = File.new "spec/default_config.yml"
44
+ lambda {@options.load_config file}.should_not raise_error
45
+ end
46
+
47
+ describe "data loading" do
48
+ before :each do
49
+ @options.environment = :development
50
+ @options.load_config "spec/default_config.yml"
51
+ end
52
+ it "should assign things correctly from all" do
53
+ @options[:port].should == 6543
54
+ end
55
+ it "should assign environment specific options" do
56
+ @options[:server].should == "apache"
57
+ production_options = OptionsHash.new
58
+ production_options.environment = :production
59
+ production_options.load_config "spec/default_config.yml"
60
+ production_options[:server].should == "thin"
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+ describe "load_database_config method" do
68
+ before :each do
69
+ @development_options = OptionsHash.new
70
+ @production_options = OptionsHash.new
71
+ end
72
+ it "should not work without assignment of environment" do
73
+ lambda {@development_options.load_database_config "spec/database.yml"}.should raise_error(OptionsHash::EnvironmentMissing)
74
+ end
75
+ describe "when environment attribute is assigned" do
76
+
77
+ before :each do
78
+ @development_options.environment = :development
79
+ @production_options.environment = :production
80
+ end
81
+
82
+ it "should not raise when a filename string is passed in" do
83
+ lambda {@development_options.load_database_config "spec/database.yml"}.should_not raise_error
84
+ end
85
+
86
+ it "should not raise when a file is passed in" do
87
+ file = File.new "spec/database.yml"
88
+ lambda {@development_options.load_database_config file}.should_not raise_error
89
+ end
90
+
91
+ describe "post data loading should have the appropriate data loaded" do
92
+ before :each do
93
+ @development_options.load_database_config "spec/database.yml"
94
+ @production_options.load_database_config "spec/database.yml"
95
+ end
96
+ it "for development" do
97
+ @development_options[:database][:adapter].should == "sqlite3"
98
+ end
99
+ it "for production" do
100
+ @production_options[:database][:adapter].should == "postgresql"
101
+ end
102
+ end
103
+
104
+ describe "primary configuration overriding" do
105
+ before :each do
106
+ @production_options.load_config "spec/default_config.yml"
107
+ end
108
+ it "should work" do
109
+ @production_options[:database][:adapter].should == "sqlite3"
110
+ @production_options.load_database_config "spec/database.yml"
111
+ @production_options[:database][:adapter].should == "postgresql"
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+ describe "inherit_authenticator_database! method" do
119
+ before :each do
120
+ @options = OptionsHash.new
121
+ @options.environment = :production
122
+ @options.load_config "spec/default_config.yml"
123
+ end
124
+ it "should work" do
125
+ @options[:authenticator][:database].should == "inherit"
126
+ @options.inherit_authenticator_database!
127
+ @options[:authenticator][:database].should_not == "inherit"
128
+ @options[:authenticator][:database][:adapter].should == "sqlite3"
129
+ end
130
+ it "should work after loading database.yml" do
131
+ @options.load_database_config "spec/database.yml"
132
+ @options[:authenticator][:database].should == "inherit"
133
+ @options.inherit_authenticator_database!
134
+ @options[:authenticator][:database].should_not == "inherit"
135
+ @options[:authenticator][:database][:adapter].should == "postgresql"
136
+ end
137
+ it "should do nothing when it should do nothing" do
138
+ options = OptionsHash.new
139
+ options.environment = :development
140
+ options.load_config "spec/default_config.yml"
141
+ options[:authenticator][:database][:adapter].should == "mysql"
142
+ options.inherit_authenticator_database!
143
+ options[:authenticator][:database][:adapter].should == "mysql"
144
+ end
145
+ end
146
+ end