@@ -295,46 +295,69 @@ def get_ca_signed_cert(cacert_path, ca_name, CN):
295295 return "\n " .join ([cert , key ])
296296
297297
298+ def _read_cert_file (path : str ) -> str :
299+ """Helper to read certificate files, which might be symlinks"""
300+ try :
301+ with open (path , 'r' ) as f :
302+ return f .read ()
303+ except (IOError , OSError ):
304+ return None
305+
306+
298307def ext_pillar (minion_id , pillar , base = "/etc/ssl" , name = "PSFCA" , cert_opts = None ):
299308 if cert_opts is None :
300309 cert_opts = {}
301310
302- # Ensure we have a CA created.
311+ # Create CA certificate
303312 opts = cert_opts .copy ()
304313 opts ["CN" ] = name
305314 create_ca (base , name , ** opts )
306315
307- # Start our pillar with just the ca certificate.
308316 data = {
309317 "tls" : {
310318 "ca" : {
311319 name : get_ca_cert (base , name ),
312320 },
313321 "certs" : {},
322+ "acme_certs" : {},
314323 },
315324 }
316325
317- # Create all of the certificates required by this minion
326+ minion_roles = []
327+ minion_roles .extend (
328+ role_name
329+ for role_name , role_config in pillar .get ("roles" , {}).items ()
330+ if role_config .get ("pattern" )
331+ and compound (role_config ["pattern" ], minion_id )
332+ )
333+
334+ # Process CA-signed certificates (gen_certs)
318335 gen_certs = pillar .get ("tls" , {}).get ("gen_certs" , {})
319336 for certificate , config in gen_certs .items ():
320- role_patterns = [
321- role .get ("pattern" )
322- for role in [
323- pillar .get ("roles" , {}).get (r ) for r in config .get ("roles" , "" )
324- ]
325- if role and role .get ("pattern" ) is not None
326- ]
327- if any ([compound (pat , minion_id ) for pat in role_patterns ]):
337+ cert_roles = config .get ("roles" , [])
338+ # Check if any of the minion's roles are in the certificate's required roles
339+ if any (role in minion_roles for role in cert_roles ):
328340 # Create the options
329341 opts = cert_opts .copy ()
330342 opts ["CN" ] = certificate
331343 opts ["days" ] = config .get ("days" , 1 )
332344
333- # Create the signed certificates
334345 create_ca_signed_cert (base , name , ** opts )
335346
336347 # Add the signed certificates to the pillar data
337348 cert_data = get_ca_signed_cert (base , name , certificate )
338349 data ["tls" ]["certs" ][certificate ] = cert_data
339350
340- return data
351+ # Collect ACME certs (acme.cert) for this minion based on its roles
352+ acme_cert_configs = pillar .get ("tls" , {}).get ("acme_cert_configs" , {})
353+ for domain , domain_config in acme_cert_configs .items ():
354+ cert_roles = domain_config .get ("roles" , [])
355+ if any (role in minion_roles for role in cert_roles ):
356+ cert_name = domain_config .get ('name' , domain )
357+ full_cert_chain = _read_cert_file (f"/etc/letsencrypt/live/{ cert_name } /fullchain.pem" )
358+ privkey = _read_cert_file (f"/etc/letsencrypt/live/{ cert_name } /privkey.pem" )
359+
360+ if full_cert_chain and privkey :
361+ data ["tls" ]["acme_certs" ][domain ] = full_cert_chain + "\n " + privkey
362+
363+ return data
0 commit comments