integration_pal 0.1.6 → 0.2.0

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 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