rbvmomi 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/rbvmomi.rb +9 -7
 - data/lib/rbvmomi/sso.rb +313 -0
 - data/lib/rbvmomi/trivial_soap.rb +6 -0
 - data/lib/rbvmomi/version.rb +1 -1
 - data/lib/rbvmomi/vim.rb +5 -2
 - metadata +3 -3
 - data/lib/rbvmomi/rake_task.rb~ +0 -7
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: e2c9c6bec8fc150387730e85d921c5e605508e86d13c4fbf439e53a32bc48b1b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 86eb6eafe9ac93c18318ef2f7cc03090e0322e86f80bf21845222e5706f32673
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 646abbb727bca29b48022672e32c5d3b0dc0404cff1f6f921bebf4a28559623d6165516d8a9e704d83e59d8ffb74e60c19b2e20e8fd007112558a49982a395e6
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: ca58ea6772f8fb67ef5f62bf04482879873ff2389694e53f435e559bbe34d8bd58ea1d02c52cbf3fd880fbd5c25f730c7766b8ab01d8b1e801f8f1276b38e987
         
     | 
    
        data/lib/rbvmomi.rb
    CHANGED
    
    | 
         @@ -1,14 +1,16 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # Copyright (c) 2010- 
     | 
| 
      
 1 
     | 
    
         
            +
            # Copyright (c) 2010-2019 VMware, Inc.  All Rights Reserved.
         
     | 
| 
       2 
2 
     | 
    
         
             
            # SPDX-License-Identifier: MIT
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            # RbVmomi is a Ruby interface to the vSphere management interface
         
     | 
| 
       4 
5 
     | 
    
         
             
            module RbVmomi
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            # @ 
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
               
     | 
| 
      
 6 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 7 
     | 
    
         
            +
              # @deprecated Use +RbVmomi::VIM.connect+.
         
     | 
| 
      
 8 
     | 
    
         
            +
              def self.connect(opts)
         
     | 
| 
      
 9 
     | 
    
         
            +
                VIM.connect opts
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
       10 
11 
     | 
    
         
             
            end
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            end
         
     | 
| 
       13 
13 
     | 
    
         
             
            require 'rbvmomi/connection'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'rbvmomi/sso'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'rbvmomi/version'
         
     | 
| 
       14 
16 
     | 
    
         
             
            require 'rbvmomi/vim'
         
     | 
    
        data/lib/rbvmomi/sso.rb
    ADDED
    
    | 
         @@ -0,0 +1,313 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'net/https'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'nokogiri'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'securerandom'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module RbVmomi
         
     | 
| 
      
 9 
     | 
    
         
            +
              # Provides access to vCenter Single Sign-On
         
     | 
| 
      
 10 
     | 
    
         
            +
              class SSO
         
     | 
| 
      
 11 
     | 
    
         
            +
                BST_PROFILE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'.freeze
         
     | 
| 
      
 12 
     | 
    
         
            +
                C14N_CLASS = Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
         
     | 
| 
      
 13 
     | 
    
         
            +
                C14N_METHOD = 'http://www.w3.org/2001/10/xml-exc-c14n#'.freeze
         
     | 
| 
      
 14 
     | 
    
         
            +
                DIGEST_METHOD = 'http://www.w3.org/2001/04/xmlenc#sha512'.freeze
         
     | 
| 
      
 15 
     | 
    
         
            +
                ENCODING_METHOD = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'.freeze
         
     | 
| 
      
 16 
     | 
    
         
            +
                SIGNATURE_METHOD = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'.freeze
         
     | 
| 
      
 17 
     | 
    
         
            +
                STS_PATH = '/sts/STSService'.freeze
         
     | 
| 
      
 18 
     | 
    
         
            +
                TOKEN_TYPE = 'urn:oasis:names:tc:SAML:2.0:assertion'.freeze
         
     | 
| 
      
 19 
     | 
    
         
            +
                TOKEN_PROFILE = 'http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0'.freeze
         
     | 
| 
      
 20 
     | 
    
         
            +
                NAMESPACES = {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  :ds => 'http://www.w3.org/2000/09/xmldsig#',
         
     | 
| 
      
 22 
     | 
    
         
            +
                  :soap => 'http://schemas.xmlsoap.org/soap/envelope/',
         
     | 
| 
      
 23 
     | 
    
         
            +
                  :wsse => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
         
     | 
| 
      
 24 
     | 
    
         
            +
                  :wsse11 => 'http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd',
         
     | 
| 
      
 25 
     | 
    
         
            +
                  :wst => 'http://docs.oasis-open.org/ws-sx/ws-trust/200512',
         
     | 
| 
      
 26 
     | 
    
         
            +
                  :wsu => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
         
     | 
| 
      
 27 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                attr_reader :assertion,
         
     | 
| 
      
 30 
     | 
    
         
            +
                            :assertion_id,
         
     | 
| 
      
 31 
     | 
    
         
            +
                            :certificate,
         
     | 
| 
      
 32 
     | 
    
         
            +
                            :host,
         
     | 
| 
      
 33 
     | 
    
         
            +
                            :user,
         
     | 
| 
      
 34 
     | 
    
         
            +
                            :password,
         
     | 
| 
      
 35 
     | 
    
         
            +
                            :path,
         
     | 
| 
      
 36 
     | 
    
         
            +
                            :port,
         
     | 
| 
      
 37 
     | 
    
         
            +
                            :private_key
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Creates an instance of an SSO object
         
     | 
| 
      
 40 
     | 
    
         
            +
                #
         
     | 
| 
      
 41 
     | 
    
         
            +
                # @param [Hash] opts the options to create the object with
         
     | 
| 
      
 42 
     | 
    
         
            +
                # @option opts [String] :host the host to connect to
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @option opts [Fixnum] :port (443) the port to connect to
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @option opts [String] :path the path to call
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @option opts [String] :user the user to authenticate with
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @option opts [String] :password the password to authenticate with
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @option opts [String] :private_key the private key to use
         
     | 
| 
      
 48 
     | 
    
         
            +
                # @option opts [String] :certificate the certificate to use
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @option opts [Boolean] :insecure (false) whether to connect insecurely
         
     | 
| 
      
 50 
     | 
    
         
            +
                def initialize(opts = {})
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @host     = opts[:host]
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @insecure = opts.fetch(:insecure, false)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @password = opts[:password]
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @path     = opts.fetch(:path, STS_PATH)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @port     = opts.fetch(:port, 443)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @user     = opts[:user]
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  load_x509(opts[:private_key], opts[:certificate])
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def request_token
         
     | 
| 
      
 62 
     | 
    
         
            +
                  req = sso_call(hok_token_request)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  unless req.is_a?(Net::HTTPSuccess)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    resp = Nokogiri::XML(req.body)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    resp.remove_namespaces!
         
     | 
| 
      
 67 
     | 
    
         
            +
                    raise(resp.at_xpath('//Envelope/Body/Fault/faultstring/text()'))
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  extract_assertion(req.body)
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def sign_request(request)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  raise('Need SAML2 assertion') unless @assertion
         
     | 
| 
      
 75 
     | 
    
         
            +
                  raise('No SAML2 assertion ID') unless @assertion_id
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  request_id = generate_id
         
     | 
| 
      
 78 
     | 
    
         
            +
                  timestamp_id = generate_id
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  request = request.is_a?(String) ? Nokogiri::XML(request) : request
         
     | 
| 
      
 81 
     | 
    
         
            +
                  builder = Nokogiri::XML::Builder.new do |xml|
         
     | 
| 
      
 82 
     | 
    
         
            +
                    xml[:soap].Header(Hash[NAMESPACES.map { |ns, uri| ["xmlns:#{ns}", uri] }]) do
         
     | 
| 
      
 83 
     | 
    
         
            +
                      xml[:wsse].Security do
         
     | 
| 
      
 84 
     | 
    
         
            +
                        wsu_timestamp(xml, timestamp_id)
         
     | 
| 
      
 85 
     | 
    
         
            +
                        ds_signature(xml, request_id, timestamp_id) do |x|
         
     | 
| 
      
 86 
     | 
    
         
            +
                          x[:wsse].SecurityTokenReference('wsse11:TokenType' => TOKEN_PROFILE) do
         
     | 
| 
      
 87 
     | 
    
         
            +
                            x[:wsse].KeyIdentifier(
         
     | 
| 
      
 88 
     | 
    
         
            +
                              @assertion_id,
         
     | 
| 
      
 89 
     | 
    
         
            +
                              'ValueType' => 'http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID'
         
     | 
| 
      
 90 
     | 
    
         
            +
                            )
         
     | 
| 
      
 91 
     | 
    
         
            +
                          end
         
     | 
| 
      
 92 
     | 
    
         
            +
                        end
         
     | 
| 
      
 93 
     | 
    
         
            +
                      end
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  # To avoid Nokogiri mangling the token, we replace it as a string
         
     | 
| 
      
 98 
     | 
    
         
            +
                  # later on. Figure out a way around this.
         
     | 
| 
      
 99 
     | 
    
         
            +
                  builder.doc.at_xpath('//soap:Header/wsse:Security/wsu:Timestamp').add_previous_sibling(Nokogiri::XML::Text.new('SAML_ASSERTION_PLACEHOLDER', builder.doc))
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  request.at_xpath('//soap:Envelope', NAMESPACES).tap do |e|
         
     | 
| 
      
 102 
     | 
    
         
            +
                    NAMESPACES.each do |ns, uri|
         
     | 
| 
      
 103 
     | 
    
         
            +
                      e.add_namespace(ns.to_s, uri)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  request.xpath('//soap:Envelope/soap:Body').each do |body|
         
     | 
| 
      
 107 
     | 
    
         
            +
                    body.add_previous_sibling(builder.doc.root)
         
     | 
| 
      
 108 
     | 
    
         
            +
                    body.add_namespace('wsu', NAMESPACES[:wsu])
         
     | 
| 
      
 109 
     | 
    
         
            +
                    body['wsu:Id'] = request_id
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  signed = sign(request)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  signed.gsub!('SAML_ASSERTION_PLACEHOLDER', @assertion.to_xml(:indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML).strip)
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  signed
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                # We default to Issue, since that's all we currently need.
         
     | 
| 
      
 119 
     | 
    
         
            +
                def sso_call(body)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  sso_url = URI::HTTPS.build(:host => @host, :port => @port, :path => @path)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  http = Net::HTTP.new(sso_url.host, sso_url.port)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  http.use_ssl = true
         
     | 
| 
      
 123 
     | 
    
         
            +
                  http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @insecure
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  req = Net::HTTP::Post.new(sso_url.request_uri)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  req.add_field('Accept', 'text/xml, multipart/related')
         
     | 
| 
      
 127 
     | 
    
         
            +
                  req.add_field('User-Agent', "VMware/RbVmomi #{RbVmomi::VERSION}")
         
     | 
| 
      
 128 
     | 
    
         
            +
                  req.add_field('SOAPAction', 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue')
         
     | 
| 
      
 129 
     | 
    
         
            +
                  req.content_type = 'text/xml; charset="UTF-8"'
         
     | 
| 
      
 130 
     | 
    
         
            +
                  req.body = body
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  http.request(req)
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                private
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                def hok_token_request
         
     | 
| 
      
 138 
     | 
    
         
            +
                  request_id = generate_id
         
     | 
| 
      
 139 
     | 
    
         
            +
                  security_token_id = generate_id
         
     | 
| 
      
 140 
     | 
    
         
            +
                  signature_id = generate_id
         
     | 
| 
      
 141 
     | 
    
         
            +
                  timestamp_id = generate_id
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  datum = Time.now.utc
         
     | 
| 
      
 144 
     | 
    
         
            +
                  created_at = datum.iso8601
         
     | 
| 
      
 145 
     | 
    
         
            +
                  token_expires_at = (datum + 1800).iso8601
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  builder = Nokogiri::XML::Builder.new do |xml|
         
     | 
| 
      
 148 
     | 
    
         
            +
                    xml[:soap].Envelope(Hash[NAMESPACES.map { |ns, uri| ["xmlns:#{ns}", uri] }]) do
         
     | 
| 
      
 149 
     | 
    
         
            +
                      xml[:soap].Header do
         
     | 
| 
      
 150 
     | 
    
         
            +
                        xml[:wsse].Security do
         
     | 
| 
      
 151 
     | 
    
         
            +
                          wsu_timestamp(xml, timestamp_id, datum)
         
     | 
| 
      
 152 
     | 
    
         
            +
                          wsse_username_token(xml)
         
     | 
| 
      
 153 
     | 
    
         
            +
                          wsse_binary_security_token(xml, security_token_id)
         
     | 
| 
      
 154 
     | 
    
         
            +
                          ds_signature(xml, request_id, timestamp_id, signature_id) do |x|
         
     | 
| 
      
 155 
     | 
    
         
            +
                            x[:wsse].SecurityTokenReference do
         
     | 
| 
      
 156 
     | 
    
         
            +
                              x[:wsse].Reference(
         
     | 
| 
      
 157 
     | 
    
         
            +
                                'URI' => "##{security_token_id}",
         
     | 
| 
      
 158 
     | 
    
         
            +
                                'ValueType' => BST_PROFILE
         
     | 
| 
      
 159 
     | 
    
         
            +
                              )
         
     | 
| 
      
 160 
     | 
    
         
            +
                            end
         
     | 
| 
      
 161 
     | 
    
         
            +
                          end
         
     | 
| 
      
 162 
     | 
    
         
            +
                        end
         
     | 
| 
      
 163 
     | 
    
         
            +
                      end
         
     | 
| 
      
 164 
     | 
    
         
            +
                      xml[:soap].Body('wsu:Id' => request_id) do
         
     | 
| 
      
 165 
     | 
    
         
            +
                        xml[:wst].RequestSecurityToken do
         
     | 
| 
      
 166 
     | 
    
         
            +
                          xml[:wst].TokenType(TOKEN_TYPE)
         
     | 
| 
      
 167 
     | 
    
         
            +
                          xml[:wst].RequestType('http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue')
         
     | 
| 
      
 168 
     | 
    
         
            +
                          xml[:wst].Lifetime do
         
     | 
| 
      
 169 
     | 
    
         
            +
                            xml[:wsu].Created(created_at)
         
     | 
| 
      
 170 
     | 
    
         
            +
                            xml[:wsu].Expires(token_expires_at)
         
     | 
| 
      
 171 
     | 
    
         
            +
                          end
         
     | 
| 
      
 172 
     | 
    
         
            +
                          xml[:wst].Renewing('Allow' => 'false', 'OK' => 'false')
         
     | 
| 
      
 173 
     | 
    
         
            +
                          xml[:wst].KeyType('http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey')
         
     | 
| 
      
 174 
     | 
    
         
            +
                          xml[:wst].SignatureAlgorithm(SIGNATURE_METHOD)
         
     | 
| 
      
 175 
     | 
    
         
            +
                          xml[:wst].Delegatable('false')
         
     | 
| 
      
 176 
     | 
    
         
            +
                        end
         
     | 
| 
      
 177 
     | 
    
         
            +
                        xml[:wst].UseKey('Sig' => signature_id)
         
     | 
| 
      
 178 
     | 
    
         
            +
                      end
         
     | 
| 
      
 179 
     | 
    
         
            +
                    end
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  sign(builder.doc)
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                def extract_assertion(sso_response)
         
     | 
| 
      
 186 
     | 
    
         
            +
                  sso_response = Nokogiri::XML(sso_response) if sso_response.is_a?(String)
         
     | 
| 
      
 187 
     | 
    
         
            +
                  namespaces = sso_response.collect_namespaces
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                  # Doesn't matter that usually there's more than one NS with the same
         
     | 
| 
      
 190 
     | 
    
         
            +
                  # URI - either will work for XPath. We just don't want to hardcode
         
     | 
| 
      
 191 
     | 
    
         
            +
                  # xmlns:saml2.
         
     | 
| 
      
 192 
     | 
    
         
            +
                  token_ns = namespaces.find { |_, uri| uri == TOKEN_TYPE }.first.gsub(/^xmlns:/, '')
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  @assertion = sso_response.at_xpath("//#{token_ns}:Assertion", namespaces)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  @assertion_id = @assertion.at_xpath("//#{token_ns}:Assertion/@ID", namespaces).value
         
     | 
| 
      
 196 
     | 
    
         
            +
                end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                def sign(doc)
         
     | 
| 
      
 199 
     | 
    
         
            +
                  signature_digest_references = doc.xpath('/soap:Envelope/soap:Header/wsse:Security/ds:Signature/ds:SignedInfo/ds:Reference/@URI', doc.collect_namespaces).map { |a| a.value.sub(/^#/, '') }
         
     | 
| 
      
 200 
     | 
    
         
            +
                  signature_digest_references.each do |ref|
         
     | 
| 
      
 201 
     | 
    
         
            +
                    data = doc.at_xpath("//*[@wsu:Id='#{ref}']", doc.collect_namespaces)
         
     | 
| 
      
 202 
     | 
    
         
            +
                    digest = Base64.strict_encode64(Digest::SHA2.new(512).digest(data.canonicalize(C14N_CLASS)))
         
     | 
| 
      
 203 
     | 
    
         
            +
                    digest_tag = doc.at_xpath("/soap:Envelope/soap:Header/wsse:Security/ds:Signature/ds:SignedInfo/ds:Reference[@URI='##{ref}']/ds:DigestValue", doc.collect_namespaces)
         
     | 
| 
      
 204 
     | 
    
         
            +
                    digest_tag.add_child(Nokogiri::XML::Text.new(digest, doc))
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                  signed_info = doc.at_xpath('/soap:Envelope/soap:Header/wsse:Security/ds:Signature/ds:SignedInfo', doc.collect_namespaces)
         
     | 
| 
      
 208 
     | 
    
         
            +
                  signature = Base64.strict_encode64(@private_key.sign(OpenSSL::Digest::SHA512.new, signed_info.canonicalize(C14N_CLASS)))
         
     | 
| 
      
 209 
     | 
    
         
            +
                  signature_value_tag = doc.at_xpath('/soap:Envelope/soap:Header/wsse:Security/ds:Signature/ds:SignatureValue', doc.collect_namespaces)
         
     | 
| 
      
 210 
     | 
    
         
            +
                  signature_value_tag.add_child(Nokogiri::XML::Text.new(signature, doc))
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                  doc.to_xml(:indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML).strip
         
     | 
| 
      
 213 
     | 
    
         
            +
                end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                def load_x509(private_key, certificate)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  @private_key = private_key ? private_key : OpenSSL::PKey::RSA.new(2048)
         
     | 
| 
      
 217 
     | 
    
         
            +
                  if @private_key.is_a? String
         
     | 
| 
      
 218 
     | 
    
         
            +
                    @private_key = OpenSSL::PKey::RSA.new(@private_key)
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                  @certificate = certificate
         
     | 
| 
      
 222 
     | 
    
         
            +
                  if @certificate && !private_key
         
     | 
| 
      
 223 
     | 
    
         
            +
                    raise(ArgumentError, "Can't generate private key from a certificate")
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                  if @certificate.is_a? String
         
     | 
| 
      
 227 
     | 
    
         
            +
                    @certificate = OpenSSL::X509::Certificate.new(@certificate)
         
     | 
| 
      
 228 
     | 
    
         
            +
                  end
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # If only a private key is specified, we will generate a certificate.
         
     | 
| 
      
 230 
     | 
    
         
            +
                  unless @certificate
         
     | 
| 
      
 231 
     | 
    
         
            +
                    timestamp = Time.now.utc
         
     | 
| 
      
 232 
     | 
    
         
            +
                    @certificate = OpenSSL::X509::Certificate.new
         
     | 
| 
      
 233 
     | 
    
         
            +
                    @certificate.not_before = timestamp
         
     | 
| 
      
 234 
     | 
    
         
            +
                    @certificate.not_after = timestamp + 3600 # 3600 is 1 hour
         
     | 
| 
      
 235 
     | 
    
         
            +
                    @certificate.subject = OpenSSL::X509::Name.new([
         
     | 
| 
      
 236 
     | 
    
         
            +
                                                                     %w[O VMware],
         
     | 
| 
      
 237 
     | 
    
         
            +
                                                                     %w[OU RbVmomi],
         
     | 
| 
      
 238 
     | 
    
         
            +
                                                                     %W[CN #{@user}]
         
     | 
| 
      
 239 
     | 
    
         
            +
                                                                   ])
         
     | 
| 
      
 240 
     | 
    
         
            +
                    @certificate.issuer = @certificate.subject
         
     | 
| 
      
 241 
     | 
    
         
            +
                    @certificate.serial = rand(2**160)
         
     | 
| 
      
 242 
     | 
    
         
            +
                    @certificate.public_key = @private_key.public_key
         
     | 
| 
      
 243 
     | 
    
         
            +
                    @certificate.sign(@private_key, OpenSSL::Digest::SHA512.new)
         
     | 
| 
      
 244 
     | 
    
         
            +
                  end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                  true
         
     | 
| 
      
 247 
     | 
    
         
            +
                end
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                def ds_signature(xml, request_id, timestamp_id, id = nil)
         
     | 
| 
      
 250 
     | 
    
         
            +
                  signature_id = {}
         
     | 
| 
      
 251 
     | 
    
         
            +
                  signature_id['Id'] = id if id
         
     | 
| 
      
 252 
     | 
    
         
            +
                  xml[:ds].Signature(signature_id) do
         
     | 
| 
      
 253 
     | 
    
         
            +
                    ds_signed_info(xml, request_id, timestamp_id)
         
     | 
| 
      
 254 
     | 
    
         
            +
                    xml[:ds].SignatureValue
         
     | 
| 
      
 255 
     | 
    
         
            +
                    xml[:ds].KeyInfo do
         
     | 
| 
      
 256 
     | 
    
         
            +
                      yield xml
         
     | 
| 
      
 257 
     | 
    
         
            +
                    end
         
     | 
| 
      
 258 
     | 
    
         
            +
                  end
         
     | 
| 
      
 259 
     | 
    
         
            +
                end
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                def ds_signed_info(xml, request_id, timestamp_id)
         
     | 
| 
      
 262 
     | 
    
         
            +
                  xml[:ds].SignedInfo do
         
     | 
| 
      
 263 
     | 
    
         
            +
                    xml[:ds].CanonicalizationMethod('Algorithm' => C14N_METHOD)
         
     | 
| 
      
 264 
     | 
    
         
            +
                    xml[:ds].SignatureMethod('Algorithm' => SIGNATURE_METHOD)
         
     | 
| 
      
 265 
     | 
    
         
            +
                    xml[:ds].Reference('URI' => "##{request_id}") do
         
     | 
| 
      
 266 
     | 
    
         
            +
                      xml[:ds].Transforms do
         
     | 
| 
      
 267 
     | 
    
         
            +
                        xml[:ds].Transform('Algorithm' => C14N_METHOD)
         
     | 
| 
      
 268 
     | 
    
         
            +
                      end
         
     | 
| 
      
 269 
     | 
    
         
            +
                      xml[:ds].DigestMethod('Algorithm' => DIGEST_METHOD)
         
     | 
| 
      
 270 
     | 
    
         
            +
                      xml[:ds].DigestValue
         
     | 
| 
      
 271 
     | 
    
         
            +
                    end
         
     | 
| 
      
 272 
     | 
    
         
            +
                    xml[:ds].Reference('URI' => "##{timestamp_id}") do
         
     | 
| 
      
 273 
     | 
    
         
            +
                      xml[:ds].Transforms do
         
     | 
| 
      
 274 
     | 
    
         
            +
                        xml[:ds].Transform('Algorithm' => C14N_METHOD)
         
     | 
| 
      
 275 
     | 
    
         
            +
                      end
         
     | 
| 
      
 276 
     | 
    
         
            +
                      xml[:ds].DigestMethod('Algorithm' => DIGEST_METHOD)
         
     | 
| 
      
 277 
     | 
    
         
            +
                      xml[:ds].DigestValue
         
     | 
| 
      
 278 
     | 
    
         
            +
                    end
         
     | 
| 
      
 279 
     | 
    
         
            +
                  end
         
     | 
| 
      
 280 
     | 
    
         
            +
                end
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                def wsu_timestamp(xml, id, datum = nil)
         
     | 
| 
      
 283 
     | 
    
         
            +
                  datum ||= Time.now.utc
         
     | 
| 
      
 284 
     | 
    
         
            +
                  created_at = datum.iso8601
         
     | 
| 
      
 285 
     | 
    
         
            +
                  expires_at = (datum + 600).iso8601
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                  xml[:wsu].Timestamp('wsu:Id' => id) do
         
     | 
| 
      
 288 
     | 
    
         
            +
                    xml[:wsu].Created(created_at)
         
     | 
| 
      
 289 
     | 
    
         
            +
                    xml[:wsu].Expires(expires_at)
         
     | 
| 
      
 290 
     | 
    
         
            +
                  end
         
     | 
| 
      
 291 
     | 
    
         
            +
                end
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                def wsse_username_token(xml)
         
     | 
| 
      
 294 
     | 
    
         
            +
                  xml[:wsse].UsernameToken do
         
     | 
| 
      
 295 
     | 
    
         
            +
                    xml[:wsse].Username(@user)
         
     | 
| 
      
 296 
     | 
    
         
            +
                    xml[:wsse].Password(@password)
         
     | 
| 
      
 297 
     | 
    
         
            +
                  end
         
     | 
| 
      
 298 
     | 
    
         
            +
                end
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                def wsse_binary_security_token(xml, id)
         
     | 
| 
      
 301 
     | 
    
         
            +
                  xml[:wsse].BinarySecurityToken(
         
     | 
| 
      
 302 
     | 
    
         
            +
                    Base64.strict_encode64(@certificate.to_der),
         
     | 
| 
      
 303 
     | 
    
         
            +
                    'EncodingType' => ENCODING_METHOD,
         
     | 
| 
      
 304 
     | 
    
         
            +
                    'ValueType' => BST_PROFILE,
         
     | 
| 
      
 305 
     | 
    
         
            +
                    'wsu:Id' => id
         
     | 
| 
      
 306 
     | 
    
         
            +
                  )
         
     | 
| 
      
 307 
     | 
    
         
            +
                end
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
      
 309 
     | 
    
         
            +
                def generate_id
         
     | 
| 
      
 310 
     | 
    
         
            +
                  "_#{SecureRandom.uuid}"
         
     | 
| 
      
 311 
     | 
    
         
            +
                end
         
     | 
| 
      
 312 
     | 
    
         
            +
              end
         
     | 
| 
      
 313 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/rbvmomi/trivial_soap.rb
    CHANGED
    
    | 
         @@ -17,6 +17,7 @@ class RbVmomi::TrivialSoap 
     | 
|
| 
       17 
17 
     | 
    
         
             
                return unless @opts[:host] # for testcases
         
     | 
| 
       18 
18 
     | 
    
         
             
                @debug = @opts[:debug]
         
     | 
| 
       19 
19 
     | 
    
         
             
                @cookie = @opts[:cookie]
         
     | 
| 
      
 20 
     | 
    
         
            +
                @sso = @opts[:sso]
         
     | 
| 
       20 
21 
     | 
    
         
             
                @operation_id = @opts[:operation_id]
         
     | 
| 
       21 
22 
     | 
    
         
             
                @lock = Mutex.new
         
     | 
| 
       22 
23 
     | 
    
         
             
                @http = nil
         
     | 
| 
         @@ -89,6 +90,11 @@ class RbVmomi::TrivialSoap 
     | 
|
| 
       89 
90 
     | 
    
         
             
                  $stderr.puts
         
     | 
| 
       90 
91 
     | 
    
         
             
                end
         
     | 
| 
       91 
92 
     | 
    
         | 
| 
      
 93 
     | 
    
         
            +
                if @cookie.nil? && @sso
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @sso.request_token unless @sso.assertion_id
         
     | 
| 
      
 95 
     | 
    
         
            +
                  body = @sso.sign_request(body)
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
       92 
98 
     | 
    
         
             
                start_time = Time.now
         
     | 
| 
       93 
99 
     | 
    
         
             
                response = @lock.synchronize do
         
     | 
| 
       94 
100 
     | 
    
         
             
                  begin
         
     | 
    
        data/lib/rbvmomi/version.rb
    CHANGED
    
    
    
        data/lib/rbvmomi/vim.rb
    CHANGED
    
    | 
         @@ -27,6 +27,7 @@ class VIM < Connection 
     | 
|
| 
       27 
27 
     | 
    
         
             
              # @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
         
     | 
| 
       28 
28 
     | 
    
         
             
              # @option opts [String]  :operation_id If set, use for operationID
         
     | 
| 
       29 
29 
     | 
    
         
             
              # @option opts [Boolean] :close_on_exit (true) If true, will close connection with at_exit
         
     | 
| 
      
 30 
     | 
    
         
            +
              # @option opts [RbVmomi::SSO] :sso (nil) Use SSO token to login if set
         
     | 
| 
       30 
31 
     | 
    
         
             
              def self.connect opts
         
     | 
| 
       31 
32 
     | 
    
         
             
                fail unless opts.is_a? Hash
         
     | 
| 
       32 
33 
     | 
    
         
             
                fail "host option required" unless opts[:host]
         
     | 
| 
         @@ -38,7 +39,7 @@ class VIM < Connection 
     | 
|
| 
       38 
39 
     | 
    
         
             
                opts[:port] ||= (opts[:ssl] ? 443 : 80)
         
     | 
| 
       39 
40 
     | 
    
         
             
                opts[:path] ||= '/sdk'
         
     | 
| 
       40 
41 
     | 
    
         
             
                opts[:ns] ||= 'urn:vim25'
         
     | 
| 
       41 
     | 
    
         
            -
                opts[:rev] = '6. 
     | 
| 
      
 42 
     | 
    
         
            +
                opts[:rev] = '6.7' if opts[:rev].nil?
         
     | 
| 
       42 
43 
     | 
    
         
             
                opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
         
     | 
| 
       43 
44 
     | 
    
         | 
| 
       44 
45 
     | 
    
         
             
                conn = new(opts).tap do |vim|
         
     | 
| 
         @@ -55,8 +56,10 @@ class VIM < Connection 
     | 
|
| 
       55 
56 
     | 
    
         
             
                            vim.serviceContent.sessionManager.LoginBySSPI :base64Token => negotiation.complete_authentication(fault.base64Token)
         
     | 
| 
       56 
57 
     | 
    
         
             
                          end
         
     | 
| 
       57 
58 
     | 
    
         
             
                        end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    elsif opts[:sso]
         
     | 
| 
      
 60 
     | 
    
         
            +
                      vim.serviceContent.sessionManager.LoginByToken
         
     | 
| 
       58 
61 
     | 
    
         
             
                    else
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 62 
     | 
    
         
            +
                      vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
         
     | 
| 
       60 
63 
     | 
    
         
             
                    end
         
     | 
| 
       61 
64 
     | 
    
         
             
                  end
         
     | 
| 
       62 
65 
     | 
    
         
             
                  rev = vim.serviceContent.about.apiVersion
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: rbvmomi
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Rich Lane
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2019- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2019-06-13 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: builder
         
     | 
| 
         @@ -140,9 +140,9 @@ files: 
     | 
|
| 
       140 
140 
     | 
    
         
             
            - lib/rbvmomi/fault.rb
         
     | 
| 
       141 
141 
     | 
    
         
             
            - lib/rbvmomi/optimist.rb
         
     | 
| 
       142 
142 
     | 
    
         
             
            - lib/rbvmomi/pbm.rb
         
     | 
| 
       143 
     | 
    
         
            -
            - lib/rbvmomi/rake_task.rb~
         
     | 
| 
       144 
143 
     | 
    
         
             
            - lib/rbvmomi/sms.rb
         
     | 
| 
       145 
144 
     | 
    
         
             
            - lib/rbvmomi/sms/SmsStorageManager.rb
         
     | 
| 
      
 145 
     | 
    
         
            +
            - lib/rbvmomi/sso.rb
         
     | 
| 
       146 
146 
     | 
    
         
             
            - lib/rbvmomi/trivial_soap.rb
         
     | 
| 
       147 
147 
     | 
    
         
             
            - lib/rbvmomi/type_loader.rb
         
     | 
| 
       148 
148 
     | 
    
         
             
            - lib/rbvmomi/utils/admission_control.rb
         
     |