1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# pylint: skip-file
# flake8: noqa
class CAServerCertConfig(OpenShiftCLIConfig):
''' CAServerCertConfig is a DTO for the oc adm ca command '''
def __init__(self, kubeconfig, verbose, ca_options):
super(CAServerCertConfig, self).__init__('ca', None, kubeconfig, ca_options)
self.kubeconfig = kubeconfig
self.verbose = verbose
self._ca = ca_options
class CAServerCert(OpenShiftCLI):
''' Class to wrap the oc adm ca create-server-cert command line'''
def __init__(self,
config,
verbose=False):
''' Constructor for oadm ca '''
super(CAServerCert, self).__init__(None, config.kubeconfig, verbose)
self.config = config
self.verbose = verbose
def get(self):
'''get the current cert file
If a file exists by the same name in the specified location then the cert exists
'''
cert = self.config.config_options['cert']['value']
if cert and os.path.exists(cert):
return open(cert).read()
return None
def create(self):
'''run openshift oc adm ca create-server-cert cmd'''
# Added this here as a safegaurd for stomping on the
# cert and key files if they exist
if self.config.config_options['backup']['value']:
import time
ext = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
date_str = "%s_" + "%s" % ext
if os.path.exists(self.config.config_options['key']['value']):
shutil.copy(self.config.config_options['key']['value'],
date_str % self.config.config_options['key']['value'])
if os.path.exists(self.config.config_options['cert']['value']):
shutil.copy(self.config.config_options['cert']['value'],
date_str % self.config.config_options['cert']['value'])
options = self.config.to_option_list()
cmd = ['ca', 'create-server-cert']
cmd.extend(options)
return self.openshift_cmd(cmd, oadm=True)
def exists(self):
''' check whether the certificate exists and has the clusterIP '''
cert_path = self.config.config_options['cert']['value']
if not os.path.exists(cert_path):
return False
# Would prefer pyopenssl but is not installed.
# When we verify it is, switch this code
# Here is the code to get the subject and the SAN
# openssl x509 -text -noout -certopt \
# no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux \
# -in /etc/origin/master/registry.crt
# Instead of this solution we will use a regex.
cert_names = []
hostnames = self.config.config_options['hostnames']['value'].split(',')
proc = subprocess.Popen(['openssl', 'x509', '-noout', '-text', '-in', cert_path],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x509output, _ = proc.communicate()
if proc.returncode == 0:
regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE)
match = regex.search(x509output) # E501
for entry in re.split(r", *", match.group(1)):
if entry.startswith('DNS') or entry.startswith('IP Address'):
cert_names.append(entry.split(':')[1])
# now that we have cert names let's compare
cert_set = set(cert_names)
hname_set = set(hostnames)
if cert_set.issubset(hname_set) and hname_set.issubset(cert_set):
return True
return False
@staticmethod
def run_ansible(params, check_mode):
'''run the idempotent ansible code'''
config = CAServerCertConfig(params['kubeconfig'],
params['debug'],
{'cert': {'value': params['cert'], 'include': True},
'hostnames': {'value': ','.join(params['hostnames']), 'include': True},
'overwrite': {'value': True, 'include': True},
'key': {'value': params['key'], 'include': True},
'signer_cert': {'value': params['signer_cert'], 'include': True},
'signer_key': {'value': params['signer_key'], 'include': True},
'signer_serial': {'value': params['signer_serial'], 'include': True},
'backup': {'value': params['backup'], 'include': False},
})
server_cert = CAServerCert(config)
state = params['state']
if state == 'present':
########
# Create
########
if not server_cert.exists() or params['force']:
if check_mode:
return {'changed': True,
'msg': "CHECK_MODE: Would have created the certificate.",
'state': state}
api_rval = server_cert.create()
if api_rval['returncode'] != 0:
return {'Failed': True, 'msg': api_rval}
return {'changed': True, 'results': api_rval, 'state': state}
########
# Exists
########
api_rval = server_cert.get()
return {'changed': False, 'results': api_rval, 'state': state}
return {'failed': True,
'msg': 'Unknown state passed. %s' % state}
|