saml_camel 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db6a8d7294f375eadf0c0358d7e438fb367a2b45
4
+ data.tar.gz: c89095973afa1aaa726f242cabb7b2d360360f33
5
+ SHA512:
6
+ metadata.gz: ba097413cf902c8bd2184c64e4fcb87b39027cf223042952732a5022245901196edafd7e3b9c20d9f9e76b76c95eb23bf1eda86f2b3d5c35d9ba814e5b5ad280
7
+ data.tar.gz: afb5650b0e054af8cb911461b7211106eddb305d994e77c9941738f03f6c085a6a0fa8fe1a05ca1c0fe0d561214ac0304cfeac3bb97a880cee5fd0423b9b7ff7
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Danai Adkisson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # SamlCamel - (not production ready)
2
+ ## Installation
3
+ Add this line to your application's Gemfile:
4
+
5
+ ```ruby
6
+ source "https://gems-internal.oit.duke.edu" do
7
+ gem 'saml_camel'
8
+ end
9
+ ```
10
+
11
+
12
+ And then execute:
13
+ ```bash
14
+ $ bundle
15
+ ```
16
+
17
+
18
+ ## Usage
19
+ 1. run `rake saml_camel:generate_saml` to generate metadata files for each environment. you can also specify a specifc/custom environment like this `rake saml_camel:generate_saml environment=acceptance`
20
+
21
+ **Note: these steps will use development as an example, if you use seperate metadata per environemtn, you will repeat each step for your chosed environement**
22
+
23
+ 2. from the root of your app open `saml/development/settings.json` and specify an entity ID of your choice. this is a unique identifier used by the
24
+ Identity Provider(idp) to recognize your app. Typically it should take the form of a url, however note that it is just an identifier and does not have to be routeable (e.g. https://my-app-name/not/a/real/route)
25
+
26
+ 3. Go to https://idms-web.oit.duke.edu/spreg/sps and register your metadata with the identity provider. You will need the values from `saml/development/settings.json` in addition to the `saml/development/saml_certificate.crt`
27
+
28
+ - copy the entity_id you chose in the `settings.json` file and paste it into the "Entity Field"
29
+ - fill out functional purpose, responsible dept, function owner dept, and audience with information relevent to your application
30
+ - copy the cert from `saml/development/saml_certificate.crt` and paste it into the Certificate Field
31
+ - copy the acs value and paste it into the Location field in the Assertion Consumer Service box
32
+ - note that the default host value for ACS is `http://locahost:3000` which is the default `rails s` host. If you're using a differnet host (such as in production or using docker) you will want to replace the host value with what is relevent for your situation(*e.g. https://my-app.duke.edu/saml/consumeSaml*), but keep the path `/saml/consumeSaml`
33
+
34
+ 4. In your app mount the engine in config/routes.rb
35
+ ```ruby
36
+ mount SamlCamel::Engine, at: "/saml"
37
+ ```
38
+
39
+ 5. include saml helpers in `app/controllers/application_controller.rb`
40
+ ```ruby
41
+ class ApplicationController < ActionController::Base
42
+ include SamlCamel::SamlHelpers
43
+ end
44
+ ```
45
+
46
+ 6. now simply provide the `saml protect` method in your controllers (via `around_action`) to protect paths
47
+ **NOTE: it is important you MUST use around_action**
48
+
49
+ 7. to logout simply make a post to `localhost:3000/saml/logout`. This will kill the local saml session, and the session with the identity provider. You can specify a return url in `saml/development/settings.json`
50
+
51
+ ```ruby
52
+ class DashboardController < ApplicationController
53
+ around_action :saml_protect, except: [:home]
54
+
55
+ def home
56
+ end
57
+
58
+ def index
59
+ end
60
+
61
+ end
62
+ ```
63
+
64
+ 7. response attributes found in `session[:saml_attributes]`
65
+
66
+
67
+ ## License
68
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SamlCamel'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+ load 'rails/tasks/statistics.rake'
20
+
21
+
22
+
23
+ require 'bundler/gem_tasks'
24
+
25
+ require 'rake/testtask'
26
+
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/saml_camel .js
2
+ //= link_directory ../stylesheets/saml_camel .css
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,80 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #333;
4
+ margin: 33px;
5
+ }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a {
20
+ color: #000;
21
+ }
22
+
23
+ a:visited {
24
+ color: #666;
25
+ }
26
+
27
+ a:hover {
28
+ color: #fff;
29
+ background-color: #000;
30
+ }
31
+
32
+ th {
33
+ padding-bottom: 5px;
34
+ }
35
+
36
+ td {
37
+ padding: 0 5px 7px;
38
+ }
39
+
40
+ div.field,
41
+ div.actions {
42
+ margin-bottom: 10px;
43
+ }
44
+
45
+ #notice {
46
+ color: green;
47
+ }
48
+
49
+ .field_with_errors {
50
+ padding: 2px;
51
+ background-color: red;
52
+ display: table;
53
+ }
54
+
55
+ #error_explanation {
56
+ width: 450px;
57
+ border: 2px solid red;
58
+ padding: 7px 7px 0;
59
+ margin-bottom: 20px;
60
+ background-color: #f0f0f0;
61
+ }
62
+
63
+ #error_explanation h2 {
64
+ text-align: left;
65
+ font-weight: bold;
66
+ padding: 5px 5px 5px 15px;
67
+ font-size: 12px;
68
+ margin: -7px -7px 0;
69
+ background-color: #c00;
70
+ color: #fff;
71
+ }
72
+
73
+ #error_explanation ul li {
74
+ font-size: 12px;
75
+ list-style: square;
76
+ }
77
+
78
+ label {
79
+ display: block;
80
+ }
@@ -0,0 +1,30 @@
1
+ require_dependency "saml_camel/application_controller"
2
+
3
+ module SamlCamel::SamlHelpers
4
+ extend ActiveSupport::Concern
5
+
6
+ #this generates a call to the idp, which will then be returned to the consume action the in saml_contorller
7
+ def saml_request(host_request)
8
+ request = OneLogin::RubySaml::Authrequest.new
9
+ cookies.encrypted[:saml_camel_redirect] = host_request.url
10
+ redirect_to(request.create(SamlCamel::Transaction.saml_settings))
11
+ end
12
+
13
+
14
+ def saml_reset
15
+ session[:saml_success] = nil
16
+ end
17
+
18
+
19
+ def saml_protect
20
+ begin
21
+ saml_request(request) unless (session[:saml_success] || session[:sp_session]) #keeps us from looping, and maintains sp session
22
+ yield
23
+ ensure
24
+ saml_reset #keeps us from looping
25
+ end
26
+ end
27
+
28
+
29
+
30
+ end
@@ -0,0 +1,5 @@
1
+ module SamlCamel
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,48 @@
1
+ require_dependency "saml_camel/application_controller"
2
+
3
+ module SamlCamel
4
+ class SamlController < ApplicationController
5
+ skip_before_action :verify_authenticity_token ,only: [:consume,:logout]
6
+
7
+
8
+ #TODO ROUTABLE STUFF GOES IN THE SHIB CONTROLLER, METHODS CALLED BUT NOT ROUTED GO TO SAML_CONTROLLER
9
+ def index
10
+ @attributes = session[:saml_attributes]
11
+ end
12
+
13
+ def consume
14
+ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], :settings => saml_settings)
15
+ response.settings = saml_settings
16
+
17
+ if response.is_valid? # validate the SAML Response
18
+ # authorize_success, log the user
19
+ session[:saml_success] = true
20
+ session[:sp_session] = true
21
+ session[:saml_attributes] = SamlCamel::Transaction.map_attributes(response.attributes)
22
+
23
+ #TODO account for nil redirect
24
+ redirect_to cookies.encrypted[:saml_camel_redirect]
25
+ else # otherwise list out the errors in the response
26
+ #TODO how do we handle errors?
27
+ session[:saml_success] = false
28
+ response.errors
29
+ redirect_to main_app.try('root_path')
30
+ end
31
+ end
32
+
33
+ def logout
34
+ session[:saml_attributes] = nil
35
+ session[:sp_session] = nil
36
+
37
+ return_url = SamlCamel::Transaction.logout #this methods logs the user out of the IDP, and returns a url to be redirected to
38
+ redirect_to return_url
39
+ end
40
+
41
+
42
+ private
43
+ def saml_settings
44
+ SamlCamel::Transaction.saml_settings
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,4 @@
1
+ module SamlCamel
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module SamlCamel
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module SamlCamel
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module SamlCamel
2
+ class ApplicationRecord
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,69 @@
1
+ module SamlCamel
2
+ class Transaction
3
+ SP_SETTINGS = JSON.parse(File.read("saml/#{Rails.env}/settings.json"))
4
+
5
+ def self.saml_settings
6
+ sp_settings = SP_SETTINGS["settings"]
7
+ settings = OneLogin::RubySaml::Settings.new
8
+ settings.assertion_consumer_service_url = sp_settings["acs"]
9
+
10
+
11
+ settings.issuer = sp_settings["entity_id"]
12
+ settings.idp_sso_target_url = sp_settings["sso_url"]
13
+
14
+
15
+ #certificate to register with IDP and key to decrypt
16
+ settings.certificate = File.read("saml/#{Rails.env}/saml_certificate.crt")
17
+
18
+ #certificate to decrypt SAML response
19
+ settings.private_key = File.read("saml/#{Rails.env}/saml_key.key")
20
+
21
+ #certificate to verify IDP signature
22
+ settings.idp_cert = File.read("saml/#{Rails.env}/idp_certificate.crt")
23
+
24
+ # Optional for most SAML IdPs
25
+ settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
26
+ settings.attribute_consuming_service.configure do
27
+ service_name "Service"
28
+ service_index 5
29
+ add_attribute :redirect_path => "root_path"
30
+ end
31
+ settings
32
+ end
33
+
34
+ def self.map_attributes(attrs)
35
+ attr_map = SP_SETTINGS["attribute_map"]
36
+ mapped_attributes = {}
37
+
38
+ attrs.each do |attr,value|
39
+ mapped_name = attr_map[attr]
40
+ if mapped_name.nil? #handles attributes not in map
41
+ mapped_attributes[attr] = value
42
+ else
43
+ mapped_attributes[mapped_name] = value
44
+ end
45
+ end
46
+ mapped_attributes
47
+ end
48
+
49
+
50
+ def self.logout
51
+ url = URI("https://shib.oit.duke.edu/cgi-bin/logout.pl")
52
+
53
+ http = Net::HTTP.new(url.host, url.port)
54
+ http.use_ssl = true
55
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
+
57
+ request = Net::HTTP::Post.new(url)
58
+ request["authorization"] = 'Basic c29hcC5pZG1zLm9pdDowRGFvdXU2Y1g4MEJ1Vkg2QlFaaA=='
59
+ request["content-type"] = 'application/x-www-form-urlencoded'
60
+ request["cache-control"] = 'no-cache'
61
+ request.body = "logoutWithoutPrompt=1"
62
+
63
+ response = http.request(request)
64
+
65
+ logout_return = SP_SETTINGS["settings"]["logout_return_url"]
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Saml camel</title>
5
+ <%= stylesheet_link_tag "saml_camel/application", media: "all" %>
6
+ <%= javascript_include_tag "saml_camel/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ SamlCamel::Engine.routes.draw do
2
+ get "/" => "saml#index"
3
+ post "/consumeSaml" => "saml#consume"
4
+ post "/logout" => "saml#logout"
5
+ end
data/lib/saml_camel.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "saml_camel/engine"
2
+
3
+ module SamlCamel
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'onelogin/ruby-saml'
3
+
4
+ module SamlCamel
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace SamlCamel
7
+
8
+ config.to_prepare do
9
+
10
+ Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
11
+ require_dependency(c)
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module SamlCamel
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,155 @@
1
+ namespace :saml_camel do
2
+ desc "Generate Files for Saml"
3
+ task :generate_saml do
4
+ dir = "#{Rails.root}/saml/"
5
+ FileUtils.mkdir(dir) unless Dir.exists?(dir)
6
+
7
+ specified_env = ENV['environment']
8
+ default_envs = ["production","test","development"]
9
+ key = generate_key
10
+ cert = generate_cert(key)
11
+ settings = generate_saml_settings.to_json
12
+
13
+ #TODO pull in specified idp certificate
14
+ # idp_cert = File.read("saml/idp_certs/#{ENV['idp']}.crt") if ENV['idp']
15
+ idp_cert = """MIIEWjCCA0KgAwIBAgIJAP1rB/FjRgy6MA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
16
+ BAYTAlVTMRcwFQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEPMA0GA1UEBxMGRHVyaGFt
17
+ MRgwFgYDVQQKEw9EdWtlIFVuaXZlcnNpdHkxDDAKBgNVBAsTA09JVDEaMBgGA1UE
18
+ AxMRc2hpYi5vaXQuZHVrZS5lZHUwHhcNMTAwOTA5MTI0NDU1WhcNMjgwOTA0MTI0
19
+ NDU1WjB7MQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzAN
20
+ BgNVBAcTBkR1cmhhbTEYMBYGA1UEChMPRHVrZSBVbml2ZXJzaXR5MQwwCgYDVQQL
21
+ EwNPSVQxGjAYBgNVBAMTEXNoaWIub2l0LmR1a2UuZWR1MIIBIjANBgkqhkiG9w0B
22
+ AQEFAAOCAQ8AMIIBCgKCAQEAt+hnl6gSRi0Y8VuNl6PCPYejj7VfVs/y8bRa5zAY
23
+ RHwb75+vBSs2j1yeUcSore9Ba5Ni7v947V34afRMGRPOqr4TEDZxU+1Bg0zAvSrR
24
+ n4Y8B+zyJuhtOpmOZzTwE9o/Oc+CB4kYV/K0woKZdcoxHJm8TbqBqdxU4fFYUlNU
25
+ o4Dr5jRdCSr9MHBOqGWXtQMg16qYNB7StNk4twY29FNnpZwkVTfsE76uVsRMkG8i
26
+ 6/RiHpXZ/ioOOqndptbEGdsOIE3ivAJOZdvYwnDe5NnTH06P01HsxH3OOnYqhuG2
27
+ J6qdhqoelGeHRG+jfl8YkYXCcKQvja2tJ5G+6iqSN7DP6QIDAQABo4HgMIHdMB0G
28
+ A1UdDgQWBBQHYXwB6otkfyMOmUI59j8823hFRDCBrQYDVR0jBIGlMIGigBQHYXwB
29
+ 6otkfyMOmUI59j8823hFRKF/pH0wezELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5v
30
+ cnRoIENhcm9saW5hMQ8wDQYDVQQHEwZEdXJoYW0xGDAWBgNVBAoTD0R1a2UgVW5p
31
+ dmVyc2l0eTEMMAoGA1UECxMDT0lUMRowGAYDVQQDExFzaGliLm9pdC5kdWtlLmVk
32
+ dYIJAP1rB/FjRgy6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG7q
33
+ wJpiSLJbx2gj/cGDYeuBW/CeRGNghjQ/mb076P3WXsRNPAimcXulSUbQkS6eDH4t
34
+ Ifvsa0jf4FRsEOwH/x8354/0wyv4RwuavX25kjpmoFn3O+eKokyzsc7/Q2gsm0mv
35
+ V8XQo+5b+4we8AFYlAVp26nLeIqAiJM8xZJ9yHuzVL1O4yxIWIKECWHLqY5+1nas
36
+ XNiLURrHhsK5pZUPLuhzJFgZuJT62TtnrjJXlrRhJ389VSkh6R64C6ncjNkg6/Cu
37
+ tA6SX0infqNRyPRNJK+bnQd1yOP4++tjD/lAPE+5tiD/waI3fArt43ZE/qp7pYMS
38
+ 9TEfyQ5QpfRYAUFWXBc=
39
+ """
40
+
41
+ unless specified_env
42
+ default_envs.each do |e|
43
+ dir = "#{Rails.root}/saml/#{e}"
44
+ FileUtils.mkdir(dir) unless Dir.exists?(dir)
45
+ File.open("#{Rails.root}/saml/#{e}/saml_certificate.crt","w+") {|f| f.write(cert) }
46
+ File.open("#{Rails.root}/saml/#{e}/saml_key.key","w+") {|f| f.write(key) }
47
+ File.open("#{Rails.root}/saml/#{e}/idp_certificate.crt","w+") {|f| f.write(idp_cert) }
48
+ File.open("#{Rails.root}/saml/#{e}/settings.json","w+") {|f| f.write(settings) }
49
+ end
50
+ else
51
+ dir = "#{Rails.root}/saml/#{specified_env}"
52
+ FileUtils.mkdir(dir) unless Dir.exists?(dir)
53
+ File.open("#{Rails.root}/saml/#{specified_env}/saml_certificate.crt","w+") {|f| f.write(cert) }
54
+ File.open("#{Rails.root}/saml/#{specified_env}/saml_key.key","w+") {|f| f.write(key) }
55
+ File.open("#{Rails.root}/saml/#{specified_env}/idp_certificate.crt","w+") {|f| f.write(idp_cert) }
56
+ File.open("#{Rails.root}/saml/#{specified_env}/settings.json","w+") {|f| f.write(settings) }
57
+ end
58
+ end
59
+
60
+
61
+
62
+
63
+
64
+
65
+ def generate_saml_settings
66
+ {
67
+ _comment: "note you will need to restart the application when you make changes to this file",
68
+ settings: {
69
+ acs: "http://localhost:3000/saml/consumeSaml" ,
70
+ entity_id: "https://your-entity-id.com",
71
+ sso_url: "https://shib.oit.duke.edu/idp/profile/SAML2/Redirect/SSO",
72
+ logout_return_url: "http://localhost:3000"
73
+ },
74
+ "attribute_map": {
75
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.9": "eduPersonScopedAffiliation",
76
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.6": "eduPersonPrincipalName",
77
+ "urn:oid:2.5.4.3": "cn",
78
+ "urn:oid:0.9.2342.19200300.100.1.1": "uid",
79
+ "urn:oid:0.9.2342.19200300.100.1.3": "mail",
80
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.5": "eduPersonPrimaryAffiliation",
81
+ "urn:oid:2.16.840.1.113730.3.1.241": "displayName",
82
+ "urn:mace:duke.edu:idms:unique-id": "duDukeID",
83
+ "urn:mace:duke.edu:idms:dku-id": "urn:mace:duke.edu:idms:dku-id",
84
+ "urn:oid:1.3.6.1.4.1.5923.1.5.1.1": "isMemberOf",
85
+ "urn:oid:2.5.4.42": "givenName",
86
+ "urn:oid:2.5.4.4": "sn",
87
+ "urn:oid:2.5.4.11": "ou",
88
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.1": "eduPersonAffiliation",
89
+ "urn:oid:2.5.4.20": "telephoneNumber",
90
+ "urn:oid:2.5.4.12": "title",
91
+ "urn:mace:duke.edu:idms:middle-name1": "duMiddleName1",
92
+ "urn:mace:duke.edu:idms:sap:name-first": "duSAPNameFirst",
93
+ "urn:mace:duke.edu:idms:sap:name-last": "duSAPNameLast",
94
+ "urn:mace:duke.edu:idms:proxy-token": "duProxyToken"
95
+ }
96
+ }
97
+ end
98
+
99
+
100
+ def generate_key
101
+ OpenSSL::PKey::RSA.new(2048)
102
+ end
103
+
104
+ def generate_cert(key)
105
+ STDOUT.puts "Country Name (2 letter code) [AU]:"
106
+ country = STDIN.gets.strip
107
+
108
+ STDOUT.puts "State or Province Name (full name) [Some-State]:"
109
+ state = STDIN.gets.strip
110
+
111
+ STDOUT.puts "Locality Name (eg, city):"
112
+ city = STDIN.gets.strip
113
+
114
+ STDOUT.puts "Organization Name (eg, company):"
115
+ org = STDIN.gets.strip
116
+
117
+ STDOUT.puts "Organizational Unit Name (eg, section):"
118
+ unit = STDIN.gets.strip
119
+
120
+ STDOUT.puts "Common Name (non url name, remember this is not a server cert):"
121
+ cn = STDIN.gets.strip
122
+
123
+ STDOUT.puts "Email Address:"
124
+ email = STDIN.gets.strip
125
+
126
+
127
+ public_key = key.public_key
128
+
129
+ #generate subject line of cert
130
+ subject = "/C=#{country}/ST=#{state}/L=#{city}/O=#{org}/OU=#{unit}/CN=#{cn}/emailAddress=#{email}"
131
+
132
+ cert = OpenSSL::X509::Certificate.new
133
+ cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject) #TODO this line breaks when https:// is added for CN
134
+ cert.not_before = Time.now
135
+ cert.not_after = Time.now + 365 * 24 * 60 * 60
136
+ cert.public_key = public_key
137
+ cert.serial = 0x0
138
+ cert.version = 2
139
+
140
+ ef = OpenSSL::X509::ExtensionFactory.new
141
+ ef.subject_certificate = cert
142
+ ef.issuer_certificate = cert
143
+ cert.extensions = [
144
+ ef.create_extension("basicConstraints","CA:TRUE", true),
145
+ ef.create_extension("subjectKeyIdentifier", "hash"),
146
+ # ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
147
+ ]
148
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
149
+ "keyid:always,issuer:always")
150
+
151
+ cert.sign key, OpenSSL::Digest::SHA256.new
152
+ end
153
+
154
+
155
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: saml_camel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - 'Danai Adkisson '
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-saml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: ruby-saml
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.7.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.7.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: SAML tool wrapping onelogin/rubysaml
70
+ email:
71
+ - da129@duke.edu
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - MIT-LICENSE
77
+ - README.md
78
+ - Rakefile
79
+ - app/assets/config/saml_camel_manifest.js
80
+ - app/assets/javascripts/saml_camel/application.js
81
+ - app/assets/stylesheets/saml_camel/application.css
82
+ - app/assets/stylesheets/scaffold.css
83
+ - app/controllers/concerns/saml_camel/saml_helpers.rb
84
+ - app/controllers/saml_camel/application_controller.rb
85
+ - app/controllers/saml_camel/saml_controller.rb
86
+ - app/helpers/saml_camel/application_helper.rb
87
+ - app/jobs/saml_camel/application_job.rb
88
+ - app/mailers/saml_camel/application_mailer.rb
89
+ - app/models/saml_camel/application_record.rb
90
+ - app/models/saml_camel/transaction.rb
91
+ - app/views/layouts/saml_camel/application.html.erb
92
+ - config/routes.rb
93
+ - lib/saml_camel.rb
94
+ - lib/saml_camel/engine.rb
95
+ - lib/saml_camel/version.rb
96
+ - lib/tasks/saml_camel_tasks.rake
97
+ homepage: https://oit.duke.edu
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.5.1
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: SAML tool wrapping onelogin/rubysaml
121
+ test_files: []