Parse X.509 certificate object into standard format
(self, cert_obj)
| 288 | return extensions |
| 289 | |
| 290 | def _parse_x509_certificate(self, cert_obj): |
| 291 | """Parse X.509 certificate object into standard format""" |
| 292 | try: |
| 293 | # Extract subject and issuer |
| 294 | subject = [] |
| 295 | for attribute in cert_obj.subject: |
| 296 | subject.append([attribute.oid._name, attribute.value]) |
| 297 | |
| 298 | issuer = [] |
| 299 | for attribute in cert_obj.issuer: |
| 300 | issuer.append([attribute.oid._name, attribute.value]) |
| 301 | |
| 302 | # Extract dates (use UTC versions to avoid deprecation warning) |
| 303 | try: |
| 304 | not_before = cert_obj.not_valid_before_utc.strftime('%b %d %H:%M:%S %Y %Z') |
| 305 | not_after = cert_obj.not_valid_after_utc.strftime('%b %d %H:%M:%S %Y %Z') |
| 306 | except AttributeError: |
| 307 | # Fallback for older cryptography versions |
| 308 | not_before = cert_obj.not_valid_before.strftime('%b %d %H:%M:%S %Y %Z') |
| 309 | not_after = cert_obj.not_valid_after.strftime('%b %d %H:%M:%S %Y %Z') |
| 310 | |
| 311 | # Extract extensions |
| 312 | extensions = {} |
| 313 | try: |
| 314 | san_ext = cert_obj.extensions.get_extension_for_oid(x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) |
| 315 | san_list = [] |
| 316 | for name in san_ext.value: |
| 317 | if hasattr(name, 'value'): |
| 318 | san_list.append(('DNS', name.value)) |
| 319 | elif hasattr(name, 'ip_address'): |
| 320 | san_list.append(('IP Address', str(name.ip_address))) |
| 321 | extensions['subjectAltName'] = san_list |
| 322 | except: |
| 323 | extensions['subjectAltName'] = [] |
| 324 | |
| 325 | return { |
| 326 | 'subject': subject, |
| 327 | 'issuer': issuer, |
| 328 | 'version': cert_obj.version.value + 1, # X.509 versions are 0-indexed |
| 329 | 'serialNumber': str(cert_obj.serial_number), |
| 330 | 'notBefore': not_before, |
| 331 | 'notAfter': not_after, |
| 332 | 'subjectAltName': extensions.get('subjectAltName', []) |
| 333 | } |
| 334 | |
| 335 | except Exception as e: |
| 336 | return {'error': str(e)[:MAX_ERROR_LENGTH]} |
| 337 | |
| 338 | def test_http_connectivity(self, ip, port): |
| 339 | """Test HTTP/HTTPS connectivity to a specific IP:port""" |
no outgoing calls
no test coverage detected