Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/SAML-Toolkits/v2.x' into merge-…
Browse files Browse the repository at this point in the history
…master-20240711
  • Loading branch information
johnnyshields committed Sep 30, 2024
2 parents 9ee5238 + 455d17d commit dc4c8d5
Show file tree
Hide file tree
Showing 37 changed files with 2,937 additions and 1,480 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ AllCops:
- 'tmp/**/*'
- 'vendor/**/*'

Style/ModuleFunction:
EnforcedStyle: extend_self

Style/NumericPredicate:
EnforcedStyle: comparison

Expand Down
68 changes: 28 additions & 40 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2024-07-09 08:57:21 UTC using RuboCop version 1.64.1.
# on 2024-07-11 13:04:30 UTC using RuboCop version 1.64.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -20,7 +20,7 @@ Layout/EmptyLineAfterGuardClause:
- 'lib/ruby_saml/slo_logoutrequest.rb'
- 'lib/ruby_saml/slo_logoutresponse.rb'

# Offense count: 6
# Offense count: 7
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only
Expand All @@ -31,6 +31,7 @@ Layout/EmptyLinesAroundClassBody:
- 'lib/ruby_saml/logoutrequest.rb'
- 'lib/ruby_saml/logoutresponse.rb'
- 'lib/ruby_saml/metadata.rb'
- 'lib/ruby_saml/saml_message.rb'
- 'lib/ruby_saml/slo_logoutresponse.rb'

# Offense count: 1
Expand All @@ -39,14 +40,16 @@ Layout/EmptyLinesAroundMethodBody:
Exclude:
- 'lib/ruby_saml/slo_logoutrequest.rb'

# Offense count: 11
# Offense count: 13
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
Layout/EmptyLinesAroundModuleBody:
Exclude:
- 'lib/ruby_saml/attribute_service.rb'
- 'lib/ruby_saml/attributes.rb'
- 'lib/ruby_saml/authrequest.rb'
- 'lib/ruby_saml/idp_metadata_parser.rb'
- 'lib/ruby_saml/logoutrequest.rb'
- 'lib/ruby_saml/logoutresponse.rb'
- 'lib/ruby_saml/metadata.rb'
Expand Down Expand Up @@ -124,7 +127,7 @@ Layout/SpaceAroundOperators:
- 'lib/ruby_saml/xml/document.rb'
- 'lib/ruby_saml/xml/signed_document.rb'

# Offense count: 5
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
Expand Down Expand Up @@ -177,7 +180,7 @@ Lint/UselessAssignment:
Exclude:
- 'lib/ruby_saml/slo_logoutrequest.rb'

# Offense count: 42
# Offense count: 41
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 100
Expand All @@ -188,20 +191,30 @@ Metrics/AbcSize:
Metrics/BlockLength:
Max: 27

# Offense count: 9
# Offense count: 8
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 652

# Offense count: 25
# Offense count: 26
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
Max: 21

# Offense count: 59
# Offense count: 58
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 63
Max: 80

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ModuleLength:
Max: 300

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ModuleLength:
Max: 244

# Offense count: 2
# Configuration parameters: Max, CountKeywordArgs.
Expand Down Expand Up @@ -276,25 +289,23 @@ Performance/RedundantEqualityComparisonBlock:
Exclude:
- 'lib/ruby_saml/settings.rb'

# Offense count: 5
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
Performance/StringInclude:
Exclude:
- 'lib/ruby_saml/authrequest.rb'
- 'lib/ruby_saml/logoutrequest.rb'
- 'lib/ruby_saml/slo_logoutresponse.rb'
- 'lib/ruby_saml/utils.rb'

# Offense count: 8
# Offense count: 4
# This cop supports safe autocorrection (--autocorrect).
Performance/StringReplacement:
Exclude:
- 'lib/ruby_saml/metadata.rb'
- 'lib/ruby_saml/saml_message.rb'
- 'lib/ruby_saml/utils.rb'
- 'lib/ruby_saml/xml/document.rb'

# Offense count: 52
# Offense count: 48
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: separated, grouped
Expand Down Expand Up @@ -406,22 +417,6 @@ Style/IfUnlessModifier:
- 'lib/ruby_saml/xml/document.rb'
- 'lib/ruby_saml/xml/signed_document.rb'

# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, Autocorrect.
# SupportedStyles: module_function, extend_self, forbidden
Style/ModuleFunction:
Exclude:
- 'lib/ruby_saml/logging.rb'

# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, Autocorrect.
# SupportedStyles: module_function, extend_self, forbidden
Style/ModuleFunction:
Exclude:
- 'lib/ruby_saml/logging.rb'

# Offense count: 16
# Configuration parameters: AllowedMethods.
# AllowedMethods: respond_to_missing?
Expand All @@ -437,18 +432,11 @@ Style/OptionalBooleanParameter:
- 'lib/ruby_saml/utils.rb'
- 'lib/ruby_saml/xml/signed_document.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantBegin:
Exclude:
- 'lib/ruby_saml/utils.rb'

# Offense count: 8
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantRegexpArgument:
Exclude:
- 'lib/ruby_saml/saml_message.rb'
- 'lib/ruby_saml/utils.rb'
- 'lib/ruby_saml/xml/document.rb'

# Offense count: 3
Expand Down Expand Up @@ -477,7 +465,7 @@ Style/StringConcatenation:
- 'lib/ruby_saml/saml_message.rb'
- 'lib/ruby_saml/slo_logoutrequest.rb'

# Offense count: 351
# Offense count: 339
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Expand Down Expand Up @@ -514,7 +502,7 @@ Style/SymbolArray:
Exclude:
- 'lib/ruby_saml/settings.rb'

# Offense count: 95
# Offense count: 104
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
* [#690](https://github.com/SAML-Toolkits/ruby-saml/pull/690) Remove deprecated `settings.security[:embed_sign]` parameter.
* [#697](https://github.com/SAML-Toolkits/ruby-saml/pull/697) Add deprecation for various parameters in `RubySaml::Settings`.
* [#709](https://github.com/SAML-Toolkits/ruby-saml/pull/709) Allow passing in `Net::HTTP` `:open_timeout`, `:read_timeout`, and `:max_retries` settings to `IdpMetadataParser#parse_remote`.
* [#715](https://github.com/SAML-Toolkits/ruby-saml/pull/715) Fix typo in error when SPNameQualifier value does not match the SP entityID.
* [#718](https://github.com/SAML-Toolkits/ruby-saml/pull/718/) Add support to retrieve from SAMLResponse the AuthnInstant and AuthnContextClassRef values
* [#711](https://github.com/SAML-Toolkits/ruby-saml/pull/711) Standardize how RubySaml reads and formats certificate and private_key PEM values, including the `RubySaml::Util#format_cert` and `#format_private_key` methods.

### 1.18.0 (???)
* [#718](https://github.com/SAML-Toolkits/ruby-saml/pull/718) Add support to retrieve from SAMLResponse the AuthnInstant and AuthnContextClassRef values
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ In the above there are a few assumptions, one being that `response.nameid` is an
This is all handled with how you specify the settings that are in play via the `saml_settings` method.
That could be implemented along the lines of this:
```
```ruby
response = RubySaml::Response.new(params[:SAMLResponse])
response.settings = saml_settings
```
Expand Down Expand Up @@ -762,6 +762,11 @@ Note the following:
inactive/expired certificates. This avoids validation errors when the IdP reads the SP
metadata.
#### Key Algorithm Support
Ruby SAML supports RSA, DSA, and ECDSA keys for both SP and IdP certificates.
JRuby cannot support ECDSA due to a [known issue](https://github.com/jruby/jruby-openssl/issues/257).
#### Audience Validation
A service provider should only consider a SAML response valid if the IdP includes an <AudienceRestriction>
Expand Down
60 changes: 50 additions & 10 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@

Before attempting to upgrade to `2.0.0`:
- Upgrade your project to minimum Ruby 3.0, JRuby 9.4, or TruffleRuby 22.
- Upgrade RubySaml to `1.17.x`. Note that RubySaml `1.17.x` is compatible with up to Ruby 3.3.
- Upgrade RubySaml to `1.17.x`.
- In RubySaml `1.17.x`, if you were using the SHA-1 default behavior, change your settings to use SHA-256 as per below:

```ruby
# Set this in RubySaml 1.17.x, can be removed when upgrading to 2.0.0
settings.idp_cert_fingerprint_algorithm = XMLSecurity::Document::SHA256
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
settings.security[:digest_method] = XMLSecurity::Document::SHA256
```

### Root "OneLogin" namespace changed to "RubySaml"

Expand Down Expand Up @@ -38,19 +46,20 @@ For security reasons, RubySaml version `2.0.0` uses SHA-256 as its default hashi
instead of the now-obsolete SHA-1. This affects:
- The default signature and digest algorithms used when generating SP metadata.
- The default signature algorithm used when generating SP messages such as AuthnRequests.
- The default fingerprint of IdP metadata (`:idp_cert_fingerprint` as generated by `RubySaml::IdpMetadataParser`)
- The `:idp_cert_fingerprint` of IdP metadata as generated by `RubySaml::IdpMetadataParser`.

To preserve the old insecure SHA-1 behavior *(not recommended)*, you may set `RubySaml::Settings` as follows:
If you see any signature or fingerprint mismatch errors after upgrading to RubySaml `2.0.0`,
this change is likely the reason. To preserve the old insecure SHA-1 behavior *(not recommended)*,
you may set `RubySaml::Settings` as follows:

```ruby
# Preserve RubySaml 1.x insecure SHA-1 behavior
settings = RubySaml::Settings.new
settings.idp_cert_fingerprint_algorithm = RubySaml::XML::Document::SHA1
settings.security[:digest_method] = RubySaml::XML::Document::SHA1
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA1
settings.idp_cert_fingerprint_algorithm = RubySaml::XML::Crypto::SHA1
settings.security[:digest_method] = RubySaml::XML::Crypto::SHA1
settings.security[:signature_method] = RubySaml::XML::Crypto::RSA_SHA1
```

### Removal of embed_sign Setting
### Removal of embed_sign setting

The deprecated `settings.security[:embed_sign]` parameter has been removed. If you were using it, please instead switch
to using both the `settings.idp_sso_service_binding` and `settings.idp_slo_service_binding` parameters as show below.
Expand All @@ -68,7 +77,7 @@ settings.idp_slo_service_binding = :redirect

For clarity, the default value of both parameters is `:redirect` if they are not set.

### Deprecation of Compression Settings
### Deprecation of compression settings

The `settings.compress_request` and `settings.compress_response` parameters have been deprecated
and are no longer functional. They will be removed in RubySaml 2.1.0. Please remove `compress_request`
Expand All @@ -80,7 +89,7 @@ The SAML SP request/response message compression behavior is now controlled auto
"compression" is used to make redirect URLs which contain SAML messages be shorter. For POST messages,
compression may be achieved by enabling `Content-Encoding: gzip` on your webserver.

## Settings deprecations
### Other settings deprecations

The following parameters in `RubySaml::Settings` are deprecated and will be removed in RubySaml 2.1.0:

Expand All @@ -92,6 +101,37 @@ The following parameters in `RubySaml::Settings` are deprecated and will be remo
- `#certificate_new` is deprecated and replaced by `#sp_cert_multi`. Refer to documentation as `#sp_cert_multi`
has a different value type than `#certificate_new`.

### Minor changes to Util#format_cert and #format_private_key


Version `2.0.0` standardizes how RubySaml reads and formats certificate and private key
PEM strings. In general, version `2.0.0` is more permissive than `1.x`, and the changes
are not anticipated to affect most users. Please note the change affects parameters
such `#idp_cert` and `#certificate`, as well as the `RubySaml::Util#format_cert`
and `#format_private_key` methods. Specifically:


| # | Input value | RubySaml 2.0.0 | RubySaml 1.x |
|---|------------------------------------------------------|---------------------------------------------------------|---------------------------|
| 1 | Input contains a bad (e.g. non-base64) PEM | Skip PEM formatting | Return a bad PEM |
| 2 | Input contains `\r` character(s) | Strip out all `\r` character(s) and format as PEM | Skip PEM formatting |
| 3 | PEM header other than `CERTIFICATE` or `PRIVATE KEY` | Format if header ends in `CERTIFICATE` or `PRIVATE KEY` | Skip PEM formatting |
| 4 | `#format_cert` given `PRIVATE KEY` (and vice-versa) | Ignore PEMs of incorrect type | Return a bad PEM |
| 5 | Text outside header/footer values | Strip out text outside header/footer values | Skip PEM formatting |
| 6 | Input non-ASCII characters | Ignore non-ASCII chars if they are outside the PEM | Skip PEM formatting |
| 7 | `#format_cert` input contains mix of good/bad certs | Return only good cert PEMs (joined with `\n`) | Return good and bad certs |

**Notes**
- Case 3: For example, `-----BEGIN TRUSTED X509 CERTIFICATE-----` is now
considered a valid header as an input, but it will be formatted to
`-----BEGIN CERTIFICATE-----` in the output. As a special case, in both `2.0.0`
and 1.x, if `RSA PRIVATE KEY` is present in the input string, the `RSA` prefix will
be preserved in the output.
- Case 5: When formatting multiple certificates in one string (i.e. a certificate chain),
text present between the footer and header of two different certificates will also be
stripped out.
- Case 7: If no valid certificates are found, the entire original string will be returned.

## Updating from 1.12.x to 1.13.0

Version `1.13.0` adds `settings.idp_sso_service_binding` and `settings.idp_slo_service_binding`, and
Expand Down
1 change: 1 addition & 0 deletions lib/ruby_saml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
require 'ruby_saml/validation_error'
require 'ruby_saml/metadata'
require 'ruby_saml/idp_metadata_parser'
require 'ruby_saml/pem_formatter'
require 'ruby_saml/utils'
require 'ruby_saml/version'

Expand Down
7 changes: 3 additions & 4 deletions lib/ruby_saml/authrequest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

# Only supports SAML 2.0
module RubySaml
include REXML

# SAML2 Authentication. AuthNRequest (SSO SP initiated, Builder)
#
Expand Down Expand Up @@ -78,14 +77,14 @@ def create_params(settings, params={})
sp_signing_key = settings.get_sp_signing_key

if binding_redirect && settings.security[:authn_requests_signed] && sp_signing_key
params['SigAlg'] = settings.security[:signature_method]
params['SigAlg'] = settings.get_sp_signature_method
url_string = RubySaml::Utils.build_query(
type: 'SAMLRequest',
data: base64_request,
relay_state: relay_state,
sig_alg: params['SigAlg']
)
sign_algorithm = RubySaml::XML::BaseDocument.new.algorithm(settings.security[:signature_method])
sign_algorithm = RubySaml::XML::Crypto.hash_algorithm(settings.get_sp_signature_method)
signature = sp_signing_key.sign(sign_algorithm.new, url_string)
params['Signature'] = encode(signature)
end
Expand Down Expand Up @@ -186,7 +185,7 @@ def create_xml_document(settings)
def sign_document(document, settings)
cert, private_key = settings.get_sp_signing_pair
if settings.idp_sso_service_binding == Utils::BINDINGS[:post] && settings.security[:authn_requests_signed] && private_key && cert
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
document.sign_document(private_key, cert, settings.get_sp_signature_method, settings.get_sp_digest_method)
end

document
Expand Down
3 changes: 1 addition & 2 deletions lib/ruby_saml/idp_metadata_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

# Only supports SAML 2.0
module RubySaml
include REXML

# Auxiliary class to retrieve and parse the Identity Provider Metadata
#
Expand Down Expand Up @@ -399,7 +398,7 @@ def fingerprint(certificate, fingerprint_algorithm = RubySaml::XML::Document::SH

cert = OpenSSL::X509::Certificate.new(Base64.decode64(certificate))

fingerprint_alg = RubySaml::XML::BaseDocument.new.algorithm(fingerprint_algorithm).new
fingerprint_alg = RubySaml::XML::Crypto.hash_algorithm(fingerprint_algorithm).new
fingerprint_alg.hexdigest(cert.to_der).upcase.scan(/../).join(":")
end
end
Expand Down
Loading

0 comments on commit dc4c8d5

Please sign in to comment.