saml_camel 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []