alydns27.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import base64
  4. import urllib
  5. import hmac
  6. import hashlib
  7. import pytz
  8. import datetime
  9. import random
  10. import string
  11. import json
  12. from sys import argv
  13. ACCESS_KEY_ID = '阿里云 access_key_id'
  14. ACCESS_KEY_SECRET = '阿里云 access_key_secret'
  15. class AliDns:
  16. def __init__(self, access_key_id, access_key_secret, domain_name):
  17. self.access_key_id = access_key_id
  18. self.access_key_secret = access_key_secret
  19. self.domain_name = domain_name
  20. @staticmethod
  21. def generate_random_str(length=14):
  22. """
  23. 生成一个指定长度(默认14位)的随机数值,其中
  24. string.digits = "0123456789'
  25. """
  26. str_list = [random.choice(string.digits) for i in range(length)]
  27. random_str = ''.join(str_list)
  28. return random_str
  29. @staticmethod
  30. def percent_encode(str):
  31. res = urllib.quote(str.encode('utf-8'), '')
  32. res = res.replace('+', '%20')
  33. res = res.replace('*', '%2A')
  34. res = res.replace('%7E', '~')
  35. return res
  36. @staticmethod
  37. def utc_time():
  38. """
  39. 请求的时间戳。日期格式按照ISO8601标准表示,
  40. 并需要使用UTC时间。格式为YYYY-MM-DDThh:mm:ssZ
  41. 例如,2015-01-09T12:00:00Z(为UTC时间2015年1月9日12点0分0秒)
  42. :return:
  43. """
  44. utc_tz = pytz.timezone('UTC')
  45. time = datetime.datetime.now(tz=utc_tz).strftime('%Y-%m-%dT%H:%M:%SZ')
  46. return time
  47. @staticmethod
  48. def sign_string(url_param):
  49. percent_encode = AliDns.percent_encode
  50. sorted_url_param = sorted(url_param.items(), key=lambda x: x[0])
  51. can_string = ''
  52. for k, v in sorted_url_param:
  53. can_string += '&' + percent_encode(k) + '=' + percent_encode(v)
  54. string_to_sign = 'GET' + '&' + '%2F' + '&' + percent_encode(can_string[1:])
  55. return string_to_sign
  56. @staticmethod
  57. def access_url(url):
  58. f = urllib.urlopen(url)
  59. result = f.read().decode('utf-8')
  60. print(result)
  61. return json.loads(result)
  62. def visit_url(self, action_param):
  63. common_param = {
  64. 'Format': 'json',
  65. 'Version': '2015-01-09',
  66. 'AccessKeyId': self.access_key_id,
  67. 'SignatureMethod': 'HMAC-SHA1',
  68. 'Timestamp': AliDns.utc_time(),
  69. 'SignatureVersion': '1.0',
  70. 'SignatureNonce': AliDns.generate_random_str(),
  71. 'DomainName': self.domain_name,
  72. }
  73. url_param = dict(common_param, **action_param)
  74. string_to_sign = AliDns.sign_string(url_param)
  75. hash_bytes = self.access_key_secret + "&"
  76. h = hmac.new(hash_bytes, string_to_sign, digestmod=hashlib.sha1)
  77. signature = base64.encodestring(h.digest()).strip()
  78. url_param.setdefault('Signature', signature)
  79. url = 'https://alidns.aliyuncs.com/?' + urllib.urlencode(url_param)
  80. print(url)
  81. return AliDns.access_url(url)
  82. # 显示所有
  83. def describe_domain_records(self):
  84. """
  85. 最多只能查询此域名的 500条解析记录
  86. PageNumber 当前页数,起始值为1,默认为1
  87. PageSize 分页查询时设置的每页行数,最大值500,默认为20
  88. :return:
  89. """
  90. action_param = dict(
  91. Action='DescribeDomainRecords',
  92. PageNumber='1',
  93. PageSize='500',
  94. )
  95. result = self.visit_url(action_param)
  96. return result
  97. # 增加解析
  98. def add_domain_record(self, type, rr, value):
  99. action_param = dict(
  100. Action='AddDomainRecord',
  101. RR=rr,
  102. Type=type,
  103. Value=value,
  104. )
  105. result = self.visit_url(action_param)
  106. return result
  107. # 修改解析
  108. def update_domain_record(self, id, type, rr, value):
  109. action_param = dict(
  110. Action="UpdateDomainRecord",
  111. RecordId=id,
  112. RR=rr,
  113. Type=type,
  114. Value=value,
  115. )
  116. result = self.visit_url(action_param)
  117. return result
  118. # 删除解析
  119. def delete_domain_record(self, id):
  120. action_param = dict(
  121. Action="DeleteDomainRecord",
  122. RecordId=id,
  123. )
  124. result = self.visit_url(action_param)
  125. return result
  126. if __name__ == '__main__':
  127. # domain = AliDns(ACCESS_KEY_ID, ACCESS_KEY_SECRET, 'wuqianlin.cn')
  128. # domain.describe_domain_records()
  129. # 增加记录
  130. # domain.add_domain_record("TXT", "test", "test")
  131. # 修改解析
  132. # domain.update_domain_record('4011918010876928', 'TXT', 'test', 'text2')
  133. # 删除解析记录
  134. # data = domain.describe_domain_records()
  135. # record_list = data["DomainRecords"]["Record"]
  136. # for item in record_list:
  137. # if 'test' in item['RR']:
  138. # domain.delete_domain_record(item['RecordId'])
  139. print(argv)
  140. file_name, certbot_domain, acme_challenge, certbot_validation = argv
  141. domain = AliDns(ACCESS_KEY_ID, ACCESS_KEY_SECRET, certbot_domain)
  142. data = domain.describe_domain_records()
  143. record_list = data["DomainRecords"]["Record"]
  144. if record_list:
  145. for item in record_list:
  146. if acme_challenge == item['RR']:
  147. domain.delete_domain_record(item['RecordId'])
  148. domain.add_domain_record("TXT", acme_challenge, certbot_validation)