knife-azure 2.0.10 → 2.0.11
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/azure/resource_management/windows_credentials.rb +135 -133
- data/lib/chef/knife/azurerm_base.rb +5 -5
- data/lib/knife-azure/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6de7af42a6cf8184a9f2b57ad1556034f129f49812c9c3573a70a22cf95c6fe
|
4
|
+
data.tar.gz: c1aac2ac6eb7c5e0127d8971a3de4fd5fdb085f4521a6c414c857259e20a825e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 215f6a9ebf1f3339e589c48bd86ddf0c762426b26a05972b0660c541f7caedcaa695ed8f38da63fe354eff53af2a2a2caa50f3a2959d268d2e8f2e2cb75d488d
|
7
|
+
data.tar.gz: 3d3ee631a0e3a68fd3af1c50298ceecf7ac04978b1928be79f552e0405bff167cd92793aa4e90e9344ead46cc4518ab359a4eb391a4b1a3b45f6e5602f7c32ea
|
@@ -23,159 +23,161 @@ require "mixlib/shellout"
|
|
23
23
|
require "ffi"
|
24
24
|
require "chef/win32/api"
|
25
25
|
|
26
|
-
module Azure
|
26
|
+
module Azure
|
27
|
+
module ARM
|
27
28
|
|
28
|
-
|
29
|
+
module ReadCred
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
extend Chef::ReservedNames::Win32::API
|
32
|
+
extend FFI::Library
|
32
33
|
|
33
|
-
|
34
|
+
ffi_lib "Advapi32"
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
CRED_TYPE_GENERIC = 1
|
37
|
+
CRED_TYPE_DOMAIN_PASSWORD = 2
|
38
|
+
CRED_TYPE_DOMAIN_CERTIFICATE = 3
|
39
|
+
CRED_TYPE_DOMAIN_VISIBLE_PASSWORD = 4
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374790(v=vs.85).aspx
|
47
|
-
class CREDENTIAL_ATTRIBUTE < FFI::Struct
|
48
|
-
layout :Keyword, :LPTSTR,
|
49
|
-
:Flags, :DWORD,
|
50
|
-
:ValueSize, :DWORD,
|
51
|
-
:Value, :LPBYTE
|
52
|
-
end
|
53
|
-
|
54
|
-
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
|
55
|
-
class CREDENTIAL_OBJECT < FFI::Struct
|
56
|
-
layout :Flags, :DWORD,
|
57
|
-
:Type, :DWORD,
|
58
|
-
:TargetName, :LPTSTR,
|
59
|
-
:Comment, :LPTSTR,
|
60
|
-
:LastWritten, FILETIME,
|
61
|
-
:CredentialBlobSize, :DWORD,
|
62
|
-
:CredentialBlob, :LPBYTE,
|
63
|
-
:Persist, :DWORD,
|
64
|
-
:AttributeCount, :DWORD,
|
65
|
-
:Attributes, CREDENTIAL_ATTRIBUTE,
|
66
|
-
:TargetAlias, :LPTSTR,
|
67
|
-
:UserName, :LPTSTR
|
41
|
+
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
|
42
|
+
class FILETIME < FFI::Struct
|
43
|
+
layout :dwLowDateTime, :DWORD,
|
44
|
+
:dwHighDateTime, :DWORD
|
68
45
|
end
|
69
46
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
include Chef::Mixin::WideString
|
77
|
-
include ReadCred
|
78
|
-
|
79
|
-
def token_details_from_WCM
|
80
|
-
target = target_name
|
81
|
-
|
82
|
-
if target && !target.empty?
|
83
|
-
target_pointer = wstring(target)
|
84
|
-
info_ptr = FFI::MemoryPointer.new(:pointer)
|
85
|
-
cred = CREDENTIAL_OBJECT.new info_ptr
|
86
|
-
cred_result = CredReadW(target_pointer, CRED_TYPE_GENERIC, 0, cred)
|
87
|
-
translated_cred = CREDENTIAL_OBJECT.new(info_ptr.read_pointer)
|
88
|
-
|
89
|
-
target_obj = translated_cred[:TargetName].read_wstring.split("::") if translated_cred[:TargetName].read_wstring
|
90
|
-
cred_blob = translated_cred[:CredentialBlob].get_bytes(0, translated_cred[:CredentialBlobSize]).split("::")
|
91
|
-
|
92
|
-
tokentype = target_obj.select { |obj| obj.include? "tokenType" }
|
93
|
-
user = target_obj.select { |obj| obj.include? "userId" }
|
94
|
-
clientid = target_obj.select { |obj| obj.include? "clientId" }
|
95
|
-
expiry_time = target_obj.select { |obj| obj.include? "expiresOn" }
|
96
|
-
access_token = cred_blob.select { |obj| obj.include? "a:" }
|
97
|
-
refresh_token = cred_blob.select { |obj| obj.include? "r:" }
|
98
|
-
|
99
|
-
credential = {}
|
100
|
-
credential[:tokentype] = tokentype[0].split(":")[1]
|
101
|
-
credential[:user] = user[0].split(":")[1]
|
102
|
-
credential[:token] = access_token[0].split(":")[1]
|
103
|
-
# Todo: refresh_token is not complete currently
|
104
|
-
# target_name method needs to be modified for that
|
105
|
-
credential[:refresh_token] = refresh_token[0].split(":")[1]
|
106
|
-
credential[:clientid] = clientid[0].split(":")[1]
|
107
|
-
credential[:expiry_time] = expiry_time[0].split("expiresOn:")[1].delete("\\")
|
108
|
-
|
109
|
-
# Free memory pointed by info_ptr
|
110
|
-
info_ptr.free
|
111
|
-
else
|
112
|
-
raise "TargetName Not Found"
|
47
|
+
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374790(v=vs.85).aspx
|
48
|
+
class CREDENTIAL_ATTRIBUTE < FFI::Struct
|
49
|
+
layout :Keyword, :LPTSTR,
|
50
|
+
:Flags, :DWORD,
|
51
|
+
:ValueSize, :DWORD,
|
52
|
+
:Value, :LPBYTE
|
113
53
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
54
|
+
|
55
|
+
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
|
56
|
+
class CREDENTIAL_OBJECT < FFI::Struct
|
57
|
+
layout :Flags, :DWORD,
|
58
|
+
:Type, :DWORD,
|
59
|
+
:TargetName, :LPTSTR,
|
60
|
+
:Comment, :LPTSTR,
|
61
|
+
:LastWritten, FILETIME,
|
62
|
+
:CredentialBlobSize, :DWORD,
|
63
|
+
:CredentialBlob, :LPBYTE,
|
64
|
+
:Persist, :DWORD,
|
65
|
+
:AttributeCount, :DWORD,
|
66
|
+
:Attributes, CREDENTIAL_ATTRIBUTE,
|
67
|
+
:TargetAlias, :LPTSTR,
|
68
|
+
:UserName, :LPTSTR
|
69
|
+
end
|
70
|
+
|
71
|
+
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374804(v=vs.85).aspx
|
72
|
+
safe_attach_function :CredReadW, %i{LPCTSTR DWORD DWORD pointer}, :BOOL
|
119
73
|
end
|
120
74
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
75
|
+
module WindowsCredentials
|
76
|
+
|
77
|
+
include Chef::Mixin::WideString
|
78
|
+
include ReadCred
|
79
|
+
|
80
|
+
def token_details_from_WCM
|
81
|
+
target = target_name
|
82
|
+
|
83
|
+
if target && !target.empty?
|
84
|
+
target_pointer = wstring(target)
|
85
|
+
info_ptr = FFI::MemoryPointer.new(:pointer)
|
86
|
+
cred = CREDENTIAL_OBJECT.new info_ptr
|
87
|
+
cred_result = CredReadW(target_pointer, CRED_TYPE_GENERIC, 0, cred)
|
88
|
+
translated_cred = CREDENTIAL_OBJECT.new(info_ptr.read_pointer)
|
89
|
+
|
90
|
+
target_obj = translated_cred[:TargetName].read_wstring.split("::") if translated_cred[:TargetName].read_wstring
|
91
|
+
cred_blob = translated_cred[:CredentialBlob].get_bytes(0, translated_cred[:CredentialBlobSize]).split("::")
|
92
|
+
|
93
|
+
tokentype = target_obj.select { |obj| obj.include? "tokenType" }
|
94
|
+
user = target_obj.select { |obj| obj.include? "userId" }
|
95
|
+
clientid = target_obj.select { |obj| obj.include? "clientId" }
|
96
|
+
expiry_time = target_obj.select { |obj| obj.include? "expiresOn" }
|
97
|
+
access_token = cred_blob.select { |obj| obj.include? "a:" }
|
98
|
+
refresh_token = cred_blob.select { |obj| obj.include? "r:" }
|
99
|
+
|
100
|
+
credential = {}
|
101
|
+
credential[:tokentype] = tokentype[0].split(":")[1]
|
102
|
+
credential[:user] = user[0].split(":")[1]
|
103
|
+
credential[:token] = access_token[0].split(":")[1]
|
104
|
+
# Todo: refresh_token is not complete currently
|
105
|
+
# target_name method needs to be modified for that
|
106
|
+
credential[:refresh_token] = refresh_token[0].split(":")[1]
|
107
|
+
credential[:clientid] = clientid[0].split(":")[1]
|
108
|
+
credential[:expiry_time] = expiry_time[0].split("expiresOn:")[1].delete("\\")
|
109
|
+
|
110
|
+
# Free memory pointed by info_ptr
|
111
|
+
info_ptr.free
|
112
|
+
else
|
113
|
+
raise "TargetName Not Found"
|
114
|
+
end
|
115
|
+
credential
|
116
|
+
rescue => error
|
117
|
+
ui.error("#{error.message}")
|
118
|
+
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
119
|
+
exit
|
120
|
+
end
|
121
|
+
|
122
|
+
# Todo: For getting the complete refreshToken, both credentials (ending with --0-2 and --1-2) have to be read
|
123
|
+
def target_name
|
124
|
+
# cmdkey command is used for accessing windows credential manager.
|
125
|
+
# Multiple credentials get created in windows credential manager for a single Azure account in xplat-cli
|
126
|
+
# One of them is for common tanent id, which can't be used
|
127
|
+
# Others end with --0-x,--1-x,--2-x etc, where x represents the total no. of credentails across which the token is divided
|
128
|
+
# The one ending with --0-x has the complete accessToken in the credentialBlob.
|
129
|
+
# Refresh Token is split across both credentials (ending with --0-x and --1-x).
|
130
|
+
# Xplat splits the credentials based on the number of bytes of the tokens.
|
131
|
+
# Hence the access token is always found in the one which start with --0-
|
132
|
+
# So selecting the credential on the basis of --0-
|
133
|
+
xplat_creds_cmd = Mixlib::ShellOut.new('cmdkey /list | findstr AzureXplatCli | findstr \--0- | findstr -v common')
|
139
134
|
result = xplat_creds_cmd.run_command
|
135
|
+
target_names = []
|
140
136
|
|
141
137
|
if result.stdout.empty?
|
142
|
-
|
138
|
+
Chef::Log.debug("Unable to find a credential with --0- and falling back to looking for any credential.")
|
139
|
+
xplat_creds_cmd = Mixlib::ShellOut.new("cmdkey /list | findstr AzureXplatCli | findstr -v common")
|
140
|
+
result = xplat_creds_cmd.run_command
|
141
|
+
|
142
|
+
if result.stdout.empty?
|
143
|
+
raise "Azure Credentials not found. Please run xplat's 'azure login' command"
|
144
|
+
else
|
145
|
+
target_names = result.stdout.split("\n")
|
146
|
+
end
|
143
147
|
else
|
144
148
|
target_names = result.stdout.split("\n")
|
145
149
|
end
|
146
|
-
else
|
147
|
-
target_names = result.stdout.split("\n")
|
148
|
-
end
|
149
150
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
151
|
+
# If "azure login" is run for multiple users, there will be multiple credentials
|
152
|
+
# Picking up the latest logged in user's credentials
|
153
|
+
latest_target = latest_credential_target target_names
|
154
|
+
latest_target
|
155
|
+
end
|
155
156
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
157
|
+
def latest_credential_target(targets)
|
158
|
+
case targets.size
|
159
|
+
when 0
|
160
|
+
raise "No Target was found for windows credentials"
|
161
|
+
when 1
|
162
|
+
targets.first.gsub("Target:", "").strip
|
163
|
+
else
|
164
|
+
latest_target = ""
|
165
|
+
max_expiry_time = Time.new(0)
|
166
|
+
|
167
|
+
# Using expiry_time to determine the latest credential
|
168
|
+
targets.each do |target|
|
169
|
+
target_obj = target.split("::")
|
170
|
+
expiry_time_obj = target_obj.select { |obj| obj.include? "expiresOn" }
|
171
|
+
expiry_time = expiry_time_obj[0].split("expiresOn:")[1].delete("\\")
|
172
|
+
if Time.parse(expiry_time) > max_expiry_time
|
173
|
+
latest_target = target
|
174
|
+
max_expiry_time = Time.parse(expiry_time)
|
175
|
+
end
|
174
176
|
end
|
175
|
-
end
|
176
177
|
|
177
|
-
|
178
|
+
latest_target.gsub("Target:", "").strip
|
179
|
+
end
|
178
180
|
end
|
179
181
|
end
|
180
|
-
|
182
|
+
end
|
181
183
|
end
|
@@ -28,11 +28,6 @@ class Chef
|
|
28
28
|
## Manager (WCM) usage for authentication credentials storage purpose ##
|
29
29
|
XPLAT_VERSION_WITH_WCM_DEPRECATED ||= "0.10.5".freeze
|
30
30
|
|
31
|
-
if Chef::Platform.windows?
|
32
|
-
require_relative "../../azure/resource_management/windows_credentials"
|
33
|
-
include Azure::ARM::WindowsCredentials
|
34
|
-
end
|
35
|
-
|
36
31
|
def self.included(includer)
|
37
32
|
includer.class_eval do
|
38
33
|
deps do
|
@@ -42,6 +37,11 @@ class Chef
|
|
42
37
|
require "chef/mixin/shell_out"
|
43
38
|
require "time"
|
44
39
|
require "json"
|
40
|
+
|
41
|
+
if Chef::Platform.windows?
|
42
|
+
require_relative "../../azure/resource_management/windows_credentials"
|
43
|
+
include Azure::ARM::WindowsCredentials
|
44
|
+
end
|
45
45
|
end
|
46
46
|
|
47
47
|
option :azure_resource_group_name,
|
data/lib/knife-azure/version.rb
CHANGED