class AzureEnum::Federation

Class initializes with a domain name, and provides methods to interact with MS Autodiscover

Public Class Methods

new(domain) click to toggle source
# File lib/azure_enum.rb, line 10
def initialize(domain)
  @domain = domain
  @xml_text = nil
  @redirect = nil
end

Public Instance Methods

autodisc() click to toggle source
# File lib/azure_enum.rb, line 28
def autodisc
  # These are the default autodiscover domains.
  [
    "https://autodiscover.#{@domain}/autodiscover/autodiscover.svc",
    "https://#{@domain}/autodiscover/autodiscover.svc"
  ]
end
check_redirect() click to toggle source

This will identify if the http:// redirect exists for the domain, usually per Office 365

# File lib/azure_enum.rb, line 17
def check_redirect
  url = "http://autodiscover.#{@domain}/autodiscover/autodiscover.svc"
  begin
    res = HTTPClient.head(url)
  rescue
    return nil
  end
  return nil unless res.status_code == 302
  @redirect = res.header["Location"][0]
end
enumerate_autodisc(httpsdomains = autodisc) click to toggle source
# File lib/azure_enum.rb, line 36
def enumerate_autodisc(httpsdomains = autodisc)
  httpsdomains.unshift @redirect if @redirect
  @redirect = nil
  httpsdomains.each do |url|
    xml = get_xml(@domain, url)
    begin
      http = HTTPClient.new
      content = { "Content-Type" => "text/xml; charset=utf-8" }
      res = http.post(url, xml, content)
      # In the event of a second redirect we are on the right path
      # Recurse this function for the correct result
      if res.status_code == 302
        return enumerate_autodisc [res.header['Location'][0]]
      end
      @xml_text = res.content
      return true
      # It is bad style to rescue "all" errors. However, it turns out there is a practically
      # never ending list of ways this can fail. And "any" failure is reason to rule out the address
    rescue
      next
    end
  end
  return false
end
getdomains() click to toggle source
# File lib/azure_enum.rb, line 61
def getdomains
  raise "enumumerate_autodisc not called yet" unless @xml_text
  tree = Nokogiri.parse(@xml_text)
  tree.xpath(
    "//ad:GetFederationInformationResponseMessage/ad:Response/ad:Domains/ad:Domain",
    ad: "http://schemas.microsoft.com/exchange/2010/Autodiscover"
  ).map(&:text)
end

Private Instance Methods

get_xml(domain, url) click to toggle source
# File lib/azure_enum.rb, line 84
def get_xml(domain, url)
  path = File.dirname __dir__
  template = File.read(File.join(path, "discovery.xml.erb"))
  renderer = ERB.new(template)
  discovery = Discovery.new(domain, url)
  renderer.result(discovery.get_binding)
end