mirror of
https://github.com/xcat2/confluent.git
synced 2026-01-11 10:32:31 +00:00
Implement method to sign BMC certificates
This commit is contained in:
@@ -296,7 +296,7 @@ def create_certificate(keyout=None, certout=None, csrfile=None, subj=None, san=N
|
||||
certout = tlsmateriallocation.get('certs', [None])[0]
|
||||
if not certout:
|
||||
certout = tlsmateriallocation.get('bundles', [None])[0]
|
||||
if not keyout or not certout:
|
||||
if (not keyout and not csrfile) or not certout:
|
||||
raise Exception('Unable to locate TLS certificate path automatically')
|
||||
assure_tls_ca()
|
||||
if not subj:
|
||||
|
||||
@@ -300,6 +300,20 @@ def _init_core():
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
},
|
||||
'certificate': {
|
||||
'sign': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
'generate_csr': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
'install': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
},
|
||||
'certificate_authorities': PluginCollection({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
|
||||
@@ -519,6 +519,8 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
|
||||
return InputAlertDestination(path, nodes, inputdata, multinode)
|
||||
elif len(path) == 3 and path[:3] == ['configuration', 'management_controller', 'certificate_authorities'] and operation not in ('retrieve', 'delete'):
|
||||
return InputCertificateAuthority(path, nodes, inputdata)
|
||||
elif len(path) == 4 and path[:4] == ['configuration', 'management_controller', 'certificate', 'sign'] and operation not in ('retrieve', 'delete'):
|
||||
return InputSigningParameters(path, inputdata, nodes, configmanager)
|
||||
elif path == ['identify'] and operation != 'retrieve':
|
||||
return InputIdentifyMessage(path, nodes, inputdata)
|
||||
elif path == ['events', 'hardware', 'decode']:
|
||||
@@ -956,6 +958,20 @@ class ConfluentInputMessage(ConfluentMessage):
|
||||
def is_valid_key(self, key):
|
||||
return key in self.valid_values
|
||||
|
||||
class InputSigningParameters(InputConfigChangeSet):
|
||||
|
||||
def get_days(self, node):
|
||||
attribs = self.get_attributes(node)
|
||||
return int(attribs['days'])
|
||||
|
||||
def get_added_san(self, node):
|
||||
attribs = self.get_attributes(node)
|
||||
addsans = []
|
||||
for subj in attribs.get('added_san', '').split(','):
|
||||
if subj:
|
||||
addsans.append(subj.strip())
|
||||
return addsans
|
||||
|
||||
|
||||
class InputCertificateAuthority(ConfluentInputMessage):
|
||||
keyname = 'pem'
|
||||
|
||||
@@ -20,6 +20,7 @@ import confluent.messages as msg
|
||||
import confluent.util as util
|
||||
import copy
|
||||
import errno
|
||||
from confluent import certutil
|
||||
import eventlet
|
||||
import eventlet.event
|
||||
import eventlet.green.threading as threading
|
||||
@@ -37,6 +38,7 @@ ipmicommand = eventlet.import_patched('pyghmi.redfish.command')
|
||||
import socket
|
||||
import ssl
|
||||
import traceback
|
||||
import tempfile
|
||||
|
||||
if not hasattr(ssl, 'SSLEOFError'):
|
||||
ssl.SSLEOFError = None
|
||||
@@ -532,6 +534,8 @@ class IpmiHandler(object):
|
||||
return self.handle_alerts()
|
||||
elif self.element[1:3] == ['management_controller', 'certificate_authorities']:
|
||||
return self.handle_cert_authorities()
|
||||
elif self.element[1:3] == ['management_controller', 'certificate']:
|
||||
return self.handle_certificate()
|
||||
elif self.element[1:3] == ['management_controller', 'users']:
|
||||
return self.handle_users()
|
||||
elif self.element[1:3] == ['management_controller', 'net_interfaces']:
|
||||
@@ -582,6 +586,26 @@ class IpmiHandler(object):
|
||||
self.pyghmi_event_to_confluent(event)
|
||||
self.output.put(msg.EventCollection((event,), name=self.node))
|
||||
|
||||
def handle_certificate(self):
|
||||
self.element = self.element[3:]
|
||||
if len(self.element) != 1:
|
||||
raise Exception('Not implemented')
|
||||
if self.element[0] == 'sign' and self.op == 'update':
|
||||
csr = self.ipmicmd.get_bmc_csr()
|
||||
subj, san = util.get_bmc_subject_san(self.cfm, self.node, self.inputdata.get_added_san(self.node))
|
||||
with tempfile.NamedTemporaryFile() as tmpfile:
|
||||
tmpfile.write(csr.encode())
|
||||
tmpfile.flush()
|
||||
certfile = tempfile.NamedTemporaryFile(delete=False)
|
||||
certname = certfile.name
|
||||
certfile.close()
|
||||
certutil.create_certificate(None, certname, tmpfile.name, subj, san, backdate=False,
|
||||
days=self.inputdata.get_days(self.node))
|
||||
with open(certname, 'rb') as certf:
|
||||
cert = certf.read()
|
||||
os.unlink(certname)
|
||||
self.ipmicmd.install_bmc_certificate(cert)
|
||||
|
||||
def handle_cert_authorities(self):
|
||||
if len(self.element) == 3:
|
||||
if self.op == 'read':
|
||||
|
||||
@@ -94,13 +94,17 @@ def list_interface_indexes():
|
||||
return
|
||||
|
||||
|
||||
def get_bmc_subject_san(configmanager, nodename, addip=None):
|
||||
def get_bmc_subject_san(configmanager, nodename, addnames=()):
|
||||
bmc_san = []
|
||||
subject = ''
|
||||
ipas = set([])
|
||||
if addip:
|
||||
ipas.add(addip)
|
||||
dnsnames = set([])
|
||||
for addname in addnames:
|
||||
try:
|
||||
addr = ipaddress.ip_address(addname)
|
||||
ipas.add(addname)
|
||||
except Exception:
|
||||
dnsnames.add(addname)
|
||||
nodecfg = configmanager.get_node_attributes(nodename,
|
||||
('dns.domain', 'hardwaremanagement.manager', 'hardwaremanagement.manager_tls_name'))
|
||||
bmcaddr = nodecfg.get(nodename, {}).get('hardwaremanagement.manager', {}).get('value', '')
|
||||
|
||||
Reference in New Issue
Block a user