阿里云证书过期时间监测
我只监控了slb下使用的ssl证书的过期时间,然后以prometheus能读取的metrics格式供prometheus采集。因为我们是prometheus-operator,通过helm发布的时候添加一个servicemonitor即可。想要监控所有证书调用阿里云证书系列产品api即可。
1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 4 ''' 5 Date: 2019-11-26 6 Blog: www.cnblogs.com/qinghe123 7 ''' 8 9 import re,sys 10 import base64 11 import json 12 import time 13 from datetime import datetime 14 import hmac 15 import urllib 16 17 import argparse 18 from pprint import pprint 19 from urllib import request 20 import uuid 21 import os 22 from sys import exit 23 24 import dateutil.parser 25 from prometheus_client import start_http_server, Summary 26 from prometheus_client.core import GaugeMetricFamily, REGISTRY 27 from hashlib import sha1 28 29 DEBUG = int(os.environ.get('DEBUG', '0')) 30 #DEBUG = True 31 aliyun_access_key = os.environ.get('AccessKeyID',None) 32 aliyun_access_secret = os.environ.get('AccessKeySecret',None) 33 34 COLLECTION_TIME = Summary('request_aliyun_api_seconds', 'Time spent to collect metrics from aliyun') 35 36 37 class AliyunSignature(): 38 """获取阿里云签名和数据""" 39 Timestamp = datetime.utcnow().isoformat() 40 SignatureNonce = str(uuid.uuid1()) 41 42 def __init__(self,config,Id=None,key=None): 43 ''' 44 this is aliyun api auth single, now, any api request parame to main 45 ''' 46 assert config['Action'], "Value error" 47 48 self.config = config 49 self.url = 'http://slb.aliyuncs.com' 50 self.id = Id 51 self.Key = key 52 self.__data = dict({ 53 "AccessKeyId": self.id, 54 "SignatureMethod": 'HMAC-SHA1', 55 "SignatureVersion": "1.0", 56 "SignatureNonce": self.SignatureNonce, 57 "Timestamp": self.Timestamp, 58 "Version": "2014-05-15", 59 "Format": "JSON" 60 }, **self.config) 61 62 @classmethod 63 def reload(cls, body): 64 cls.Timestamp = datetime.utcnow().isoformat() 65 cls.SignatureNonce = str(uuid.uuid1()) 66 return cls(config=body) 67 68 @property 69 def data(self): 70 return self.__data 71 72 @data.setter 73 def data(self, value): 74 if self.__data: 75 raise AssertionError("not allow opeartion") 76 self.__data = value 77 78 @staticmethod 79 def percent_encode(encodeStr): 80 if isinstance(encodeStr, bytes): 81 encodeStr = encodeStr.decode(sys.stdin.encoding) 82 res = urllib.parse.quote_plus(encodeStr.encode('utf-8'), '') 83 res = res.replace('+', '%20').replace('*', '%2A').replace('%7E', '~') 84 return res 85 86 def auth(self): 87 base = sorted(self.data.items(), key=lambda data: data[0]) 88 canstring = '' 89 for k, v in base: 90 canstring += '&' + self.percent_encode(k) + '=' + self.percent_encode(v) 91 self.Key += "&" 92 data = 'GET&%2F&' + self.percent_encode(canstring[1:]) 93 self._salt(data) 94 return self.data 95 96 def _salt(self, data): 97 result = data.encode(encoding='utf-8') 98 uri = hmac.new(self.Key.encode("utf-8"), result, sha1).digest() 99 key = base64.b64encode(uri).strip() 100 self.data['Signature'] = key 101 return self.data 102 103 def generate_url(self): 104 parameters = self.auth() 105 url = self.url + '/?' + urllib.parse.urlencode(parameters) 106 return url 107 108 def do_action(self): 109 url = self.generate_url() 110 request = urllib.request.Request(url) 111 try: 112 conn = urllib.request.urlopen(request) 113 response = conn.read().decode() 114 except urllib.error.HTTPError as e: 115 print(e.read().strip()) 116 raise SystemExit(e) 117 118 try: 119 res = json.loads(response) 120 except ValueError as e: 121 raise SystemExit(e) 122 return res 123 124 class AliyunResourceConllector(): 125 """prometheus metrics""" 126 def __init__(self,product=None): 127 self.prodct = product 128 129 def format_metric_name(self): 130 return 'aliyun_%s' % self.prodct 131 132 def collect(self): 133 config = { 134 "Action": "DescribeServerCertificates", 135 "RegionId": "cn-shanghai" 136 } 137 auth_obj = AliyunSignature(config=config, Id=aliyun_access_key, key=aliyun_access_secret) 138 auth_obj.reload(config) 139 response = auth_obj.do_action().get('ServerCertificates').get('ServerCertificate') 140 141 sub_metric_list = ["CreateTime","ExpireTime"] 142 for instance in response: 143 for sub_metric in sub_metric_list: 144 snake_case = re.sub('([A-Z])', '_\\1', sub_metric).lower() 145 date_time = self.getDateTimeFromISO8601String(instance.get(sub_metric)) 146 uninx_time = int(time.mktime(date_time.timetuple())) 147 gauge = GaugeMetricFamily(self.format_metric_name() + snake_case, 'aliyun ssl certificate',labels=['domainname','sslname']) 148 gauge.add_metric([instance.get('CommonName'),instance.get('ServerCertificateName')],uninx_time) 149 yield gauge 150 151 def _info(self,obj): 152 config = { 153 "Action": "DescribeServerCertificates", 154 "RegionId": "cn-shanghai" 155 } 156 157 response = obj.do_action().get('ServerCertificates').get('ServerCertificate') 158 obj.reload(config) 159 return response 160 161 @staticmethod 162 def getDateTimeFromISO8601String(s): 163 d = dateutil.parser.parse(s) 164 return d 165 166 def parse_args(): 167 parser = argparse.ArgumentParser( 168 description='jenkins exporter args jenkins address and port' 169 ) 170 parser.add_argument( 171 '-k', '--keyid', 172 metavar='key', 173 required=False, 174 help='aliyun access key Id', 175 default=os.environ.get('AccessKeyID', 'LTAIdmc9wg0MxRD7') 176 ) 177 parser.add_argument( 178 '-s', '--secret', 179 metavar='secret', 180 required=False, 181 help='aliyun access key secret', 182 default=os.environ.get('AccessKeySecret') 183 ) 184 parser.add_argument( 185 '-p', 186 metavar='project', 187 required=False, 188 help='aliyun project type(ecs,slb,ssl...)', 189 default=os.environ.get('PROJECT_TYPE','ssl') 190 ) 191 parser.add_argument( 192 '-r', 193 metavar='RegionId', 194 required=False, 195 help='aliyun resource region(cn-hangzhou,cn-shanghai...)', 196 default=os.environ.get('REGION_ID','cn-shanghai') 197 ) 198 199 return parser.parse_args() 200 201 if __name__ == "__main__": 202 config = { 203 "Action": "DescribeServerCertificates", 204 "RegionId": "cn-shanghai" 205 } 206 collector = AliyunResourceConllector('ssl') 207 REGISTRY.register(collector) 208 print("Polling . Serving at port: 8000") 209 start_http_server(8000) 210 while True: 211 time.sleep(1)