1 #!@PYTHON@ -tt
2 # -*- coding: utf-8 -*-
3
4 import sys
5 import atexit
6 sys.path.append("@FENCEAGENTSLIBDIR@")
7 from fencing import *
8 from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, EC_INVALID_PRIVILEGES, run_delay
9 import requests
10 import ast
11 import urllib3
12 import json
13 import logging
14
15 from requests.exceptions import ConnectionError
16
17
18 ###################################################################################
19 # Inner functions
20
21
22 def authorize_and_get_cookie(skala_ip, login, password, options):
23 URL0 = proto + str(skala_ip) + '/api/0/auth'
24 cred = {
25 "login" : str(login),
26 "password" : str(password)
27 }
28
29 try:
30 with requests.Session() as session:
31 session.post(url=URL0, data=cred, verify=ssl_verify)
32 cookie = session.cookies.get_dict()
33 except:
34 logging.exception('Exception occured.')
35 fail(EC_LOGIN_DENIED)
36 if 'api_token' in cookie:
37 return cookie
38 else:
39 fail(EC_LOGIN_DENIED)
40
41
42 def logout(skala_ip):
43 URL1 = proto + str(skala_ip) + '/api/0/logout'
44
45 try:
46 with requests.Session() as session:
47 session.post(url=URL1, verify=ssl_verify, cookies=cookie)
48 except:
49 ## Logout; we do not care about result as we will end in any case
50 pass
51
52
53 def get_vm_id(skala_ip, uuid, options, cookie):
54 URL2 = proto + str(skala_ip) + '/api/0/vm'
55 parameters = {
56 "uuid": str(uuid)
57 }
58
59 vm_info = requests.get(url=URL2, verify=ssl_verify, params=parameters, cookies=cookie)
60 jvm_info = vm_info.json()
61 if jvm_info["vm_list"]["items"] == []:
62 raise NameError('Can not find VM by uuid.')
63 logging.debug("VM_INFO:\n{}".format(json.dumps(vm_info.json(), indent=4, sort_keys=True)))
64 return jvm_info["vm_list"]["items"][0]["vm_id"]
65
66
67 def vm_task(skala_ip, vm_id, command, options, cookie):
68
69 # command(str) – Command for vm: ‘vm_start’, ‘vm_stop’, ‘vm_restart’,
70 # ‘vm_suspend’, ‘vm_resume’, ‘vm_pause’, ‘vm_reset’
71 # main_request_id(TaskId) – Parent task id
72 # graceful(bool) – vm_stop command parameter, graceful or not, default
73 # false - *args[0]
74 # force(bool) – vm_stop command parameter, force stop or not, default
75 # false - *args[1]
76
77 if "--graceful" in options:
78 graceful = True
79 else:
80 graceful = False
81 if "--force" in options:
82 force = True
83 else:
84 force = False
85
86 URL3 = proto + str(skala_ip) + '/api/0/vm/' + str(vm_id) + '/task'
87
88 logging.debug("vm_task skala_ip: " + str(skala_ip))
89 logging.debug("vm_task vm_id: " + str(vm_id))
90 logging.debug("vm_task command: " + str(command))
91 logging.debug("vm_task cookie: " + str(cookie))
92
93
94 def checking(vm_id, command, graceful, force):
95 firstcondition = type(vm_id) is int
96 secondcondition = command in ['vm_start', 'vm_stop', 'vm_restart', 'vm_suspend', 'vm_resume', 'vm_pause', 'vm_reset']
97 thirdcondition = type(graceful) is bool
98 fourthcondition = type(force) is bool
99 return firstcondition * secondcondition * thirdcondition * fourthcondition
100
101 if not checking(vm_id, command, graceful, force):
102 print('Wrong parameters! \n'
103 'command(str) – Command for vm: ‘vm_start’, ‘vm_stop’, \n'
104 '‘vm_restart’,‘vm_suspend’, ‘vm_resume’, ‘vm_pause’, ‘vm_reset’ \n'
105 'graceful(bool) – vm_stop command parameter, graceful or not, default false \n'
106 'force(bool) – vm_stop command parameter, force stop or not, default false \n'
107 )
108 else:
109 parameters = {
110 "command": command,
111 "graceful": graceful,
112 "force": force
113 }
114
115 with requests.Session() as session:
|
(1) Event Sigma main event: |
The `timeout` attribute is undefined or is set to `None`, which disables the timeouts on streaming connections. This makes it easier for an attacker to launch a Denial-of-Service (DoS) attack. Other problems can include large numbers of inactive connections that aren't being closed and running out of ephemeral ports. |
|
(2) Event remediation: |
Explicitly set the `timeout` attribute to a value greater than 0. |
116 response = session.post(url=URL3, params=parameters, verify=ssl_verify, cookies=cookie)
117 if response.status_code != 200:
118 raise Exception('Invalid response code from server: {}.'.format(response.status_code))
119 return
120
121 ######################################################################################
122
123 def get_power_status(conn, options):
124 state = {"RUNNING": "on", "PAUSED": "on", "STOPPED": "off", "SUSPENDED": "off", "ERROR": "off", "DELETED": "off",
125 "CREATING": "off", "FAILED_TO_CREATE": "off", "NODE_OFFLINE": "off", "STARTING": "off", "STOPPING": "on"}
126
127 URL4 = proto + options["--ip"] + '/api/0/vm/'
128 parameters = {
129 "uuid": str(options["--plug"])
130 }
131
132 vm_info = requests.get(url=URL4, params=parameters, verify=ssl_verify, cookies=cookie)
133 jvm_info = vm_info.json()
134 if jvm_info["vm_list"]["items"] == []:
135 raise NameError('Can not find VM by uuid.')
136 logging.debug("VM_INFO:\n{}".format(json.dumps(vm_info.json(), indent=4, sort_keys=True)))
137 status_v = jvm_info["vm_list"]["items"][0]["status"]
138 if status_v not in state:
139 raise Exception('Unknown VM state: {}.'.format(status_v))
140 return state[status_v]
141
142
143 def set_power_status(conn, options):
144 action = {
145 "on" : "vm_start",
146 "reboot": "vm_restart",
147 "off" : "vm_stop"
148 }
149
150 vm_id_v = get_vm_id(options["--ip"], options["--plug"], options, cookie)
151 vm_task(options["--ip"], vm_id_v, action[options["--action"]], options, cookie)
152 return
153
154
155 def get_list(conn, options):
156 outlets = {}
157 URL5 = proto + options["--ip"] + '/api/0/vm'
158
159 vm_info = requests.get(url=URL5, verify=ssl_verify, cookies=cookie)
160 jvm_info = vm_info.json()
161 list_jvm = jvm_info["vm_list"]["items"]
162 for elem in list_jvm:
163 outlets[elem["name"]] = (elem["uuid"], None)
164 return outlets
165
166
167 def define_new_opts():
168 all_opt["graceful"] = {
169 "getopt" : "",
170 "longopt" : "graceful",
171 "help" : "--graceful vm_stop command parameter, graceful stop or not, default false",
172 "required" : "0",
173 "shortdesc" : "vm_stop command parameter, graceful stop or not, default false",
174 "order" : 1}
175
176 all_opt["force"] = {
177 "getopt" : "",
178 "longopt" : "force",
179 "help" : "--force vm_stop command parameter, force stop or not, default false",
180 "required" : "0",
181 "shortdesc" : "vm_stop command parameter, force stop or not, default false",
182 "order" : 1}
183
184
185 def main():
186 global cookie, proto, ssl_verify
187 define_new_opts()
188 device_opt = ["ipaddr", "login", "passwd", "port", "web", "ssl", "verbose", "graceful", "force"]
189
190 atexit.register(atexit_handler)
191 options = check_input(device_opt, process_input(device_opt))
192
193 docs = {}
194 docs["shortdesc"] = "Skala-R Fence agent"
195 docs["longdesc"] = "fence_skalar is a Power Fencing agent for Skala-R."
196 docs["vendorurl"] = "https://www.skala-r.ru/"
197 show_docs(options, docs)
198 options["eol"] = "\r"
199
200 run_delay(options)
201
202 proto = "https://"
203 if "--ssl-secure" in options:
204 ssl_verify = True
205 elif "--ssl-insecure" in options:
206 ssl_verify = False
207 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
208 else:
209 proto = "http://"
210 ssl_verify = False
211 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
212
213 cookie = authorize_and_get_cookie(options["--ip"], options["--username"], options["--password"], options)
214 atexit.register(logout, options["--ip"])
215
216 logging.debug("OPTIONS: " + str(options) + "\n")
217
218 try:
219 result = fence_action(None, options, set_power_status, get_power_status, get_list)
220 sys.exit(result)
221 except Exception:
222 logging.exception('Exception occured.')
223 fail(EC_STATUS)
224
225 if __name__ == "__main__":
226 main()
227