blob: 3d9bf5fde3baa27a694cc453664829fcabeef237 [file] [log] [blame]
Derek Beckett1091ed12020-10-19 10:47:16 -07001# Lint as: python2, python3
Paul Stewart32d30332013-10-01 22:39:37 -07002# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import tempfile
7
8from autotest_lib.client.bin import utils
9
10class PEMCertificate(object):
11 """Object enclosing a PEM certificate.
12
13 Uses the "openssl" utility to report various properties of a certificate.
14
15 """
16 OPENSSL_COMMAND = 'openssl'
17 ATTRIBUTE_SUBJECT = 'subject'
18 ATTRIBUTE_FINGERPRINT = 'fingerprint'
19
20 def __init__(self, pem_contents):
21 self._pem_contents = pem_contents
22 self._fingerprint = None
23 self._subject = None
24 self._subject_dict = None
25
26
27 def get_attribute(self, attribute):
28 """Returns the named attribute of the certificate.
29
30 @param attribute string referring to the attribute to retrieve.
31 @return string containing the retrieved attribute value.
32
33 """
34 with tempfile.NamedTemporaryFile() as temp:
35 temp.write(self._pem_contents)
36 temp.flush()
37 output = utils.system_output(
Mattias Nissler3ee6c8e2020-01-22 12:19:39 +010038 '%s x509 -noout -nameopt compat -%s -in %s' %
Paul Stewart32d30332013-10-01 22:39:37 -070039 (self.OPENSSL_COMMAND, attribute, temp.name))
40 # Output is of the form "name=value..."
41 return output.split('=', 1)[1]
42
43
44 @property
45 def fingerprint(self):
46 """Returns the SHA-1 fingerprint of a certificate."""
47 if self._fingerprint is None:
48 self._fingerprint = self.get_attribute(self.ATTRIBUTE_FINGERPRINT)
49 return self._fingerprint
50
51
52 @property
53 def subject(self):
54 """Returns the subject DN of the certificate as a list of name=value"""
55 if self._subject is None:
56 subject = self.get_attribute(self.ATTRIBUTE_SUBJECT)
57 # OpenSSL returns a form of:
58 # " /C=US/ST=CA/L=Mountain View/CN=chromelab..."
59 # but we want to return something like:
60 # [ "C=US", "ST=CA", "L=Mountain View", "CN=chromelab..." ]
61 self._subject = subject.lstrip(' /').split('/')
62 return self._subject
63
64
65 @property
66 def subject_dict(self):
67 """Returns the subject DN of the certificate as a dict of name:value"""
68 if self._subject_dict is None:
69 # Convert the list [ 'A=B', ... ] into a dict { 'A': 'B', ... }
Derek Beckett1091ed12020-10-19 10:47:16 -070070 self._subject_dict = dict([x.split('=', 1) for x in self.subject])
Paul Stewart32d30332013-10-01 22:39:37 -070071 return self._subject_dict