main
 1# frozen_string_literal: true
 2
 3module Saml
 4  module Kit
 5    # The default metadata registry is used to fetch the metadata associated
 6    # with an issuer or entity id.
 7    # The metadata associated with an issuer is used to verify trust for any
 8    # SAML documents that are received.
 9    #
10    # You can replace the default registry with your own at startup.
11    #
12    # Example:
13    #
14    #   class OnDemandRegistry
15    #    def initialize(original)
16    #      @original = original
17    #    end
18    #
19    #    def metadata_for(entity_id)
20    #      found = @original.metadata_for(entity_id)
21    #      return found if found
22    #
23    #      @original.register_url(entity_id, verify_ssl: Rails.env.production?)
24    #      @original.metadata_for(entity_id)
25    #    end
26    #   end
27    #
28    #   Saml::Kit.configure do |configuration|
29    #     configuration.entity_id = ENV['ENTITY_ID']
30    #     configuration.registry = OnDemandRegistry.new(configuration.registry)
31    #     configuration.logger = Rails.logger
32    #   end
33    #
34    # {include:file:spec/saml/kit/default_registry_spec.rb}
35    class DefaultRegistry
36      include Enumerable
37
38      def initialize(items = {})
39        @items = items
40      end
41
42      # Register a metadata document
43      #
44      # @param metadata [Saml::Kit::Metadata] the metadata to register.
45      def register(metadata)
46        ensure_valid_metadata(metadata)
47        Saml::Kit.logger.debug(metadata.to_xml(pretty: true))
48        @items[metadata.entity_id] = metadata
49      end
50
51      # Register metadata via a remote URL.
52      # This will attempt to connect to the remove URL to download the
53      # metadata and register it in the registry.
54      #
55      # @param url [String] the url to download the metadata from.
56      # @param verify_ssl [Boolean] enable/disable SSL peer verification.
57      def register_url(url, verify_ssl: true)
58        headers = { 'User-Agent' => "saml/kit #{Saml::Kit::VERSION}" }
59        verify_mode = verify_ssl ? nil : OpenSSL::SSL::VERIFY_NONE
60        client = Net::Hippie::Client.new(headers: headers, verify_mode: verify_mode)
61        register(Saml::Kit::Metadata.from(client.get(url).body))
62      end
63
64      # Returns the metadata document associated with an issuer or entityID.
65      #
66      # @param entity_id [String] unique entityID/Issuer associated with
67      # metadata.
68      def metadata_for(entity_id)
69        @items[entity_id]
70      end
71
72      # Yields each registered [Saml::Kit::Metadata] to the block.
73      def each
74        @items.each_value do |value|
75          yield value
76        end
77      end
78
79      protected
80
81      def ensure_valid_metadata(metadata)
82        error = ArgumentError.new('Cannot register invalid metadata')
83        raise error if
84          metadata.nil? ||
85          !metadata.respond_to?(:entity_id) ||
86          metadata.invalid?
87      end
88    end
89  end
90end