Closed joeniquette closed 2 years ago
The signature would look like: 2:34 <?xml version="1.0" encoding="UTF-8"?>
From reading the OneLogin documentation in order to sign SAML messages we must first designate a certificate
& a private_key
in the settings object, before enabling the use of SAML signing for specific messages, which we do by setting authn_requests_signed
to true.
I can confirm that authn_requests_signed
is properly set in our devops repository, but as far as I can tell we are not including the certificate or key. The handling for those two settings exists in lib/saml/ssoe_settings_service.rb
, but so far I can't find the existence of those values in the devops repo.
Update: I found in config/initializers/saml.rb
that those settings are generated based off of the saml_ssoe.key_path
& saml_ssoe.cert_path
settings, both of which show up in devops configs
The issue appears to be a mismatch between the default settings.idp_sso_service_binding
, which is set to "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
and the RubySAML gem's requirement for SAML request signing, "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
. This mismatch can be found in the RubySAML gem @ vendor/bundle/ruby/2.7.0/gems/ruby-saml-1.14.0/lib/onelogin/ruby-saml/authrequest.rb
After manually setting the request service binding to POST
the authentication request was signed, but was rejected by ISAM as the signature was not able to validated. My assumption is that the IAM team will have to change their ISAM configuration to be set up to decrypt the SAML payload with vet-api's public key.
IAM stated this should be safe to test in Dev and staging if we want to give the change a go.
Related devops PR: https://github.com/department-of-veterans-affairs/devops/pull/11894
I'm also researching the difference betwen the "Artifact" service binding that we have now and the "POST" binding that this is changing our requests to in order to enable SAML signing. Is this something that we need to take into account?
Yes, we likely cannot just switch from artifact to post. In reading the document you posted there are some mentions of signing requests, and also of combining bindings to allow for both artifact and post. From the doc, it appears as though signing is used/required because they dont encrypt the contents. Whereas Artifact doesnt require signing because they expect encryption. Nothing in there states we cant do signing and encrypted responses with POST.
For not, review the documentation, if you dont find any concerns with using POST then lets give it a try.
Further inquiry has revealed that the SAML message is unable to be signed due to a bug in the OneLogin RubySAML gem that vets-api leverages for its SAML communications, the compute_digest
method that encrypts the Digest value:
def compute_digest(document, digest_algorithm)
digest = digest_algorithm.digest(document)
Base64.encode64(digest).strip!
end
The document
param is the unencrypted SAML to be transformed, the digest_algorithm
is controlled via a config, in this case it's OpenSSL::Digest::SHA256
. After the digest is created in the first line, the RubySAML gem attempts to strip the result of leading & trailing whitespaces, but by using strip!
instead of strip
the method returns nil
because no whitespaces were found to be removed. I have attempted altering the document
contents by introducing leading & trailing whitespaces but the digest
process always removes them so that they are not present when strip!
is being called.
The long-term solution for this is for an update to the RubySAML, however the project is no longer under active maintenance as of approximately a month ago, which makes this seem unlikely. In lieu of that, our best course of action might be to fork our own version of the gem to make the bugfix ourselves (while also submitting a ticket to the project requesting it be merged into the original version).
This is rough draft for an issue ticket on the RubySAML gem repository, any feedback @bosawt @joeniquette?
We are updating our SAML authentication requests to our service provider by including SAML signing, however the resulting DigestValue
is always blank. I traced the problem back to the compute_digest
method, which is using strip!
to remove preceding and trailing whitespaces.
def compute_digest(document, digest_algorithm)
digest = digest_algorithm.digest(document)
Base64.encode64(digest).strip!
end
We are using OpenSSL::Digest::SHA256
as our digest_algorithm
, but the Base64 encoding of the digest created on the previous line doesn't contain any preceding or trailing whitespaces, causing the strip!
method to return nil
instead of the supplied value.
What is the purpose of using strip!
over the base strip
method? Is it possible for it to be replaced with strip
in this instance?
This is rough draft for an issue ticket on the RubySAML gem repository, any feedback @bosawt @joeniquette?
We are updating our SAML authentication requests to our service provider by including SAML signing, however the resulting
DigestValue
is always blank. I traced the problem back to thecompute_digest
method, which is usingstrip!
to remove preceding and trailing whitespaces.def compute_digest(document, digest_algorithm) digest = digest_algorithm.digest(document) Base64.encode64(digest).strip! end
We are using
OpenSSL::Digest::SHA256
as ourdigest_algorithm
, but the Base64 encoding of the digest created on the previous line doesn't contain any preceding or trailing whitespaces, causing thestrip!
method to returnnil
instead of the supplied value.What is the purpose of using
strip!
over the basestrip
method? Is it possible for it to be replaced withstrip
in this instance?
Yeah, seems good to me
After further effort I was unable to introduce a change to our SAML metadata that would induce a whitespace in the string that is passed into the strip!
method, I've raised an issue ticket on the ruby-saml repository and am marking this as Blocked for now.
SAML signing has been enabled in dev and staging, with a planned prod release @ 9 PM ET on 10/20
The decision was made to not enable SAML signing for localhost as it would have necessitated either including the signing private key into version control or requiring all local vets-api builds to download/generate a key to make SAML authentication work. ISAM will continue to accept signed or unsigned SAML requests from localhost builds.
VSP Identity & the IAM team have confirmed that vets-api production is now signing SAML requests - the ISAM production switch to only accepting signed SAML requests is still due to occur at 9 EST tonight.
SAML request signing is confirmed present & working VA.gov production.
From IAM: