integration_pal 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 80040423f29a4fcef6b0484d692b920d8adf1733
4
- data.tar.gz: a46fcfbf475673dd23a9a731606ed89ad75477a9
3
+ metadata.gz: 74caae0c072309e715b66419e74685509269ea75
4
+ data.tar.gz: 4091c879c8b127dc76941f33826b69747f06511e
5
5
  SHA512:
6
- metadata.gz: c10ff705ba4bbb3c0d92dce046a03a7255e101502abd98bf78f7c0c6444edb86156be076231d2836b23bafe2a6d3f79f2a84d7648c72e1f7a32aaf93c07c7cc8
7
- data.tar.gz: e3f33b7bfef7e922e909ec13174ec026c791c789a9ff454df2e457116f5fbe7aa279063b400aa30b01c9a043fb11801409adf92516c63f624f916d467b9cc905
6
+ metadata.gz: ebd076d4c5f3e5d5a72babca42402fedf3f558d3696f9af342edae583dace2642c4aef323a1a352d6b25f4d9fdd156ca92bdabfffc7181a15541c7f401d1868f
7
+ data.tar.gz: '0987932589a5431135b3625f491f01df1ce6d08ec3ed481c2584579319092e58fd4b1f775694fb7862670a885c796263b3973c1416d753d1ac1decc2c9e562f9'
data/README.md CHANGED
@@ -4,44 +4,104 @@ This engine is meant to contain the elements of big_sis that can be shared acros
4
4
  - job starting
5
5
  - job monitoring
6
6
  - error capturing
7
- - cas authentication
7
+ - Okta SAML2 authentication
8
8
 
9
9
  ## Usage
10
10
  1) Create an active job
11
11
  `bin/rails generate job example_job`
12
12
 
13
13
  ## Installation
14
- Add this line to your application's Gemfile:
15
-
16
- ```ruby
17
- gem 'integration_pal'
18
- ```
14
+ 1. Add `integration_pal` to your application's Gemfile:
15
+ ```ruby
16
+ gem 'integration_pal'
17
+ ```
18
+
19
+ And install the bundle:
20
+ ```bash
21
+ $ bundle install
22
+ ```
23
+ ---
24
+ Or install the Gem manually:
25
+ ```bash
26
+ $ gem install integration_pal
27
+ ```
28
+ 2. Define Environment variables
29
+ ```bash
30
+ ENCRYPTION_KEY=... # must be 32 chars
31
+ SALT_KEY=... # must be 32 chars
32
+
33
+ OKTA_APP=okta_app_key
34
+ OKTA_ID=xxxxxxxxxxx # Usually Base64
35
+ SAML_DOMAIN=https://example-app-test.herokuapp.com/
36
+ SAML_AUDIENCE=https://example-app.herokuapp.com/login # If using a single Okta app for all environments, this should be set to the prod instance + /login
37
+ ```
38
+
39
+ 3. Generate template files for your project:
40
+ ```
41
+ $ bundle exec rails g integration_pal:install
42
+ ```
43
+
44
+ 4. Set active job
45
+ config.active_job.queue_adapter = :sidekiq # If you are using sidekiq
19
46
 
20
- And then execute:
21
- ```bash
22
- $ bundle
47
+ 4. Configure app.
48
+ Include `sp_metadata.xml[.erb]` in `config/saml`:
49
+ ```xml
50
+ <?xml version="1.0"?>
51
+ <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="<%= ENV['SAML_AUDIENCE'] || URI.join(ENV['SAML_DOMAIN'], saml2_meta_path) %>">
52
+ <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
53
+ <md:AssertionConsumerService Location="<%= URI.join(ENV['SAML_DOMAIN'], saml2_login_path) %>" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" index="0"/>
54
+ </md:SPSSODescriptor>
55
+ </md:EntityDescriptor>
56
+ ```
57
+
58
+ Also include `idp_metadata.xml[.erb]` in `config/saml`:
59
+ ```xml
60
+ <?xml version="1.0" encoding="UTF-8"?>
61
+ <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://www.okta.com/<%= ENV['OKTA_ID'] %>">
62
+ <md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
63
+ <md:KeyDescriptor use="signing">
64
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
65
+ <ds:X509Data>
66
+ <ds:X509Certificate>
67
+ {{ INSERT OKTA CERTIFICATE HERE }}
68
+ </ds:X509Certificate>
69
+ </ds:X509Data>
70
+ </ds:KeyInfo>
71
+ </md:KeyDescriptor>
72
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
73
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
74
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://instructure.okta.com/app/<%= ENV['OKTA_APP'] %>/<%= ENV['OKTA_ID'] %>/sso/saml"/>
75
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://instructure.okta.com/app/<%= ENV['OKTA_APP'] %>/<%= ENV['OKTA_ID'] %>/sso/saml"/>
76
+ </md:IDPSSODescriptor>
77
+ </md:EntityDescriptor>
78
+ ```
79
+
80
+ Metadata file names can be overriden from within an initializer:
81
+ ```ruby
82
+ IntegrationPal.saml_idp_metadata = 'idp_metadata.xml'
83
+ IntegrationPal.saml_sp_metadata = 'sp_metadata.xml'
84
+ ```
85
+
86
+ To validate or begin Okta authentication within a controller, use:
87
+ ```ruby
88
+ session[:saml_username] ||= ENV['USER'] if Rails.env.in?(%w(development test))
89
+ redirect_to saml2_login_url unless session[:saml_username]
90
+ ```
91
+
92
+ ### Deploying to Heroku
93
+ The SAML2 Authentication library that this tool uses requires `libxmlsec1-dev`. In order to ensure that it is installed on the Heroku dyno, add https://github.com/ABASystems/heroku-buildpack-apt as the first buildpack in Heroku, followed by `heroku/ruby`. Also include an `Aptfile` in the root of your project:
23
94
  ```
24
-
25
- Or install it yourself as:
26
- ```bash
27
- $ gem install integration_pal
95
+ libxmlsec1-dev
28
96
  ```
29
-
30
- 1) SET ENV VARS
31
- ENV['ENCRYPTION_KEY'] # this must be 32 chars
32
- ENV['SALT_KEY'] # this must be 32 chars
33
-
34
- 2) run `bundle exec rails g integration_pal:install`
35
-
36
- 3)set active job
37
- config.active_job.queue_adapter = :sidekiq # If you are using sidekiq
97
+ ! - Double check this if Heroku fails to build Gem native extensions for `nokogiri-xmlsec-instructure` during deployment.
38
98
 
39
99
  ## License
40
100
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
101
 
42
- ## EXAMPLE API REQUEST
43
- # Note how we sign the requesting using ApiAuth
44
-
102
+ ## Example API Request
103
+ Note how we sign the request using ApiAuth
104
+ ```ruby
45
105
  require "uri"
46
106
  require "net/https"
47
107
  require "time"
@@ -71,4 +131,5 @@ request.body = {
71
131
  ApiAuth.sign!(request, access_key_id, secret_access_key)
72
132
 
73
133
  response = http.request(request)
74
- puts response.body
134
+ puts response.body
135
+ ```
@@ -1,8 +1,16 @@
1
- require "rack-cas-rails"
2
-
3
1
  module IntegrationPal
4
2
  class ApplicationController < ActionController::Base
5
3
  protect_from_forgery with: :exception
6
- before_action :authenticate!
4
+ before_action :require_user, unless: :skip_authentication?
5
+
6
+ def skip_authentication?
7
+ return false
8
+ end
9
+
10
+ def require_user
11
+ # pretend to be logged in; you can still go directly to /login if you want to test the SAML flow
12
+ session[:saml_username] ||= ENV['USER'] if Rails.env.in?(%w(development test))
13
+ redirect_to saml2_login_url unless session[:saml_username]
14
+ end
7
15
  end
8
16
  end
@@ -0,0 +1,69 @@
1
+ module IntegrationPal
2
+ class SamlController < ApplicationController
3
+ class << self
4
+ def parse_meta_file(filename)
5
+ possible_names = ['.erb', ''].map { |ext| filename+ext }
6
+ possible_paths = []
7
+
8
+ ['config/saml', 'config'].each do |prefix|
9
+ possible_names.each do |filename|
10
+ possible_paths << Rails.root.join(prefix, filename)
11
+ end
12
+ end
13
+
14
+ meta_path = possible_paths.find &:exist?
15
+
16
+ meta_file = File.read(meta_path)
17
+ if meta_path.extname == '.erb'
18
+ meta_file = ERB.new(meta_file).result(ERBContext.new.get_binding)
19
+ end
20
+ SAML2::Entity.parse(meta_file)
21
+ end
22
+
23
+ def idp_metadata
24
+ @idp_metadata ||= parse_meta_file(IntegrationPal.saml_idp_metadata)
25
+ end
26
+
27
+ def sp_metadata
28
+ @sp_metadata ||= parse_meta_file(IntegrationPal.saml_sp_metadata)
29
+ end
30
+
31
+ class ERBContext
32
+ include Rails.application.routes.url_helpers
33
+
34
+ def get_binding
35
+ binding
36
+ end
37
+ end
38
+ end
39
+
40
+ protect_from_forgery except: [:create]
41
+
42
+ def skip_authentication?
43
+ true
44
+ end
45
+
46
+ def new
47
+ authn_request = self.class.sp_metadata.initiate_authn_request(self.class.idp_metadata)
48
+ redirect_to SAML2::Bindings::HTTPRedirect.encode(authn_request)
49
+ end
50
+
51
+ def create
52
+ response, _relay_state = SAML2::Bindings::HTTP_POST.decode(request.request_parameters)
53
+ unless self.class.sp_metadata.valid_response?(response, self.class.idp_metadata)
54
+ logger.error("Failed to validate SAML response: #{response.errors}")
55
+ raise ActionController::RoutingError.new('Not Found')
56
+ end
57
+
58
+ reset_session
59
+ session[:saml_username] = response.assertions.first.subject.name_id.id
60
+ logger.info("Logged in using SAML2 as #{session[:saml_username]}")
61
+
62
+ redirect_to root_url
63
+ end
64
+
65
+ def metadata
66
+ render xml: self.class.sp_metadata.to_xml
67
+ end
68
+ end
69
+ end
data/config/routes.rb CHANGED
@@ -1,4 +1,10 @@
1
1
  IntegrationPal::Engine.routes.draw do
2
+ scope as: 'saml2' do
3
+ get 'login' => 'saml#new'
4
+ post 'login' => 'saml#create'
5
+ get 'SAML2' => 'saml#metadata', as: 'meta'
6
+ end
7
+
2
8
  root to: 'workers#index'
3
9
  resources :workers
4
10
  resources :jobs
@@ -2,12 +2,6 @@ module IntegrationPal
2
2
  class InstallGenerator < Rails::Generators::Base
3
3
  source_root File.expand_path('../templates', __FILE__)
4
4
 
5
- desc "Add CAS config to application.rb"
6
- def update_application_config
7
- application "@cas_server_url = 'https://cas-sso.instructure.com/'"
8
- application "config.rack_cas.server_url = @cas_server_url"
9
- end
10
-
11
5
  desc "Mount the engine"
12
6
  def add_routes
13
7
  route "mount IntegrationPal::Engine, at: IntegrationPal::Engine.mounted_path"
@@ -21,5 +15,16 @@ module IntegrationPal
21
15
  end
22
16
  end
23
17
 
18
+ desc "Add an initializer"
19
+ def add_initializer
20
+ initializer "integration_pal.rb" do
21
+ content = <<-'RUBY'
22
+ # SAML XML Metadata files. Looked for in config/saml. Automatically looks for an existing *.erb version as well.
23
+ # IntegrationPal.saml_idp_metadata = 'idp_metadata.xml'
24
+ # IntegrationPal.saml_sp_metadata = 'sp_metadata.xml'
25
+ RUBY
26
+ end
27
+ end
28
+
24
29
  end
25
30
  end
@@ -1,5 +1,6 @@
1
1
  require "integration_pal/engine"
2
2
 
3
3
  module IntegrationPal
4
- # Your code goes here...
4
+ saml_idp_metadata = 'idp_metadata.xml'
5
+ saml_sp_metadata = 'sp_metadata.xml'
5
6
  end
@@ -1,8 +1,6 @@
1
1
  module IntegrationPal
2
2
  class Engine < ::Rails::Engine
3
3
  require 'api-auth'
4
- require 'rack-cas'
5
- require 'rack-cas-rails'
6
4
  require 'attr_encrypted'
7
5
  require 'jquery-rails'
8
6
 
@@ -1,3 +1,3 @@
1
1
  module IntegrationPal
2
- VERSION = '0.1.6'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: integration_pal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Tanner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-02 00:00:00.000000000 Z
11
+ date: 2018-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.0.3
55
- - !ruby/object:Gem::Dependency
56
- name: rack-cas-rails
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 2.0.2
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 2.0.2
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: sentry-raven
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +108,20 @@ dependencies:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
110
  version: 4.3.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: saml2
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 2.2.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.2.1
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: pg
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -211,6 +211,7 @@ files:
211
211
  - app/controllers/integration_pal/api_controller.rb
212
212
  - app/controllers/integration_pal/application_controller.rb
213
213
  - app/controllers/integration_pal/jobs_controller.rb
214
+ - app/controllers/integration_pal/saml_controller.rb
214
215
  - app/controllers/integration_pal/tasks_controller.rb
215
216
  - app/controllers/integration_pal/workers_controller.rb
216
217
  - app/helpers/integration_pal/application_helper.rb
@@ -314,8 +315,6 @@ files:
314
315
  - spec/dummy/config/secrets.yml
315
316
  - spec/dummy/config/spring.rb
316
317
  - spec/dummy/db/schema.rb
317
- - spec/dummy/log/development.log
318
- - spec/dummy/log/test.log
319
318
  - spec/dummy/package.json
320
319
  - spec/dummy/public/404.html
321
320
  - spec/dummy/public/422.html
@@ -351,73 +350,71 @@ required_rubygems_version: !ruby/object:Gem::Requirement
351
350
  version: '0'
352
351
  requirements: []
353
352
  rubyforge_project:
354
- rubygems_version: 2.6.11
353
+ rubygems_version: 2.5.2.1
355
354
  signing_key:
356
355
  specification_version: 4
357
356
  summary: Mountable engine for SIS integrations
358
357
  test_files:
359
- - spec/controllers/integration_pal/api/v1/jobs_controller_spec.rb
360
- - spec/controllers/integration_pal/jobs_controller_spec.rb
361
- - spec/controllers/integration_pal/workers_controller_spec.rb
362
- - spec/dummy/app/assets/config/manifest.js
363
- - spec/dummy/app/assets/javascripts/application.js
364
- - spec/dummy/app/assets/javascripts/cable.js
365
- - spec/dummy/app/assets/stylesheets/application.css
366
- - spec/dummy/app/channels/application_cable/channel.rb
367
- - spec/dummy/app/channels/application_cable/connection.rb
368
- - spec/dummy/app/controllers/application_controller.rb
369
- - spec/dummy/app/helpers/application_helper.rb
370
- - spec/dummy/app/jobs/application_job.rb
371
- - spec/dummy/app/jobs/test_job.rb
358
+ - spec/spec_helper.rb
372
359
  - spec/dummy/app/mailers/application_mailer.rb
373
360
  - spec/dummy/app/models/application_record.rb
361
+ - spec/dummy/app/jobs/application_job.rb
362
+ - spec/dummy/app/jobs/test_job.rb
363
+ - spec/dummy/app/controllers/application_controller.rb
374
364
  - spec/dummy/app/views/layouts/application.html.erb
375
365
  - spec/dummy/app/views/layouts/mailer.html.erb
376
366
  - spec/dummy/app/views/layouts/mailer.text.erb
377
- - spec/dummy/bin/bundle
378
- - spec/dummy/bin/rails
367
+ - spec/dummy/app/assets/config/manifest.js
368
+ - spec/dummy/app/assets/javascripts/cable.js
369
+ - spec/dummy/app/assets/javascripts/application.js
370
+ - spec/dummy/app/assets/stylesheets/application.css
371
+ - spec/dummy/app/helpers/application_helper.rb
372
+ - spec/dummy/app/channels/application_cable/connection.rb
373
+ - spec/dummy/app/channels/application_cable/channel.rb
374
+ - spec/dummy/bin/update
379
375
  - spec/dummy/bin/rake
380
376
  - spec/dummy/bin/setup
381
- - spec/dummy/bin/update
377
+ - spec/dummy/bin/bundle
382
378
  - spec/dummy/bin/yarn
383
- - spec/dummy/config/application.rb
384
- - spec/dummy/config/boot.rb
379
+ - spec/dummy/bin/rails
380
+ - spec/dummy/config/secrets.yml
381
+ - spec/dummy/config/routes.rb
382
+ - spec/dummy/config/locales/en.yml
385
383
  - spec/dummy/config/cable.yml
386
- - spec/dummy/config/database.yml
387
- - spec/dummy/config/environment.rb
388
- - spec/dummy/config/environments/development.rb
389
384
  - spec/dummy/config/environments/production.rb
385
+ - spec/dummy/config/environments/development.rb
390
386
  - spec/dummy/config/environments/test.rb
387
+ - spec/dummy/config/spring.rb
388
+ - spec/dummy/config/environment.rb
389
+ - spec/dummy/config/application.rb
390
+ - spec/dummy/config/puma.rb
391
+ - spec/dummy/config/database.yml
392
+ - spec/dummy/config/boot.rb
391
393
  - spec/dummy/config/initializers/application_controller_renderer.rb
392
- - spec/dummy/config/initializers/assets.rb
393
394
  - spec/dummy/config/initializers/backtrace_silencers.rb
394
- - spec/dummy/config/initializers/cookies_serializer.rb
395
- - spec/dummy/config/initializers/filter_parameter_logging.rb
396
- - spec/dummy/config/initializers/inflections.rb
397
395
  - spec/dummy/config/initializers/mime_types.rb
396
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
398
397
  - spec/dummy/config/initializers/wrap_parameters.rb
399
- - spec/dummy/config/locales/en.yml
400
- - spec/dummy/config/puma.rb
401
- - spec/dummy/config/routes.rb
402
- - spec/dummy/config/secrets.yml
403
- - spec/dummy/config/spring.rb
398
+ - spec/dummy/config/initializers/assets.rb
399
+ - spec/dummy/config/initializers/cookies_serializer.rb
400
+ - spec/dummy/config/initializers/inflections.rb
404
401
  - spec/dummy/config.ru
405
- - spec/dummy/db/schema.rb
406
- - spec/dummy/log/development.log
407
- - spec/dummy/log/test.log
408
- - spec/dummy/package.json
409
- - spec/dummy/public/404.html
402
+ - spec/dummy/Rakefile
403
+ - spec/dummy/public/favicon.ico
410
404
  - spec/dummy/public/422.html
405
+ - spec/dummy/public/apple-touch-icon.png
411
406
  - spec/dummy/public/500.html
407
+ - spec/dummy/public/404.html
412
408
  - spec/dummy/public/apple-touch-icon-precomposed.png
413
- - spec/dummy/public/apple-touch-icon.png
414
- - spec/dummy/public/favicon.ico
415
- - spec/dummy/Rakefile
416
- - spec/factories/integration_pal_jobs.rb
417
- - spec/factories/integration_pal_tasks.rb
418
- - spec/factories/integration_pal_workers.rb
419
- - spec/models/integration_pal/job_spec.rb
409
+ - spec/dummy/package.json
410
+ - spec/dummy/db/schema.rb
420
411
  - spec/models/integration_pal/task_spec.rb
412
+ - spec/models/integration_pal/job_spec.rb
421
413
  - spec/models/integration_pal/worker_spec.rb
414
+ - spec/factories/integration_pal_tasks.rb
415
+ - spec/factories/integration_pal_jobs.rb
416
+ - spec/factories/integration_pal_workers.rb
417
+ - spec/controllers/integration_pal/workers_controller_spec.rb
418
+ - spec/controllers/integration_pal/jobs_controller_spec.rb
419
+ - spec/controllers/integration_pal/api/v1/jobs_controller_spec.rb
422
420
  - spec/rails_helper.rb
423
- - spec/spec_helper.rb