OracleAction.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python3
  2. # -*- encoding: utf-8 -*-
  3. # Author: MoeClub.org
  4. # pip3 install rsa
  5. # python3 OracleAction.py -c "config/defaults.json" -i "ocid1.instance." -a "action" -n "name"
  6. # defaults.json
  7. # {
  8. # "compartmentId": "ocid1.tenancy...",
  9. # "userId": "ocid1.user...",
  10. # "URL": "https://iaas.xxxxx.oraclecloud.com/20160918/",
  11. # "certFinger": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
  12. # "certKey": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
  13. # }
  14. import hashlib
  15. import datetime
  16. import base64
  17. import json
  18. import rsa
  19. from urllib import request, error, parse
  20. class oracle:
  21. @staticmethod
  22. def http(url, method, headers=None, data=None, coding='utf-8'):
  23. if not headers:
  24. headers = {}
  25. if data is not None:
  26. if isinstance(data, (dict, list)):
  27. data = json.dumps(data)
  28. if 'content-length' not in [str(item).lower() for item in list(headers.keys())]:
  29. headers['Content-Length'] = str(len(data))
  30. data = str(data).encode(coding)
  31. url_obj = request.Request(url, method=method, data=data, headers=headers)
  32. try:
  33. res_obj = request.urlopen(url_obj)
  34. except error.HTTPError as err:
  35. res_obj = err
  36. return res_obj
  37. @staticmethod
  38. def header(keyID, privateKey, reqURL, reqMethod, body=None, algorithm="rsa-sha256"):
  39. sign_list = []
  40. url_parse = parse.urlparse(reqURL)
  41. _header_field = ["(request-target)", "date", "host"]
  42. _header = {
  43. 'host': str(url_parse.netloc),
  44. 'user-agent': 'oracle-api/1.0',
  45. 'date': str(datetime.datetime.utcnow().strftime("%a, %d %h %Y %H:%M:%S GMT")),
  46. 'accept': '*/*',
  47. 'accept-encoding': '',
  48. }
  49. sign_list.append(str("(request-target): {} {}").format(str(reqMethod).lower(), parse.quote_plus(str("{}{}").format(url_parse.path, str("?{}").format(url_parse.query) if url_parse.query else ""), safe="/?=&~")))
  50. if body is not None:
  51. if isinstance(body, (dict, list)):
  52. _body = json.dumps(body)
  53. else:
  54. _body = body
  55. _header_field += ["content-length", "content-type", "x-content-sha256"]
  56. _header['content-type'] = 'application/json'
  57. _header['content-length'] = str(len(_body))
  58. _header['x-content-sha256'] = str(base64.b64encode(hashlib.sha256(_body.encode("utf-8")).digest()).decode("utf-8"))
  59. sign_list += [str("{}: {}").format(item, _header[item]) for item in _header_field if "target" not in item]
  60. _signature = base64.b64encode(rsa.sign(str(str("\n").join(sign_list)).encode("utf-8"), rsa.PrivateKey.load_pkcs1(privateKey if isinstance(privateKey, bytes) else str(privateKey).strip().encode("utf-8")), str(algorithm).split("-", 1)[-1].upper().replace("SHA", "SHA-"))).decode("utf-8")
  61. _header['authorization'] = str('Signature keyId="{}",algorithm="{}",signature="{}",headers="{}"').format(keyID, algorithm, _signature, str(" ").join(_header_field))
  62. return _header
  63. @staticmethod
  64. def load_Key(file, BIN=False, coding='utf-8'):
  65. fd = open(file, 'r', encoding=coding)
  66. data = fd.read()
  67. fd.close()
  68. return str(data).strip().encode(coding) if BIN else str(data).strip()
  69. @staticmethod
  70. def load_Config(file, coding='utf-8'):
  71. fd = open(file, 'r', encoding=coding)
  72. data = fd.read()
  73. fd.close()
  74. return json.loads(data, encoding=coding)
  75. @classmethod
  76. def api(cls, method, url, keyID, privateKey, data=None):
  77. method_allow = ["GET", "HEAD", "DELETE", "PUT", "POST"]
  78. method = str(method).strip().upper()
  79. if method not in method_allow:
  80. raise Exception(str("Method Not Allow [{}]").format(method))
  81. if len(str(keyID).split("/")) != 3:
  82. raise Exception(str('Invalid "keyID"'))
  83. if method in ["PUT", "POST"] and data is None:
  84. data = ""
  85. privateKey = privateKey if isinstance(privateKey, bytes) else str(privateKey).strip().encode("utf-8")
  86. headers = cls.header(keyID, privateKey, url, method, data)
  87. return cls.http(url, method, headers, data)
  88. class action:
  89. def __init__(self, apiDict, instancesId=None):
  90. self.apiDict = apiDict
  91. self.privateKey = apiDict["certKey"]
  92. self.instancesId = instancesId
  93. self.apiKey = "/".join([apiDict["compartmentId"], apiDict["userId"], apiDict["certFinger"]])
  94. self.VNIC = None
  95. self.PRIVATE = None
  96. def getPrivateIP(self):
  97. if not self.instancesId:
  98. print("Require instancesId.")
  99. exit(1)
  100. url = self.apiDict["URL"] + "vnicAttachments?instanceId=" + self.instancesId + "&compartmentId=" + self.apiDict["compartmentId"]
  101. response = oracle.api("GET", url, keyID=self.apiKey, privateKey=self.privateKey)
  102. response_vnic = json.loads(response.read().decode())
  103. if response_vnic:
  104. self.VNIC = response_vnic[0]
  105. if not self.VNIC:
  106. print("Not Found VNIC.")
  107. exit(1)
  108. url = self.apiDict["URL"] + "privateIps?vnicId=" + self.VNIC["vnicId"]
  109. response = oracle.api("GET", url, keyID=self.apiKey, privateKey=self.privateKey)
  110. response_private = json.loads(response.read().decode())
  111. if response_private:
  112. for privateIp in response_private:
  113. if privateIp["isPrimary"]:
  114. self.PRIVATE = response_private[0]
  115. break
  116. if not self.PRIVATE:
  117. print("Not Found Private IP Address.")
  118. exit(1)
  119. def getPublicIP(self):
  120. url = self.apiDict["URL"] + "publicIps/actions/getByPrivateIpId"
  121. BodyOne = json.dumps({"privateIpId": self.PRIVATE["id"]}, ensure_ascii=False)
  122. response = oracle.api("POST", url, keyID=self.apiKey, privateKey=self.privateKey, data=BodyOne)
  123. if response.code >= 200 and response.code < 400:
  124. response_public = json.loads(response.read().decode())
  125. return response_public
  126. elif response.code >= 400 and response.code < 500:
  127. return None
  128. else:
  129. print("Server Error. [%s]" % response.code)
  130. exit(1)
  131. def delPublicIP(self, publicIp):
  132. url = self.apiDict["URL"] + "publicIps/" + publicIp
  133. oracle.api("DELETE", url, keyID=self.apiKey, privateKey=self.privateKey)
  134. def newPublicIP(self):
  135. bodyTwo = {
  136. "lifetime": "EPHEMERAL",
  137. "compartmentId": self.apiDict["compartmentId"],
  138. "privateIpId": self.PRIVATE["id"],
  139. }
  140. url = self.apiDict["URL"] + "publicIps"
  141. BodyTwo = json.dumps(bodyTwo, ensure_ascii=False)
  142. response = oracle.api("POST", url, keyID=self.apiKey, privateKey=self.privateKey, data=BodyTwo)
  143. NewPublic = json.loads(response.read().decode())
  144. print("PublicIP:", NewPublic["ipAddress"])
  145. return NewPublic
  146. def showPublicIP(self):
  147. self.getPrivateIP()
  148. PUBLIC = self.getPublicIP()
  149. publicIp = "NULL"
  150. if PUBLIC:
  151. publicIp = PUBLIC["ipAddress"]
  152. print("PublicIP: %s" % publicIp)
  153. return PUBLIC
  154. def changePubilcIP(self):
  155. self.getPrivateIP()
  156. PUBLIC = self.getPublicIP()
  157. publicIp = "NULL"
  158. if PUBLIC:
  159. publicIp = PUBLIC["ipAddress"]
  160. self.delPublicIP(PUBLIC["id"])
  161. print("PublicIP[*]: %s" % publicIp)
  162. PUBLIC = self.newPublicIP()
  163. return PUBLIC
  164. def rename(self, newName, DisableMonitoring=True):
  165. if not self.instancesId:
  166. print("Require instancesId.")
  167. exit(1)
  168. setName = str(newName).strip()
  169. if not setName:
  170. print("Name Invalid.")
  171. exit(1)
  172. body = {"displayName": setName, "agentConfig": {"isMonitoringDisabled": DisableMonitoring}}
  173. url = self.apiDict["URL"] + "instances/" + self.instancesId
  174. Body = json.dumps(body, ensure_ascii=False)
  175. response = oracle.api("PUT", url, keyID=self.apiKey, privateKey=self.privateKey, data=Body)
  176. response_json = json.loads(response.read().decode())
  177. response_json["status_code"] = str(response.code)
  178. print(json.dumps(response_json, indent=4))
  179. if __name__ == "__main__":
  180. def Exit(code=0, msg=None):
  181. if msg:
  182. print(msg)
  183. exit(code)
  184. import argparse
  185. parser = argparse.ArgumentParser()
  186. parser.add_argument('-c', type=str, default="", help="Config path")
  187. parser.add_argument('-i', type=str, default="", help="Instances Id")
  188. parser.add_argument('-n', type=str, default="", help="New Instances Name")
  189. parser.add_argument('-a', type=str, default="", help="Action [show, change, rename]")
  190. args = parser.parse_args()
  191. configPath = str(args.c).strip()
  192. configAction = str(args.a).strip().lower()
  193. configInstancesId = str(args.i).strip()
  194. configInstancesName = str(args.n).strip()
  195. configActionList = ["show", "change", "rename"]
  196. if not configPath:
  197. Exit(1, "Require Config Path.")
  198. if not configAction or configAction not in configActionList:
  199. Exit(1, "Invalid action.")
  200. if not configInstancesId:
  201. Exit(1, "Require Instances Id.")
  202. if configAction == "show":
  203. Action = action(oracle.load_Config(configPath), configInstancesId)
  204. Action.showPublicIP()
  205. elif configAction == "change":
  206. Action = action(oracle.load_Config(configPath), configInstancesId)
  207. Action.changePubilcIP()
  208. elif configAction == "rename":
  209. if not configInstancesName:
  210. Exit(1, "Require Instances Name.")
  211. Action = action(oracle.load_Config(configPath), configInstancesId)
  212. Action.rename(configInstancesName)
  213. Exit(0)