Class: OpenStack::AuthV30

Inherits:
Object show all
Defined in:
lib/openstack/connection.rb

Overview

Implement the Identity Version 3.x API developer.openstack.org/api-ref-identity-v3.html This is still experimental, so don’t use in production.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection) ⇒ AuthV30

TODO: Parse the version for an endpoint



511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/openstack/connection.rb', line 511

def initialize(connection)
  tries = connection.retries
  time = 3

  begin
    server = Net::HTTP::Proxy(connection.proxy_host, connection.proxy_port).new(connection.auth_host, connection.auth_port)
    if connection.auth_scheme == "https"
      server.use_ssl = true
      server.verify_mode = OpenSSL::SSL::VERIFY_NONE

      # use the ca_cert if were given one, and make sure we verify!
      unless connection.ca_cert.nil?
        server.ca_file = connection.ca_cert
        server.verify_mode = OpenSSL::SSL::VERIFY_PEER
      end

      # explicitly set the SSL version to use
      server.ssl_version = connection.ssl_version unless connection.ssl_version.nil?
    end
    server.start
  rescue
    puts "Can't connect to the server: #{tries} tries to reconnect" if connection.is_debug
    sleep time += 1
    retry unless (tries -= 1) <= 0
    raise OpenStack::Exception::Connection, "Unable to connect to #{server}"
  end

  # Build Auth JSON
  auth = { "auth" => { "identity" => {} } }

  case connection.auth_method.to_sym
  when :password
    auth["auth"]["identity"]["methods"] = ["password"]
    auth["auth"]["identity"]["password"] = { "user" => { "name" => connection.authuser, "password" => connection.authkey } }
    auth["auth"]["identity"]["password"]["user"]["domain"] = connection.user_domain ? { "name" => connection.user_domain } : { "id" => connection.user_domain_id }
  when :password_user_id
    auth["auth"]["identity"]["methods"] = ["password"]
    auth["auth"]["identity"]["password"] = { "user" => { "id" => connection.authuser, "password" => connection.authkey } }
  when :token
    auth["auth"]["identity"]["methods"] = ["token"]
    auth["auth"]["identity"]["token"] = { "id" => connection.authkey }
  else
    raise Exception::InvalidArgument, "Unrecognized auth method #{connection.auth_method}."
  end

  # handle project authentication scope
  if (connection.project_id || connection.project_name) && (connection.project_domain_name || connection.project_domain_id)
    auth["auth"]["scope"] = { "project" => { "domain" => {} } }
    auth["auth"]["scope"]["project"]["name"] =  connection.project_name if connection.project_name
    auth["auth"]["scope"]["project"]["id"] =  connection.project_id if connection.project_id
    auth["auth"]["scope"]["project"]["domain"]["name"] = connection.project_domain_name if connection.project_domain_name
    auth["auth"]["scope"]["project"]["domain"]["id"] = connection.project_domain_id if connection.project_domain_id
  end

  # handle domain authentication scope
  if connection.domain_name || connection.domain_id
    auth["auth"]["scope"] = { "domain" => {} }
    auth["auth"]["scope"]["domain"]["name"] = connection.domain_name if connection.domain_name
    auth["auth"]["scope"]["domain"]["id"] = connection.domain_id if connection.domain_id
  end

  response = server.post(connection.auth_path.chomp('/') + '/auth/tokens',
                         JSON.generate(auth),
                         {'Content-Type' => 'application/json'})

  # debugging
  if connection.is_debug
    puts "REQUEST: POST => #{connection.auth_path.chomp('/') + '/auth/tokens'}"
    puts "RESPONSE: #{response.body}"
    puts '----------------------------------------'
  end

  if response.code =~ /^20./
    connection.authtoken = response['X-Subject-Token']

    resp_data=JSON.parse(response.body)

    catalog = resp_data["token"]["catalog"]
    unless catalog
      raise OpenStack::Exception::Authentication, "No service catalog returned. Maybe your auth request is unscoped. Please check if your selected user has a default project."
    end

    # Check if the used service is available
    implemented_services = resp_data["token"]["catalog"].map {|service| service['type']}
    raise OpenStack::Exception::NotImplemented.new("The requested service: \"#{connection.service_type}\" is not present " +
                                                   "in the returned service catalogue.", 501, "#{resp_data["access"]["serviceCatalog"]}") unless implemented_services.include?(connection.service_type)
    catalog.each do |service|
      service["endpoints"].each do |endpoint|
        connection.regions_list[endpoint["region"]] ||= []
        connection.regions_list[endpoint["region"]] << {:service=>service["type"], :versionId => endpoint["versionId"]}
      end

      # set use preset service name if set, otherwise ignore.
      if connection.service_name
        check_service_name = connection.service_name
      else
        check_service_name = service['name']
      end

      if service['type'] == connection.service_type and service['name'] == check_service_name
        endpoints = service["endpoints"]

        # filter endpoints by interfacetype
        interface_type = connection.endpoint_type.gsub('URL','')
        endpoints = endpoints.select {|ep| ep['interface'] == interface_type}

        # Select endpoint based on region
        if connection.region
          endpoints.each do |ep|
            if ep["region"] and ep["region"].upcase == connection.region.upcase
              @uri = URI.parse(ep['url'])
            end
          end
        else
          @uri = URI.parse(endpoints[0]['url'])
        end

        if @uri == ""
          raise OpenStack::Exception::Authentication, "No API endpoint for region #{connection.region}"
        else
          connection.service_host = @uri.host
          connection.service_path = @uri.path
          connection.service_port = @uri.port
          connection.service_scheme = @uri.scheme
          connection.authok = true
        end
      end
    end
  else
    connection.authtoken = false
    raise OpenStack::Exception::Authentication, "Authentication failed with response code #{response.code}"
  end
  server.finish if server.started?
end

Instance Attribute Details

#uriObject (readonly)

Returns the value of attribute uri.



508
509
510
# File 'lib/openstack/connection.rb', line 508

def uri
  @uri
end

#versionObject (readonly)

Returns the value of attribute version.



508
509
510
# File 'lib/openstack/connection.rb', line 508

def version
  @version
end