Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update our main branch with beta changes #7

Open
wants to merge 12 commits into
base: kolide-main
Choose a base branch
from
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ KEY DATA
-----END RSA PRIVATE KEY-----
CERT

# x509_certificate, secret_key, and password may also be set from within a proc, for example:
# config.x509_certificate = -> { File.read("cert.pem") }
# config.secret_key = -> { SecretKeyFinder.key_for(id: 1) }
# config.password = -> { "password" }

# config.password = "secret_key_password"
# config.algorithm = :sha256 # Default: sha1 only for development.
# config.organization_name = "Your Organization"
Expand Down Expand Up @@ -121,8 +126,8 @@ CERT
# phone: { getter: :phone },
# email: {
# getter: :email,
# name_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS,
# name_id_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS
# name_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS,
# name_id_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS
# }
# }
# end
Expand Down
69 changes: 1 addition & 68 deletions lib/saml_idp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module SamlIdp
require 'active_support/all'
require 'saml_idp/saml_response'
require 'saml_idp/xml'
require 'saml_idp/xml_security'
require 'saml_idp/configurator'
require 'saml_idp/controller'
Expand All @@ -23,71 +24,3 @@ def self.metadata
@metadata ||= MetadataBuilder.new(config)
end
end

# TODO Needs extraction out
module Saml
module XML
module Namespaces
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
SIGNATURE = "http://www.w3.org/2000/09/xmldsig#"
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"

module Statuses
SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
end

module Consents
UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
end

module AuthnContext
module ClassRef
PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
end
end

module Methods
BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
end

module Formats
module Attr
URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
end

module NameId
EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
end
end
end

class Document < Nokogiri::XML::Document
def signed?
!!xpath("//ds:Signature", ds: signature_namespace).first
end

def valid_signature?(fingerprint)
signed? &&
signed_document.validate(fingerprint, :soft)
end

def signed_document
SamlIdp::XMLSecurity::SignedDocument.new(to_xml)
end

def signature_namespace
Namespaces::SIGNATURE
end

def to_xml
super(
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
).strip
end
end
end
end
6 changes: 3 additions & 3 deletions lib/saml_idp/assertion_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ def initialize(

def fresh
builder = Builder::XmlMarkup.new
builder.Assertion xmlns: Saml::XML::Namespaces::ASSERTION,
builder.Assertion xmlns: SamlIdp::XML::Namespaces::ASSERTION,
ID: reference_string,
IssueInstant: now_iso,
Version: "2.0" do |assertion|
assertion.Issuer issuer_uri
sign assertion
assertion.Subject do |subject|
subject.NameID name_id, Format: name_id_format[:name]
subject.SubjectConfirmation Method: Saml::XML::Namespaces::Methods::BEARER do |confirmation|
subject.SubjectConfirmation Method: SamlIdp::XML::Namespaces::Methods::BEARER do |confirmation|
confirmation_hash = {}
confirmation_hash[:InResponseTo] = saml_request_id unless saml_request_id.nil?
confirmation_hash[:NotOnOrAfter] = not_on_or_after_subject
Expand Down Expand Up @@ -101,7 +101,7 @@ def fresh
asserted_attributes.each do |friendly_name, attrs|
attrs = (attrs || {}).with_indifferent_access
attr_statement.Attribute Name: attrs[:name] || friendly_name,
NameFormat: attrs[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI,
NameFormat: attrs[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI,
FriendlyName: friendly_name.to_s do |attr|
values = get_values_for friendly_name, attrs[:getter]
values.each do |val|
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/attribute_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def friendly_name
end

def name_format
source[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI
source[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI
end

def values
Expand Down
4 changes: 2 additions & 2 deletions lib/saml_idp/configurator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class Configurator
attr_accessor :logger

def initialize
self.x509_certificate = Default::X509_CERTIFICATE
self.secret_key = Default::SECRET_KEY
self.x509_certificate = -> { Default::X509_CERTIFICATE }
self.secret_key = -> { Default::SECRET_KEY }
self.algorithm = :sha1
self.reference_id_generator = ->() { SecureRandom.uuid }
self.service_provider = OpenStruct.new
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def decode_request(raw_saml_request)
end

def authn_context_classref
Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD
end

def encode_authn_response(principal, opts = {})
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/encryptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def encrypt(raw_xml)
encrypted_key = Xmlenc::EncryptedKey.new(encrypted_key_node)
encrypted_key.encrypt(openssl_cert.public_key, encryption_key)
xml = Builder::XmlMarkup.new
xml.EncryptedAssertion xmlns: Saml::XML::Namespaces::ASSERTION do |enc_assert|
xml.EncryptedAssertion xmlns: SamlIdp::XML::Namespaces::ASSERTION do |enc_assert|
enc_assert << encrypted_data.node.to_s
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/incoming_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize(raw = "")
end

def document
@document ||= Saml::XML::Document.parse raw
@document ||= SamlIdp::XML::Document.parse raw
end

def entity_id
Expand Down Expand Up @@ -149,16 +149,16 @@ def idp_descriptor_document
end

def contact_person_document
@contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || Saml::XML::Document.new)
@contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || SamlIdp::XML::Document.new)
end

def metadata_namespace
Saml::XML::Namespaces::METADATA
SamlIdp::XML::Namespaces::METADATA
end
private :metadata_namespace

def signature_namespace
Saml::XML::Namespaces::SIGNATURE
SamlIdp::XML::Namespaces::SIGNATURE
end
private :signature_namespace
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/logout_request_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ def build
Version: "2.0",
IssueInstant: now_iso,
Destination: saml_slo_url,
"xmlns" => Saml::XML::Namespaces::PROTOCOL do |request|
request.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
"xmlns" => SamlIdp::XML::Namespaces::PROTOCOL do |request|
request.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign request
request.NameID name_id, xmlns: Saml::XML::Namespaces::ASSERTION,
Format: Saml::XML::Namespaces::Formats::NameId::PERSISTENT
request.NameID name_id, xmlns: SamlIdp::XML::Namespaces::ASSERTION,
Format: SamlIdp::XML::Namespaces::Formats::NameId::PERSISTENT
request.SessionIndex response_id_string
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/logout_response_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def build
IssueInstant: now_iso,
Destination: saml_slo_url,
InResponseTo: saml_request_id,
xmlns: Saml::XML::Namespaces::PROTOCOL do |response|
response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |response|
response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign response
response.Status xmlns: Saml::XML::Namespaces::PROTOCOL do |status|
status.StatusCode Value: Saml::XML::Namespaces::Statuses::SUCCESS
response.Status xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |status|
status.StatusCode Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS
end
end
end
Expand Down
13 changes: 7 additions & 6 deletions lib/saml_idp/metadata_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def fresh
builder = Builder::XmlMarkup.new
generated_reference_id do
builder.EntityDescriptor ID: reference_string,
xmlns: Saml::XML::Namespaces::METADATA,
"xmlns:saml" => Saml::XML::Namespaces::ASSERTION,
"xmlns:ds" => Saml::XML::Namespaces::SIGNATURE,
xmlns: SamlIdp::XML::Namespaces::METADATA,
"xmlns:saml" => SamlIdp::XML::Namespaces::ASSERTION,
"xmlns:ds" => SamlIdp::XML::Namespaces::SIGNATURE,
entityID: entity_id do |entity|
sign entity

Expand Down Expand Up @@ -56,7 +56,7 @@ def fresh

def build_key_descriptor(el)
el.KeyDescriptor use: "signing" do |key_descriptor|
key_descriptor.KeyInfo xmlns: Saml::XML::Namespaces::SIGNATURE do |key_info|
key_descriptor.KeyInfo xmlns: SamlIdp::XML::Namespaces::SIGNATURE do |key_info|
key_info.X509Data do |x509|
x509.X509Certificate x509_certificate
end
Expand Down Expand Up @@ -128,7 +128,7 @@ def entity_id
private :entity_id

def protocol_enumeration
Saml::XML::Namespaces::PROTOCOL
SamlIdp::XML::Namespaces::PROTOCOL
end
private :protocol_enumeration

Expand All @@ -152,7 +152,8 @@ def raw_algorithm
private :raw_algorithm

def x509_certificate
SamlIdp.config.x509_certificate
certificate = SamlIdp.config.x509_certificate.is_a?(Proc) ? SamlIdp.config.x509_certificate.call : SamlIdp.config.x509_certificate
certificate
.to_s
.gsub(/-----BEGIN CERTIFICATE-----/,"")
.gsub(/-----END CERTIFICATE-----/,"")
Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def response_host
private :response_host

def document
@_document ||= Saml::XML::Document.parse(raw_xml)
@_document ||= SamlIdp::XML::Document.parse(raw_xml)
end
private :document

Expand All @@ -179,17 +179,17 @@ def logout_request
private :logout_request

def samlp
Saml::XML::Namespaces::PROTOCOL
SamlIdp::XML::Namespaces::PROTOCOL
end
private :samlp

def assertion
Saml::XML::Namespaces::ASSERTION
SamlIdp::XML::Namespaces::ASSERTION
end
private :assertion

def signature_namespace
Saml::XML::Namespaces::SIGNATURE
SamlIdp::XML::Namespaces::SIGNATURE
end
private :signature_namespace

Expand Down
8 changes: 4 additions & 4 deletions lib/saml_idp/response_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ def build
resp_options[:Version] = "2.0"
resp_options[:IssueInstant] = now_iso
resp_options[:Destination] = saml_acs_url
resp_options[:Consent] = Saml::XML::Namespaces::Consents::UNSPECIFIED
resp_options[:Consent] = SamlIdp::XML::Namespaces::Consents::UNSPECIFIED
resp_options[:InResponseTo] = saml_request_id unless saml_request_id.nil?
resp_options["xmlns:samlp"] = Saml::XML::Namespaces::PROTOCOL
resp_options["xmlns:samlp"] = SamlIdp::XML::Namespaces::PROTOCOL

builder = Builder::XmlMarkup.new
builder.tag! "samlp:Response", resp_options do |response|
response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION
sign response
response.tag! "samlp:Status" do |status|
status.tag! "samlp:StatusCode", Value: Saml::XML::Namespaces::Statuses::SUCCESS
status.tag! "samlp:StatusCode", Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS
end
response << assertion_and_signature
end
Expand Down
2 changes: 1 addition & 1 deletion lib/saml_idp/signed_info_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def secret_key
private :secret_key

def password
SamlIdp.config.password
SamlIdp.config.password.is_a?(Proc) ? SamlIdp.config.password.call : SamlIdp.config.password
end
private :password

Expand Down
68 changes: 68 additions & 0 deletions lib/saml_idp/xml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'nokogiri'

module SamlIdp
module XML
module Namespaces
METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
SIGNATURE = "http://www.w3.org/2000/09/xmldsig#"
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"

module Statuses
SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
end

module Consents
UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
end

module AuthnContext
module ClassRef
PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
end
end

module Methods
BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
end

module Formats
module Attr
URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
end

module NameId
EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
end
end
end

class Document < Nokogiri::XML::Document
def signed?
!!xpath("//ds:Signature", ds: signature_namespace).first
end

def valid_signature?(fingerprint)
signed? &&
signed_document.validate(fingerprint, :soft)
end

def signed_document
SamlIdp::XMLSecurity::SignedDocument.new(to_xml)
end

def signature_namespace
Namespaces::SIGNATURE
end

def to_xml
super(
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
).strip
end
end
end
end
Loading