gcewinpass 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +37 -0
- data/.travis.yml +1 -0
- data/Gemfile +1 -3
- data/Rakefile +5 -5
- data/gcewinpass.gemspec +15 -13
- data/lib/gcewinpass.rb +34 -34
- data/lib/gcewinpass/version.rb +1 -1
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce212b5a7a13922fc372ce2bdb49c753bb5ca316
|
4
|
+
data.tar.gz: 3857b8649fa593a92b50772282464b2e208f2328
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9908386fed61d4e9f7c3f3d1d2d08375301b77ff21b8d0cac3c6d8cdb68d38035bc8e5fd4095358065fcd049f36529d6424936f0a570729f451cf4b7ba74e0a
|
7
|
+
data.tar.gz: cbe40f7e4082ba9e44cc5916c5ded942b27378ae88f8dbcffec21bf9c46f476dab0dafc453a97772e1a037628429020d663e86235dc2371a5251f86b736f80fd
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Layout/IndentHeredoc:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Metrics/AbcSize:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/BlockLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/LineLength:
|
14
|
+
Max: 130
|
15
|
+
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/Documentation:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/GuardClause:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/InverseMethods:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/StringLiterals:
|
29
|
+
Enabled: true
|
30
|
+
EnforcedStyle: single_quotes
|
31
|
+
|
32
|
+
Style/TrailingCommaInLiteral:
|
33
|
+
Enabled: true
|
34
|
+
SupportedStylesForMultiline: comma
|
35
|
+
|
36
|
+
Style/SymbolArray:
|
37
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
6
|
+
require 'chefstyle'
|
7
|
+
require 'rubocop/rake_task'
|
8
8
|
RuboCop::RakeTask.new(:style) do |task|
|
9
|
-
task.options <<
|
9
|
+
task.options << '--display-cop-names'
|
10
10
|
end
|
11
11
|
|
12
12
|
task default: [:spec, :style]
|
data/gcewinpass.gemspec
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
|
5
|
-
require
|
6
|
+
require 'gcewinpass/version'
|
6
7
|
|
7
8
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
9
|
+
spec.name = 'gcewinpass'
|
9
10
|
spec.version = GoogleComputeWindowsPassword::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
11
|
+
spec.authors = ['Chef Partner Engineering']
|
12
|
+
spec.email = ['partnereng@chef.io']
|
12
13
|
|
13
|
-
spec.summary =
|
14
|
+
spec.summary = 'Reset a password on a Google Compute Engine instance running Windows.'
|
14
15
|
spec.description = spec.summary
|
15
|
-
spec.homepage =
|
16
|
+
spec.homepage = 'https://github.com/chef-partners/gcewinpass'
|
16
17
|
|
17
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
19
20
|
|
20
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency 'google-api-client', '~> 0.13'
|
21
22
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.4'
|
26
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
27
|
+
spec.add_development_dependency 'chefstyle', '0.3.1'
|
26
28
|
end
|
data/lib/gcewinpass.rb
CHANGED
@@ -16,13 +16,13 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
19
|
+
require 'gcewinpass/version'
|
20
|
+
require 'google/apis/compute_v1'
|
21
|
+
require 'base64'
|
22
|
+
require 'json'
|
23
|
+
require 'openssl'
|
24
|
+
require 'time'
|
25
|
+
require 'timeout'
|
26
26
|
|
27
27
|
class GoogleComputeWindowsPassword
|
28
28
|
attr_reader :api, :project, :zone, :instance_name, :username, :email, :debug
|
@@ -37,7 +37,7 @@ class GoogleComputeWindowsPassword
|
|
37
37
|
@zone = opts[:zone]
|
38
38
|
@instance_name = opts[:instance_name]
|
39
39
|
@email = opts[:email]
|
40
|
-
@username = opts.fetch(:username,
|
40
|
+
@username = opts.fetch(:username, 'Administrator')
|
41
41
|
@debug = opts.fetch(:debug, false)
|
42
42
|
@timeout = opts.fetch(:timeout, 120)
|
43
43
|
end
|
@@ -50,17 +50,17 @@ class GoogleComputeWindowsPassword
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def validate_options!(opts)
|
53
|
-
raise
|
54
|
-
raise
|
55
|
-
raise
|
56
|
-
raise
|
53
|
+
raise 'Project not specified' unless opts[:project]
|
54
|
+
raise 'Zone not specified' unless opts[:zone]
|
55
|
+
raise 'Instance name not specified' unless opts[:instance_name]
|
56
|
+
raise 'Email address of GCE user not specified' unless opts[:email]
|
57
57
|
end
|
58
58
|
|
59
59
|
def authorization
|
60
60
|
@authorization ||= Google::Auth.get_application_default(
|
61
61
|
[
|
62
|
-
|
63
|
-
|
62
|
+
'https://www.googleapis.com/auth/cloud-platform',
|
63
|
+
'https://www.googleapis.com/auth/compute',
|
64
64
|
]
|
65
65
|
)
|
66
66
|
end
|
@@ -83,31 +83,31 @@ class GoogleComputeWindowsPassword
|
|
83
83
|
|
84
84
|
def password_request
|
85
85
|
{
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
'userName' => username,
|
87
|
+
'modulus' => modulus,
|
88
|
+
'exponent' => exponent,
|
89
|
+
'email' => email,
|
90
|
+
'expireOn' => expiration_date,
|
91
91
|
}
|
92
92
|
end
|
93
93
|
|
94
94
|
def password_request_metadata
|
95
95
|
Google::Apis::ComputeV1::Metadata::Item.new.tap do |item|
|
96
|
-
item.key =
|
96
|
+
item.key = 'windows-keys'
|
97
97
|
item.value = password_request.to_json
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
def update_instance_metadata
|
102
102
|
instance_metadata.items = [] if instance_metadata.items.nil?
|
103
|
-
instance_metadata.items = instance_metadata.items.select { |item| item.key !=
|
103
|
+
instance_metadata.items = instance_metadata.items.select { |item| item.key != 'windows-keys' }
|
104
104
|
instance_metadata.items << password_request_metadata
|
105
105
|
|
106
106
|
log_debug("Updating instance #{instance_name} metadata with: #{instance_metadata.inspect}")
|
107
107
|
|
108
108
|
wait_for_operation(api.set_instance_metadata(project, zone, instance_name, instance_metadata))
|
109
109
|
|
110
|
-
log_debug(
|
110
|
+
log_debug('Instance metadata updated.')
|
111
111
|
end
|
112
112
|
|
113
113
|
def private_key
|
@@ -132,13 +132,13 @@ class GoogleComputeWindowsPassword
|
|
132
132
|
|
133
133
|
def password_from_instance
|
134
134
|
response = response_from_console_port
|
135
|
-
raise
|
135
|
+
raise 'Password agent attempted the reset but did not succeed' if response['passwordFound'] == false
|
136
136
|
|
137
|
-
private_key.private_decrypt(Base64.strict_decode64(response[
|
137
|
+
private_key.private_decrypt(Base64.strict_decode64(response['encryptedPassword']), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
|
138
138
|
end
|
139
139
|
|
140
140
|
def response_from_console_port
|
141
|
-
log_debug(
|
141
|
+
log_debug('fetching password from console port')
|
142
142
|
|
143
143
|
Timeout.timeout(timeout) do
|
144
144
|
loop do
|
@@ -146,23 +146,23 @@ class GoogleComputeWindowsPassword
|
|
146
146
|
line.strip!
|
147
147
|
|
148
148
|
begin
|
149
|
-
event = JSON.
|
149
|
+
event = JSON.parse(line)
|
150
150
|
rescue JSON::ParserError
|
151
151
|
next
|
152
152
|
end
|
153
153
|
|
154
|
-
if event[
|
155
|
-
log_debug(
|
154
|
+
if event['modulus'] == modulus && event['exponent'] == exponent
|
155
|
+
log_debug('modulus and exponent found - returning event')
|
156
156
|
return event
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
log_debug(
|
160
|
+
log_debug('event not found, sleeping...')
|
161
161
|
sleep 5
|
162
162
|
end
|
163
163
|
end
|
164
164
|
rescue Timeout::Error
|
165
|
-
raise Timeout::Error,
|
165
|
+
raise Timeout::Error, 'Timeout while waiting for password agent to perform password reset'
|
166
166
|
end
|
167
167
|
|
168
168
|
def wait_for_operation(operation_obj)
|
@@ -173,17 +173,17 @@ class GoogleComputeWindowsPassword
|
|
173
173
|
loop do
|
174
174
|
operation = operation(operation_name)
|
175
175
|
log_debug("Current operation status: #{operation.status}")
|
176
|
-
break if operation.status ==
|
176
|
+
break if operation.status == 'DONE'
|
177
177
|
|
178
178
|
sleep 2
|
179
179
|
end
|
180
180
|
end
|
181
181
|
rescue Timeout::Error
|
182
|
-
raise Timeout::Error,
|
182
|
+
raise Timeout::Error, 'Timeout while performing GCE API operation'
|
183
183
|
end
|
184
184
|
|
185
185
|
check_operation_for_errors!(operation_name)
|
186
|
-
log_debug(
|
186
|
+
log_debug('Operation completed successfully.')
|
187
187
|
end
|
188
188
|
|
189
189
|
def check_operation_for_errors!(operation_name)
|
@@ -193,7 +193,7 @@ class GoogleComputeWindowsPassword
|
|
193
193
|
memo << "#{error.code}: #{error.message}"
|
194
194
|
end
|
195
195
|
|
196
|
-
raise "Operation failed: #{errors.join(
|
196
|
+
raise "Operation failed: #{errors.join(', ')}"
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
data/lib/gcewinpass/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gcewinpass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Partner Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-api-client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: '0.13'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: '0.13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.10'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: chefstyle
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.3.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.3.1
|
83
97
|
description: Reset a password on a Google Compute Engine instance running Windows.
|
84
98
|
email:
|
85
99
|
- partnereng@chef.io
|
@@ -89,6 +103,7 @@ extra_rdoc_files: []
|
|
89
103
|
files:
|
90
104
|
- ".gitignore"
|
91
105
|
- ".rspec"
|
106
|
+
- ".rubocop.yml"
|
92
107
|
- ".travis.yml"
|
93
108
|
- Gemfile
|
94
109
|
- LICENSE.txt
|
@@ -116,9 +131,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
131
|
version: '0'
|
117
132
|
requirements: []
|
118
133
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.6.13
|
120
135
|
signing_key:
|
121
136
|
specification_version: 4
|
122
137
|
summary: Reset a password on a Google Compute Engine instance running Windows.
|
123
138
|
test_files: []
|
124
|
-
has_rdoc:
|