2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-08-04 16:37:00 +00:00

Add function for nodes to request a TLS certificate from confluent

Also, make certificate lifetime default configurable as attribute, with 47 as explicit default.
This commit is contained in:
Jarrod Johnson
2026-06-23 09:39:16 -04:00
parent 1068be423a
commit cf7f2f434d
4 changed files with 26 additions and 10 deletions
@@ -666,6 +666,9 @@ node = {
'pubkeys.tls': {
'description': ('Fingerprint of the TLS certificate for service running on host.'),
},
'pubkeys.tls_lifetime': {
'description': ('When granting a certificate to the node or related BMC, this is the validity in days. Default is 45 days.'),
},
'pubkeys.ssh': {
'description': ('Fingerprint of the SSH key of the OS running on the '
'system.'),
@@ -327,8 +327,11 @@ class NodeHandler(generic.NodeHandler):
nodename, {}).get('hardwaremanagement.method', {}).get('value', 'ipmi')
if hwmgt_method != 'redfish':
return
tls_lifetime = self.configmanager.get_node_attributes(nodename, 'pubkeys.tls_lifetime')
tls_lifetime = tls_lifetime.get(nodename, {}).get('pubkeys.tls_lifetime', {}).get('value', 45)
tls_lifetime = int(tls_lifetime)
proc = await asyncio.create_subprocess_exec(
'/opt/confluent/bin/nodecertutil', nodename, 'signbmccert', '--days', '47'
'/opt/confluent/bin/nodecertutil', nodename, 'signbmccert', '--days', str(tls_lifetime)
)
await proc.wait()
@@ -595,6 +595,12 @@ class IpmiHandler:
if self.element[0] == 'sign' and self.op == 'update':
csr = await self.ipmicmd.get_bmc_csr()
subj, san = util.get_bmc_subject_san(self.cfm, self.node, self.inputdata.get_added_names(self.node))
try:
tls_lifetime = self.inputdata.get_days(self.node)
except KeyError:
tls_lifetime = self.cfm.get_node_attributes(self.node, 'hardwaremanagement.manager_tls_lifetime')
tls_lifetime = tls_lifetime.get(self.node, {}).get('hardwaremanagement.manager_tls_lifetime', {}).get('value', 45)
tls_lifetime = int(tls_lifetime)
with tempfile.NamedTemporaryFile() as tmpfile:
tmpfile.write(csr.encode())
tmpfile.flush()
@@ -602,7 +608,7 @@ class IpmiHandler:
certname = certfile.name
certfile.close()
await certutil.create_certificate(None, certname, tmpfile.name, subj, san, backdate=False,
days=self.inputdata.get_days(self.node))
days=tls_lifetime)
with open(certname, 'rb') as certf:
cert = certf.read()
os.unlink(certname)
+12 -8
View File
@@ -18,6 +18,7 @@ import hashlib
import crypt
import json
import os
import tempfile
import time
import yaml
try:
@@ -57,14 +58,14 @@ def listdump(input):
def principals_to_san(principals):
san = []
san = set([])
for principal in principals:
try:
ipaddress.ip_address(principal)
san.append('IP:' + principal)
san.add('IP:' + principal)
except ValueError:
san.append('DNS:' + principal)
return san
san.add('DNS:' + principal)
return ','.join(san)
async def get_extra_names(nodename, cfg, myip=None, preferadjacent=False, addlocalhost=True):
if addlocalhost:
@@ -409,7 +410,8 @@ async def handle_request(req, make_response, mimetype):
return await make_response(mimetype, 200, 'OK', body=dumper(ncfg))
elif reqpath == '/self/tlscert' and reqbody:
csr = reqbody.decode('utf8')
pals = await get_extra_names(nodename, cfg, myip)
pals = await get_extra_names(nodename, cfg, myip, addlocalhost=False)
pals.add(nodename)
with tempfile.NamedTemporaryFile() as tmpfile:
tmpfile.write(csr.encode())
tmpfile.flush()
@@ -417,13 +419,15 @@ async def handle_request(req, make_response, mimetype):
certname = certfile.name
certfile.close()
subj = '/CN={0}'.format(nodename)
tls_lifetime = cfg.get_node_attributes(nodename, 'pubkeys.tls_lifetime')
tls_lifetime = tls_lifetime.get(nodename, {}).get('pubkeys.tls_lifetime', {}).get('value', 45)
tls_lifetime = int(tls_lifetime)
await certutil.create_certificate(None, certname, tmpfile.name, subj, principals_to_san(pals), backdate=False,
days=3650)
days=tls_lifetime)
with open(certname, 'rb') as certf:
cert = certf.read()
os.unlink(certname)
return await make_response('application/x-pem-file', 200, 'OK', body=cert.encode())
return await make_response('application/x-pem-file', 200, 'OK', body=cert)
elif reqpath == '/self/sshcert' and reqbody:
if not sshutil.ca_exists():
return await make_response(mimetype, 500, 'Unconfigured', body='CA is not configured on this system (run ...)')