spid 0.7.0 → 0.8.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
  SHA256:
3
- metadata.gz: 5a115dcdaeda82006ef3ffa4203bf6d4635d0a15e8b435f39429516f7cc931e7
4
- data.tar.gz: bcb065ec6ea653a8745680ef8805bb756deef2410d56aa91ce9b24a51673b851
3
+ metadata.gz: 2f0ea1fc4ad96eb6348fdeec0d727966d6ed6c10673805c00753c14e07c8a32e
4
+ data.tar.gz: 272888b9072bfd42f7cc714d26c27f0548210d62ddf452797d6b25c8ebc81108
5
5
  SHA512:
6
- metadata.gz: c731db6ddea64286e5543a07aee532eedaad1d0df79ca9b7b03555ba5e34864a17fa6ed9f81dc35ed21e7526acf41b6847e2476164edd147468008935f136772
7
- data.tar.gz: 813bd1abdc555ce0d54c9376d06d7b3e31e0908296ec343691e4ef8f7a08c4fa8d04fc0fdec8d7f1d6ecd4b6b8918c7ac6c890291ace8adec4348b099d6090ad
6
+ metadata.gz: 7d0c70aa33cd6c31bee3f306394c6f3c22d1b939bd60d694c701d561e02977305ed931bee5aa815ebc9d00ab1b54ed290f4fb901337b232ebdb79948d95aaa83
7
+ data.tar.gz: b732ec284055e6f602601285cbb51f9db450f8b294217b57f491dcf0e5f8d5cc9037a3fcd5fc3ce80aa98856286db76ab71ecfb4328593b6ce003b5b007f184d
@@ -14,8 +14,16 @@ Metrics/BlockLength:
14
14
  Metrics/LineLength:
15
15
  Exclude:
16
16
  - spid.gemspec
17
+ RSpec/DescribeClass:
18
+ Exclude:
19
+ - spec/integration/**/*.rb
20
+ RSpec/FilePath:
21
+ Exclude:
22
+ - spec/integration/**/*.rb
17
23
  RSpec/NestedGroups:
18
24
  Enabled: false
25
+ RSpec/SubjectStub:
26
+ Enabled: false
19
27
  Style/EmptyMethod:
20
28
  EnforcedStyle: expanded
21
29
  Style/StringLiterals:
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.8.0]
6
+ ### Added
7
+ - Spid configuration singleton class
8
+
9
+ ### Changed
10
+ - Slo prefixed classes moved to Slo:: Namespace
11
+ - Sso prefixed classes moved to Sso:: Namespace
12
+ - Request and Response classes generate themselves setting objects
13
+
5
14
  ## [0.7.0] - 2018-07-18
6
15
  ### Added
7
16
  - SloResponse class in order to validate saml response
@@ -56,7 +65,8 @@
56
65
  - Coveralls Integration
57
66
  - Rubygems version badge in README
58
67
 
59
- [Unreleased]: https://github.com/italia/spid-ruby/compare/v0.7.0...HEAD
68
+ [Unreleased]: https://github.com/italia/spid-ruby/compare/v0.8.0...HEAD
69
+ [0.8.0]: https://github.com/italia/spid-ruby/compare/v0.7.0...v0.8.0
60
70
  [0.7.0]: https://github.com/italia/spid-ruby/compare/v0.6.0...v0.7.0
61
71
  [0.6.0]: https://github.com/italia/spid-ruby/compare/v0.5.0...v0.6.0
62
72
  [0.5.0]: https://github.com/italia/spid-ruby/compare/v0.4.0...v0.5.0
data/README.md CHANGED
@@ -6,7 +6,7 @@ Ruby library for SPID authentication
6
6
  | Project | Spid Ruby |
7
7
  | ---------------------- | ------------ |
8
8
  | Gem name | spid |
9
- | License | [MIT](https://github.com/italia/spid-ruby/blob/master/LICENSE) |
9
+ | License | [BSD 3](https://github.com/italia/spid-ruby/blob/master/LICENSE) |
10
10
  | Version | [![Gem Version](https://badge.fury.io/rb/spid.svg)](http://badge.fury.io/rb/spid) |
11
11
  | Continuous integration | [![Build Status](https://secure.travis-ci.org/italia/spid-ruby.svg?branch=master)](https://travis-ci.org/italia/spid-ruby) |
12
12
  | Test coverate | [![Coverage Status](https://coveralls.io/repos/github/italia/spid-ruby/badge.svg?branch=master)](https://coveralls.io/github/italia/spid-ruby?branch=master) |
@@ -2,18 +2,14 @@
2
2
 
3
3
  require "spid/authn_request"
4
4
  require "spid/logout_request"
5
- require "spid/sso_request"
6
- require "spid/sso_response"
7
- require "spid/slo_request"
8
- require "spid/slo_response"
9
- require "spid/identity_providers"
5
+ require "spid/sso"
6
+ require "spid/slo"
10
7
  require "spid/metadata"
11
- require "spid/idp_metadata"
12
8
  require "spid/version"
13
- require "spid/identity_provider_configuration"
14
- require "spid/service_provider_configuration"
15
- require "spid/sso_settings"
16
- require "spid/slo_settings"
9
+ require "spid/configuration"
10
+ require "spid/identity_provider"
11
+ require "spid/service_provider"
12
+ require "spid/identity_provider_manager"
17
13
 
18
14
  module Spid # :nodoc:
19
15
  class UnknownAuthnComparisonMethodError < StandardError; end
@@ -22,13 +18,13 @@ module Spid # :nodoc:
22
18
  class UnknownSignatureMethodError < StandardError; end
23
19
 
24
20
  EXACT_COMPARISON = :exact
25
- MININUM_COMPARISON = :minumum
21
+ MINIMUM_COMPARISON = :minumum
26
22
  BETTER_COMPARISON = :better
27
23
  MAXIMUM_COMPARISON = :maximum
28
24
 
29
25
  COMPARISON_METHODS = [
30
26
  EXACT_COMPARISON,
31
- MININUM_COMPARISON,
27
+ MINIMUM_COMPARISON,
32
28
  BETTER_COMPARISON,
33
29
  MAXIMUM_COMPARISON
34
30
  ].freeze
@@ -62,4 +58,20 @@ module Spid # :nodoc:
62
58
  L2,
63
59
  L3
64
60
  ].freeze
61
+
62
+ class << self
63
+ attr_writer :configuration
64
+ end
65
+
66
+ def self.configuration
67
+ @configuration ||= Configuration.new
68
+ end
69
+
70
+ def self.reset_configuration!
71
+ @configuration = Configuration.new
72
+ end
73
+
74
+ def self.configure
75
+ yield configuration
76
+ end
65
77
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spid
4
+ class Configuration # :nodoc:
5
+ attr_accessor :idp_metadata_dir_path
6
+ attr_accessor :hostname
7
+ attr_accessor :metadata_path
8
+ attr_accessor :start_sso_path
9
+ attr_accessor :start_slo_path
10
+ attr_accessor :acs_path
11
+ attr_accessor :slo_path
12
+ attr_accessor :digest_method
13
+ attr_accessor :signature_method
14
+ attr_accessor :private_key
15
+ attr_accessor :certificate
16
+ attr_accessor :attribute_service_name
17
+
18
+ # rubocop:disable Metrics/MethodLength
19
+ def initialize
20
+ @idp_metadata_dir_path = "idp_metadata"
21
+ @metadata_path = "/spid/metadata"
22
+ @start_sso_path = "/spid/login"
23
+ @start_slo_path = "/spid/logout"
24
+ @acs_path = "/spid/sso"
25
+ @slo_path = "/spid/slo"
26
+ @digest_method = Spid::SHA256
27
+ @signature_method = Spid::RSA_SHA256
28
+ @attribute_service_name = attribute_service_name
29
+ @hostname = nil
30
+ @private_key = nil
31
+ @certificate = nil
32
+ end
33
+ # rubocop:enable Metrics/MethodLength
34
+
35
+ # rubocop:disable Metrics/MethodLength
36
+ def service_provider
37
+ @service_provider ||=
38
+ begin
39
+ Spid::ServiceProvider.new(
40
+ host: hostname,
41
+ acs_path: acs_path,
42
+ slo_path: slo_path,
43
+ metadata_path: metadata_path,
44
+ private_key: private_key,
45
+ certificate: certificate,
46
+ digest_method: digest_method,
47
+ signature_method: signature_method,
48
+ attribute_service_name: attribute_service_name
49
+ )
50
+ end
51
+ end
52
+ # rubocop:enable Metrics/MethodLength
53
+ end
54
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "onelogin/ruby-saml/idp_metadata_parser"
4
+
5
+ module Spid
6
+ class IdentityProvider # :nodoc:
7
+ attr_reader :name,
8
+ :entity_id,
9
+ :sso_target_url,
10
+ :slo_target_url,
11
+ :cert_fingerprint
12
+
13
+ def initialize(
14
+ name:,
15
+ entity_id:,
16
+ sso_target_url:,
17
+ slo_target_url:,
18
+ cert_fingerprint:
19
+ )
20
+ @name = name
21
+ @entity_id = entity_id
22
+ @sso_target_url = sso_target_url
23
+ @slo_target_url = slo_target_url
24
+ @cert_fingerprint = cert_fingerprint
25
+ end
26
+
27
+ def sso_attributes
28
+ @sso_attributes ||=
29
+ begin
30
+ {
31
+ idp_sso_target_url: sso_target_url,
32
+ idp_cert_fingerprint: cert_fingerprint
33
+ }
34
+ end
35
+ end
36
+
37
+ def slo_attributes
38
+ @slo_attributes ||=
39
+ begin
40
+ {
41
+ idp_slo_target_url: slo_target_url,
42
+ idp_name_qualifier: entity_id,
43
+ idp_cert_fingerprint: cert_fingerprint
44
+ }
45
+ end
46
+ end
47
+
48
+ def self.parse_from_xml(name:, metadata:)
49
+ idp_metadata_parser = ::OneLogin::RubySaml::IdpMetadataParser.new
50
+ idp_settings = idp_metadata_parser.parse_to_hash(metadata)
51
+ new(
52
+ name: name,
53
+ entity_id: idp_settings[:idp_entity_id],
54
+ sso_target_url: idp_settings[:idp_sso_target_url],
55
+ slo_target_url: idp_settings[:idp_slo_target_url],
56
+ cert_fingerprint: idp_settings[:idp_cert_fingerprint]
57
+ )
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spid
4
+ class IdentityProviderManager # :nodoc:
5
+ include Singleton
6
+
7
+ def identity_providers
8
+ @identity_providers ||=
9
+ begin
10
+ Dir.chdir(Spid.configuration.idp_metadata_dir_path) do
11
+ Dir.glob("*.xml").map do |metadata_filepath|
12
+ generate_identity_provider_from_file(
13
+ File.expand_path(metadata_filepath)
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.find_by_name(idp_name)
21
+ instance.identity_providers.find do |idp|
22
+ idp.name == idp_name
23
+ end
24
+ end
25
+
26
+ def self.find_by_entity(entity_id)
27
+ instance.identity_providers.find do |idp|
28
+ idp.entity_id == entity_id
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def generate_identity_provider_from_file(metadata_filepath)
35
+ idp_name = File.basename(metadata_filepath, "-metadata.xml")
36
+ metadata = File.read(metadata_filepath)
37
+ IdentityProvider.parse_from_xml(
38
+ metadata: metadata,
39
+ name: idp_name
40
+ )
41
+ end
42
+ end
43
+ end
@@ -5,19 +5,13 @@ require "onelogin/ruby-saml/settings"
5
5
 
6
6
  module Spid
7
7
  class Metadata # :nodoc:
8
- attr_reader :metadata_attributes,
9
- :service_provider_configuration,
10
- :attribute_service_name
8
+ attr_reader :metadata_attributes
11
9
 
12
10
  # rubocop:disable Metrics/MethodLength
13
11
  def initialize(
14
- service_provider_configuration:,
15
- attribute_service_name:,
16
12
  digest_method: Spid::SHA256,
17
13
  signature_method: Spid::RSA_SHA256
18
14
  )
19
- @service_provider_configuration = service_provider_configuration
20
- @attribute_service_name = attribute_service_name
21
15
  @metadata_attributes = {
22
16
  issuer: issuer,
23
17
  private_key: private_key_content,
@@ -45,23 +39,31 @@ module Spid
45
39
  end
46
40
 
47
41
  def issuer
48
- service_provider_configuration.host
42
+ service_provider.host
49
43
  end
50
44
 
51
45
  def private_key_content
52
- service_provider_configuration.private_key
46
+ service_provider.private_key
53
47
  end
54
48
 
55
49
  def certificate_content
56
- service_provider_configuration.certificate
50
+ service_provider.certificate
57
51
  end
58
52
 
59
53
  def assertion_consumer_service_url
60
- service_provider_configuration.sso_url
54
+ service_provider.acs_url
61
55
  end
62
56
 
63
57
  def single_logout_service_url
64
- service_provider_configuration.slo_url
58
+ service_provider.slo_url
59
+ end
60
+
61
+ def attribute_service_name
62
+ service_provider.attribute_service_name
63
+ end
64
+
65
+ def service_provider
66
+ @service_provider ||= Spid.configuration.service_provider
65
67
  end
66
68
 
67
69
  private
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Spid
6
+ class ServiceProvider # :nodoc:
7
+ attr_reader :host,
8
+ :acs_path,
9
+ :slo_path,
10
+ :metadata_path,
11
+ :private_key,
12
+ :certificate,
13
+ :digest_method,
14
+ :signature_method,
15
+ :attribute_service_name
16
+
17
+ # rubocop:disable Metrics/ParameterLists
18
+ def initialize(
19
+ host:,
20
+ acs_path:,
21
+ slo_path:,
22
+ metadata_path:,
23
+ private_key:,
24
+ certificate:,
25
+ digest_method:,
26
+ signature_method:,
27
+ attribute_service_name:
28
+ )
29
+ @host = host
30
+ @acs_path = acs_path
31
+ @slo_path = slo_path
32
+ @metadata_path = metadata_path
33
+ @private_key = private_key
34
+ @certificate = certificate
35
+ @digest_method = digest_method
36
+ @signature_method = signature_method
37
+ @attribute_service_name = attribute_service_name
38
+ validate_attributes
39
+ end
40
+ # rubocop:enable Metrics/ParameterLists
41
+
42
+ def acs_url
43
+ @acs_url ||= URI.join(host, acs_path).to_s
44
+ end
45
+
46
+ def slo_url
47
+ @slo_url ||= URI.join(host, slo_path).to_s
48
+ end
49
+
50
+ def metadata_url
51
+ @metadata_url ||= URI.join(host, metadata_path).to_s
52
+ end
53
+
54
+ # rubocop:disable Metrics/MethodLength
55
+ def sso_attributes
56
+ @sso_attributes ||=
57
+ begin
58
+ {
59
+ assertion_consumer_service_url: acs_url,
60
+ issuer: host,
61
+ private_key: private_key,
62
+ certificate: certificate,
63
+ security: {
64
+ authn_requests_signed: true,
65
+ embed_sign: true,
66
+ digest_method: digest_method,
67
+ signature_method: signature_method
68
+ }
69
+ }
70
+ end
71
+ end
72
+ # rubocop:enable Metrics/MethodLength
73
+
74
+ # rubocop:disable Metrics/MethodLength
75
+ def slo_attributes
76
+ @slo_attributes ||=
77
+ begin
78
+ {
79
+ issuer: host,
80
+ private_key: private_key,
81
+ certificate: certificate,
82
+ security: {
83
+ logout_requests_signed: true,
84
+ embed_sign: true,
85
+ digest_method: digest_method,
86
+ signature_method: signature_method
87
+ }
88
+ }
89
+ end
90
+ end
91
+ # rubocop:enable Metrics/MethodLength
92
+
93
+ private
94
+
95
+ def validate_attributes
96
+ if !DIGEST_METHODS.include?(digest_method)
97
+ raise UnknownDigestMethodError,
98
+ "Provided digest method is not valid:" \
99
+ " use one of #{DIGEST_METHODS.join(', ')}"
100
+ elsif !SIGNATURE_METHODS.include?(signature_method)
101
+ raise UnknownSignatureMethodError,
102
+ "Provided digest method is not valid:" \
103
+ " use one of #{SIGNATURE_METHODS.join(', ')}"
104
+ end
105
+ end
106
+ end
107
+ end