rbvmomi 1.11.3 → 3.0.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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +2 -2
  3. data/exe/rbvmomish +5 -5
  4. data/lib/rbvmomi/connection.rb +13 -13
  5. data/lib/rbvmomi/deserialization.rb +1 -2
  6. data/lib/rbvmomi/{trollop.rb → optimist.rb} +7 -7
  7. data/lib/rbvmomi/pbm.rb +1 -1
  8. data/lib/rbvmomi/sms.rb +1 -1
  9. data/lib/rbvmomi/sso.rb +313 -0
  10. data/lib/rbvmomi/trivial_soap.rb +8 -5
  11. data/lib/rbvmomi/type_loader.rb +1 -1
  12. data/lib/rbvmomi/utils/deploy.rb +1 -1
  13. data/lib/rbvmomi/version.rb +2 -2
  14. data/lib/rbvmomi/vim/Folder.rb +1 -1
  15. data/lib/rbvmomi/vim/HostSystem.rb +2 -2
  16. data/lib/rbvmomi/vim/ManagedObject.rb +1 -1
  17. data/lib/rbvmomi/vim/OvfManager.rb +1 -1
  18. data/lib/rbvmomi/vim/VirtualMachine.rb +9 -11
  19. data/lib/rbvmomi/vim.rb +9 -10
  20. data/lib/rbvmomi.rb +11 -9
  21. data/vmodl.db +0 -0
  22. metadata +45 -61
  23. data/.gitignore +0 -13
  24. data/.travis.yml +0 -11
  25. data/.yardopts +0 -6
  26. data/CONTRIBUTORS.md +0 -42
  27. data/Gemfile +0 -10
  28. data/Rakefile +0 -16
  29. data/devel/analyze-vim-declarations.rb +0 -217
  30. data/devel/analyze-xml.rb +0 -49
  31. data/devel/benchmark.rb +0 -121
  32. data/devel/collisions.rb +0 -22
  33. data/devel/merge-internal-vmodl.rb +0 -63
  34. data/devel/merge-manual-vmodl.rb +0 -36
  35. data/examples/annotate.rb +0 -57
  36. data/examples/cached_ovf_deploy.rb +0 -124
  37. data/examples/clone_vm.rb +0 -88
  38. data/examples/create_vm-1.9.rb +0 -97
  39. data/examples/create_vm.rb +0 -97
  40. data/examples/extraConfig.rb +0 -57
  41. data/examples/lease_tool.rb +0 -106
  42. data/examples/logbundle.rb +0 -66
  43. data/examples/logtail.rb +0 -63
  44. data/examples/nfs_datastore.rb +0 -99
  45. data/examples/power.rb +0 -62
  46. data/examples/readme-1.rb +0 -38
  47. data/examples/readme-2.rb +0 -54
  48. data/examples/run.sh +0 -41
  49. data/examples/screenshot.rb +0 -51
  50. data/examples/vdf.rb +0 -84
  51. data/examples/vm_drs_behavior.rb +0 -80
  52. data/rbvmomi.gemspec +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 291486048aa5b6cbd7146d49d7324a4b236212d5
4
- data.tar.gz: 1586964068b6036bbee0a7b2beb3c0ca430c8aa6
2
+ SHA256:
3
+ metadata.gz: a94fe8a2f4faf96128119f1108856f73cd48ad979cb7f55da44d85628f7aae7a
4
+ data.tar.gz: 58f4de40f316bab9631062b8f5cad76f12eed1bf420ff9287b95788e7f1b58f5
5
5
  SHA512:
6
- metadata.gz: 7869ac4308e5c56472c42bb1359a1808956d9f2f83b30066825e88b7ab9be434d94b42521a45c335bf7718d8ae624a9102565ffe8c5abb04d3027b735476ca79
7
- data.tar.gz: 7779212ffb10678dcae454875a381ff0beed76488fc77106490506d032b7b166f348a8678ea5577cfe0e2be3bf61967775d001f5f3a0776b0f145078056b372c
6
+ metadata.gz: '08f70868de310a5b3c6b23d376058b02cfba807de7b3dd7bef71f2b976b7400ea1b48ad8e63f1461227a5f8b75eaf7cace3c7f4e73c6acf03378fffe55aaa635'
7
+ data.tar.gz: 6d49a75c34cb17b774a05eb6319818bd56a2762ee9f84da62730f70abf7a143ecf281dfe70884c1bb32040faa680443555f68a3770be0a25b201178d7f4ea93e
data/README.md CHANGED
@@ -56,7 +56,7 @@ require 'rbvmomi'
56
56
 
57
57
  vim = RbVmomi::VIM.connect(host: 'foo', user: 'bar', password: 'baz')
58
58
  root_folder = vim.serviceInstance.content.rootFolder
59
- dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == 'mydatacenter' } || fail('datacenter not found')
59
+ dc = root_folder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == 'mydatacenter' } || fail('datacenter not found')
60
60
  vm = dc.vmFolder.childEntity.grep(RbVmomi::VIM::VirtualMachine).find { |x| x.name == 'my_vm' } || fail('VM not found')
61
61
  task = vm.PowerOnVM_Task
62
62
  filter = vim.propertyCollector.CreateFilter(
@@ -89,7 +89,7 @@ A few important points:
89
89
  * Data object types can usually be inferred from context, so you may use a hash instead.
90
90
  * Enumeration values are simply strings.
91
91
  * Example code is included in the examples/ directory.
92
- * A set of helper methods for Trollop is included to speed up development of
92
+ * A set of helper methods for Optimist is included to speed up development of
93
93
  command line apps. See the included examples for usage.
94
94
  * If you don't have trusted SSL certificates installed on the host you're
95
95
  connecting to, you'll get an `OpenSSL::SSL::SSLError` "certificate verify
data/exe/rbvmomish CHANGED
@@ -2,14 +2,14 @@
2
2
  # TODO keepalive
3
3
  # TODO rc file
4
4
  # TODO proxy support?
5
- require 'trollop'
5
+ require 'optimist'
6
6
  require 'readline'
7
7
  require 'rbvmomi'
8
- require 'rbvmomi/trollop'
8
+ require 'rbvmomi/optimist'
9
9
 
10
10
  VIM = RbVmomi::VIM
11
11
 
12
- opts = Trollop.options do
12
+ opts = Optimist.options do
13
13
  banner <<-EOS
14
14
  vSphere API console.
15
15
 
@@ -35,7 +35,7 @@ VIM connection options:
35
35
  Other options:
36
36
  EOS
37
37
 
38
- $trollop = self
38
+ $optimist = self
39
39
  end
40
40
 
41
41
  begin
@@ -102,7 +102,7 @@ def si
102
102
  end
103
103
 
104
104
  def help
105
- $trollop.educate
105
+ $optimist.educate
106
106
  :no_result
107
107
  end
108
108
 
@@ -3,11 +3,11 @@
3
3
 
4
4
  require 'time'
5
5
  require 'date'
6
- require 'rbvmomi/trivial_soap'
7
- require 'rbvmomi/basic_types'
8
- require 'rbvmomi/fault'
9
- require 'rbvmomi/type_loader'
10
- require 'rbvmomi/deserialization'
6
+ require_relative 'trivial_soap'
7
+ require_relative 'basic_types'
8
+ require_relative 'fault'
9
+ require_relative 'type_loader'
10
+ require_relative 'deserialization'
11
11
 
12
12
  module RbVmomi
13
13
 
@@ -23,7 +23,7 @@ class Connection < TrivialSoap
23
23
  attr_reader :profile_summary
24
24
  attr_accessor :profiling
25
25
  attr_reader :deserializer
26
-
26
+
27
27
  def initialize opts
28
28
  @ns = opts[:ns] or fail "no namespace specified"
29
29
  @rev = opts[:rev] or fail "no revision specified"
@@ -32,7 +32,7 @@ class Connection < TrivialSoap
32
32
  @profiling = false
33
33
  super opts
34
34
  end
35
-
35
+
36
36
  def reset_profiling
37
37
  @profile = {}
38
38
  @profile_summary = {:network_latency => 0, :request_emit => 0, :response_parse => 0, :num_calls => 0}
@@ -90,7 +90,7 @@ class Connection < TrivialSoap
90
90
 
91
91
  t3 = Time.now
92
92
  out = parse_response resp, desc['result']
93
-
93
+
94
94
  if @profiling
95
95
  t4 = Time.now
96
96
  @profile[method] ||= []
@@ -98,8 +98,8 @@ class Connection < TrivialSoap
98
98
  :network_latency => (t3 - t2),
99
99
  :request_emit => t2 - t1,
100
100
  :response_parse => t4 - t3,
101
- :params => params,
102
- :obj => this,
101
+ :params => params,
102
+ :obj => this,
103
103
  :backtrace => caller,
104
104
  :request_size => body.length,
105
105
  :response_size => resp_size,
@@ -110,7 +110,7 @@ class Connection < TrivialSoap
110
110
  @profile_summary[:request_emit] += profile_info[:request_emit]
111
111
  @profile_summary[:num_calls] += 1
112
112
  end
113
-
113
+
114
114
  out
115
115
  end
116
116
 
@@ -139,7 +139,7 @@ class Connection < TrivialSoap
139
139
  when BasicTypes::DataObject
140
140
  if expected and not expected >= o.class and not expected == BasicTypes::AnyType
141
141
  fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}"
142
- end
142
+ end
143
143
  xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
144
144
  o.class.full_props_desc.each do |desc|
145
145
  if o.props.member? desc['name'].to_sym
@@ -223,7 +223,7 @@ class Connection < TrivialSoap
223
223
  def type name
224
224
  self.class.type name
225
225
  end
226
-
226
+
227
227
  def instanceUuid
228
228
  nil
229
229
  end
@@ -101,7 +101,6 @@ class NewDeserializer
101
101
  obj = klass.new nil
102
102
  props = obj.props
103
103
  children = node.children.select(&:element?)
104
- n = children.size
105
104
  i = 0
106
105
 
107
106
  klass.full_props_desc.each do |desc|
@@ -152,7 +151,7 @@ class NewDeserializer
152
151
  h[child.name] = child.content
153
152
  end
154
153
  [h['key'], h['value']]
155
- end
154
+ end
156
155
  end
157
156
 
158
157
  class OldDeserializer
@@ -1,19 +1,19 @@
1
1
  # Copyright (c) 2010-2017 VMware, Inc. All Rights Reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'trollop'
4
+ require 'optimist'
5
5
 
6
- # Convenience methods for Trollop, Ruby's premier option parser.
7
- # @see http://trollop.rubyforge.org/
8
- # @see Trollop::Parser
9
- module Trollop
6
+ # Convenience methods for Optimist, Ruby's premier option parser.
7
+ # @see http://optimist.rubyforge.org/
8
+ # @see Optimist::Parser
9
+ module Optimist
10
10
 
11
- # Convenience methods for Trollop, Ruby's premier option parser.
11
+ # Convenience methods for Optimist, Ruby's premier option parser.
12
12
  #
13
13
  # See the examples directory for sample code.
14
14
  # Descriptions are of the form:
15
15
  # <key>: <options> <environment variable> (<default>)
16
- # @see http://trollop.rubyforge.org/
16
+ # @see http://optimist.rubyforge.org/
17
17
  class Parser
18
18
  # Options used by VIM.connect
19
19
  #
data/lib/rbvmomi/pbm.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2012-2017 VMware, Inc. All Rights Reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'rbvmomi'
4
+ require_relative '../rbvmomi'
5
5
 
6
6
  module RbVmomi
7
7
 
data/lib/rbvmomi/sms.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2013-2017 VMware, Inc. All Rights Reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'rbvmomi'
4
+ require_relative '../rbvmomi'
5
5
  module RbVmomi
6
6
 
7
7
  # A connection to one vSphere SMS endpoint.
@@ -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
@@ -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
@@ -42,11 +43,8 @@ class RbVmomi::TrivialSoap
42
43
  if @opts[:ssl]
43
44
  require 'net/https'
44
45
  @http.use_ssl = true
45
- if @opts[:insecure]
46
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
47
- else
48
- @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
49
- end
46
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @opts[:insecure]
47
+ @http.ca_file = @opts[:ca_file] if @opts[:ca_file]
50
48
  @http.cert = OpenSSL::X509::Certificate.new(@opts[:cert]) if @opts[:cert]
51
49
  @http.key = OpenSSL::PKey::RSA.new(@opts[:key]) if @opts[:key]
52
50
  end
@@ -89,6 +87,11 @@ class RbVmomi::TrivialSoap
89
87
  $stderr.puts
90
88
  end
91
89
 
90
+ if @cookie.nil? && @sso
91
+ @sso.request_token unless @sso.assertion_id
92
+ body = @sso.sign_request(body)
93
+ end
94
+
92
95
  start_time = Time.now
93
96
  response = @lock.synchronize do
94
97
  begin
@@ -95,7 +95,7 @@ class TypeLoader
95
95
 
96
96
  def load_extension name
97
97
  @extension_dirs.map { |x| File.join(x, "#{name}.rb") }.
98
- select { |x| File.exists? x }.
98
+ select { |x| File.exist? x }.
99
99
  each { |x| load x }
100
100
  end
101
101
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'open-uri'
5
5
  require 'nokogiri'
6
- require 'rbvmomi'
6
+ require_relative '../../rbvmomi'
7
7
 
8
8
  # The cached ovf deployer is an optimization on top of regular OVF deployment
9
9
  # as it is offered by the VIM::OVFManager. Creating a VM becomes a multi-stage
@@ -1,6 +1,6 @@
1
- # Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved.
1
+ # Copyright (c) 2016-2020 VMware, Inc. All Rights Reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
4
  module RbVmomi
5
- VERSION = '1.11.3'.freeze
5
+ VERSION = '3.0.0'.freeze
6
6
  end
@@ -67,7 +67,7 @@ class RbVmomi::VIM::Folder
67
67
  propSpecs = {
68
68
  :entity => self, :inventoryPath => path
69
69
  }
70
- x = _connection.searchIndex.FindByInventoryPath(propSpecs)
70
+ _connection.searchIndex.FindByInventoryPath(propSpecs)
71
71
  end
72
72
 
73
73
  # Alias to <tt>traverse path, type, true</tt>
@@ -115,12 +115,12 @@ class VIM::EsxcliNamespace
115
115
  conn.type(@type_info.wsdlName).new(conn, @instance)
116
116
  end
117
117
 
118
- def method_missing name, *args
118
+ def method_missing(name, *args)
119
119
  name = name.to_s
120
120
  if @namespaces.member? name and args.empty?
121
121
  @namespaces[name]
122
122
  elsif @commands.member? name
123
- @commands[name].call *args
123
+ @commands[name].call(*args)
124
124
  else
125
125
  raise NoMethodError
126
126
  end
@@ -52,7 +52,7 @@ class RbVmomi::VIM::ManagedObject
52
52
  # @return [Array] Property values in same order as +pathSet+, or the return
53
53
  # value from the block if it is given.
54
54
  def collect *pathSet
55
- h = collect! *pathSet
55
+ h = collect!(*pathSet)
56
56
  a = pathSet.map { |k| h[k.to_s] }
57
57
  if block_given?
58
58
  yield a
@@ -139,7 +139,7 @@ class RbVmomi::VIM::OvfManager
139
139
  # to the uploadCmd. It is not clear to me why, but that leads to
140
140
  # trucation of the uploaded disk. Without this option curl can't tell
141
141
  # the progress, but who cares
142
- system("#{downloadCmd} | #{uploadCmd}", STDOUT => "/dev/null")
142
+ system("#{downloadCmd} | #{uploadCmd}", :out => "/dev/null")
143
143
 
144
144
  keepAliveThread.kill
145
145
  keepAliveThread.join