blob: e20103bb76169e28987571f03e0b31e93cbdfbfc [file] [log] [blame]
Alex Schendel47af8322023-07-21 13:32:38 -07001#!/usr/bin/env python3
Ed Tanous178c55a2025-02-11 15:43:33 -08002"""
3Script to generate certificates for a CA, server, and client allowing for
4client authentication using mTLS certificates. This can then be used to test
5mTLS client authentication for Redfish and WebUI.
6"""
Alex Schendel47af8322023-07-21 13:32:38 -07007
8import argparse
Ed Tanous178c55a2025-02-11 15:43:33 -08009import datetime
10import errno
11import ipaddress
Alex Schendel47af8322023-07-21 13:32:38 -070012import os
Ed Tanous7b9e2562024-04-07 20:24:12 -070013import socket
Ed Tanous178c55a2025-02-11 15:43:33 -080014import time
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -070015from typing import Optional
Alex Schendel47af8322023-07-21 13:32:38 -070016
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -070017import asn1
Ed Tanous178c55a2025-02-11 15:43:33 -080018import httpx
19from cryptography import x509
20from cryptography.hazmat.primitives import hashes, serialization
21from cryptography.hazmat.primitives.asymmetric import ec
22from cryptography.hazmat.primitives.serialization import (
23 load_pem_private_key,
24 pkcs12,
25)
26from cryptography.x509.oid import NameOID
Alex Schendel47af8322023-07-21 13:32:38 -070027
Ed Tanous178c55a2025-02-11 15:43:33 -080028replaceCertPath = "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -070029# https://oidref.com/1.3.6.1.4.1.311.20.2.3
30upnObjectIdentifier = "1.3.6.1.4.1.311.20.2.3"
Alex Schendel47af8322023-07-21 13:32:38 -070031
32
Ed Tanous178c55a2025-02-11 15:43:33 -080033class RedfishSessionContext:
34 def __init__(self, client, username="root", password="0penBmc"):
35 self.client = client
36 self.session_uri = None
37 self.x_auth_token = None
38 self.username = username
39 self.password = password
Alex Schendel47af8322023-07-21 13:32:38 -070040
Ed Tanous178c55a2025-02-11 15:43:33 -080041 def __enter__(self):
42 r = self.client.post(
43 "/redfish/v1/SessionService/Sessions",
44 json={
45 "UserName": self.username,
46 "Password": self.password,
47 "Context": f"pythonscript::{os.path.basename(__file__)}",
48 },
49 headers={"content-type": "application/json"},
50 )
51 r.raise_for_status()
52 self.x_auth_token = r.headers["x-auth-token"]
53 self.session_uri = r.headers["location"]
54 return self
Ed Tanous7b9e2562024-04-07 20:24:12 -070055
Ed Tanous178c55a2025-02-11 15:43:33 -080056 def __exit__(self, type, value, traceback):
57 if not self.session_uri:
58 return
59 r = self.client.delete(self.session_uri)
60 r.raise_for_status()
Alex Schendel47af8322023-07-21 13:32:38 -070061
Alex Schendel47af8322023-07-21 13:32:38 -070062
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -070063def get_hostname(redfish_session, username, password, url):
64 service_root = redfish_session.get("/redfish/v1/")
65 service_root.raise_for_status()
66
67 manager_uri = service_root.json()["Links"]["ManagerProvidingService"][
68 "@odata.id"
69 ]
70
71 manager_response = redfish_session.get(manager_uri)
72 manager_response.raise_for_status()
73
74 network_protocol_uri = manager_response.json()["NetworkProtocol"][
75 "@odata.id"
76 ]
77
78 network_protocol_response = redfish_session.get(network_protocol_uri)
79 network_protocol_response.raise_for_status()
80
81 hostname = network_protocol_response.json()["HostName"]
82
83 return hostname
84
85
Ed Tanous178c55a2025-02-11 15:43:33 -080086def generateCA():
87 private_key = ec.generate_private_key(ec.SECP256R1())
88 public_key = private_key.public_key()
89 builder = x509.CertificateBuilder()
90
91 name = x509.Name(
Alex Schendel47af8322023-07-21 13:32:38 -070092 [
Ed Tanous178c55a2025-02-11 15:43:33 -080093 x509.NameAttribute(NameOID.ORGANIZATION_NAME, "OpenBMC"),
94 x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "bmcweb"),
95 x509.NameAttribute(NameOID.COMMON_NAME, "Test CA"),
Alex Schendel47af8322023-07-21 13:32:38 -070096 ]
97 )
Ed Tanous178c55a2025-02-11 15:43:33 -080098 builder = builder.subject_name(name)
99 builder = builder.issuer_name(name)
100
101 builder = builder.not_valid_before(
102 datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
103 )
104 builder = builder.not_valid_after(
105 datetime.datetime(2070, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
106 )
107 builder = builder.serial_number(x509.random_serial_number())
108 builder = builder.public_key(public_key)
109
110 basic_constraints = x509.BasicConstraints(ca=True, path_length=None)
111 builder = builder.add_extension(basic_constraints, critical=True)
112
113 usage = x509.KeyUsage(
114 content_commitment=False,
115 crl_sign=True,
116 data_encipherment=False,
117 decipher_only=False,
118 digital_signature=False,
119 encipher_only=False,
120 key_agreement=False,
121 key_cert_sign=True,
122 key_encipherment=False,
123 )
124 builder = builder.add_extension(usage, critical=False)
125
126 auth_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(public_key)
127
128 builder = builder.add_extension(auth_key, critical=False)
129
130 root_cert = builder.sign(
131 private_key=private_key, algorithm=hashes.SHA256()
Alex Schendel47af8322023-07-21 13:32:38 -0700132 )
133
Ed Tanous178c55a2025-02-11 15:43:33 -0800134 return private_key, root_cert
Alex Schendel47af8322023-07-21 13:32:38 -0700135
136
Ed Tanous178c55a2025-02-11 15:43:33 -0800137def signCsr(csr, ca_key):
138 csr.sign(ca_key, algorithm=hashes.SHA256())
139 return
140
141
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700142def generate_client_key_and_cert(
143 ca_cert,
144 ca_key,
145 common_name: Optional[str] = None,
146 upn: Optional[str] = None,
147):
Ed Tanous178c55a2025-02-11 15:43:33 -0800148 private_key = ec.generate_private_key(ec.SECP256R1())
149 public_key = private_key.public_key()
150 builder = x509.CertificateBuilder()
151
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700152 cert_names = [
153 x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
154 x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),
155 x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"),
156 x509.NameAttribute(NameOID.ORGANIZATION_NAME, "OpenBMC"),
157 x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "bmcweb"),
158 ]
159 if common_name is not None:
160 cert_names.append(x509.NameAttribute(NameOID.COMMON_NAME, common_name))
161
162 builder = builder.subject_name(x509.Name(cert_names))
Ed Tanous178c55a2025-02-11 15:43:33 -0800163
164 builder = builder.issuer_name(ca_cert.subject)
165 builder = builder.public_key(public_key)
166 builder = builder.serial_number(x509.random_serial_number())
167 builder = builder.not_valid_before(
168 datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
169 )
170 builder = builder.not_valid_after(
171 datetime.datetime(2070, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
172 )
173
174 usage = x509.KeyUsage(
175 content_commitment=False,
176 crl_sign=False,
177 data_encipherment=False,
178 decipher_only=False,
179 digital_signature=True,
180 encipher_only=False,
181 key_agreement=True,
182 key_cert_sign=False,
183 key_encipherment=False,
184 )
185 builder = builder.add_extension(usage, critical=False)
186
187 exusage = x509.ExtendedKeyUsage([x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH])
188 builder = builder.add_extension(exusage, critical=True)
189
190 auth_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(public_key)
191 builder = builder.add_extension(auth_key, critical=False)
192
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700193 if upn is not None:
194 encoder = asn1.Encoder()
195 encoder.start()
196 encoder.write(upn, asn1.Numbers.UTF8String)
197
198 builder = builder.add_extension(
199 x509.SubjectAlternativeName(
200 [
201 x509.OtherName(
202 x509.ObjectIdentifier(upnObjectIdentifier),
203 encoder.output(),
204 )
205 ]
206 ),
207 critical=False,
208 )
209
Ed Tanous178c55a2025-02-11 15:43:33 -0800210 signed = builder.sign(private_key=ca_key, algorithm=hashes.SHA256())
211
212 return private_key, signed
213
214
215def generateServerCert(url, ca_key, ca_cert, csr):
216 builder = x509.CertificateBuilder()
217
218 builder = builder.subject_name(csr.subject)
219 builder = builder.issuer_name(ca_cert.subject)
220 builder = builder.public_key(csr.public_key())
221 builder = builder.serial_number(x509.random_serial_number())
222 builder = builder.not_valid_before(
223 datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
224 )
225 builder = builder.not_valid_after(
226 datetime.datetime(2070, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
227 )
228
229 usage = x509.KeyUsage(
230 content_commitment=False,
231 crl_sign=False,
232 data_encipherment=False,
233 decipher_only=False,
234 digital_signature=True,
235 encipher_only=False,
236 key_agreement=False,
237 key_cert_sign=True,
238 key_encipherment=True,
239 )
240 builder = builder.add_extension(usage, critical=True)
241
242 exusage = x509.ExtendedKeyUsage([x509.oid.ExtendedKeyUsageOID.SERVER_AUTH])
243 builder = builder.add_extension(exusage, critical=True)
244
245 san_list = [x509.DNSName("localhost")]
246 try:
247 value = ipaddress.ip_address(url)
248 san_list.append(x509.IPAddress(value))
249 except ValueError:
250 san_list.append(x509.DNSName(url))
251
252 altname = x509.SubjectAlternativeName(san_list)
253 builder = builder.add_extension(altname, critical=True)
254 basic_constraints = x509.BasicConstraints(ca=False, path_length=None)
255 builder = builder.add_extension(basic_constraints, critical=True)
256
257 builder = builder.add_extension(
258 x509.SubjectKeyIdentifier.from_public_key(ca_key.public_key()),
259 critical=False,
260 )
261 authkeyident = x509.AuthorityKeyIdentifier.from_issuer_public_key(
262 ca_key.public_key()
263 )
264 builder = builder.add_extension(authkeyident, critical=False)
265
266 signed = builder.sign(private_key=ca_key, algorithm=hashes.SHA256())
267
268 return signed
269
270
271def generateCsr(
272 redfish_session,
273 commonName,
274 manager_uri,
Ed Tanous7b9e2562024-04-07 20:24:12 -0700275):
Ed Tanous7b9e2562024-04-07 20:24:12 -0700276 try:
277 socket.inet_aton(commonName)
278 commonName = "IP: " + commonName
279 except socket.error:
280 commonName = "DNS: " + commonName
281
282 CSRRequest = {
283 "CommonName": commonName,
284 "City": "San Fransisco",
285 "Country": "US",
286 "Organization": "",
287 "OrganizationalUnit": "",
288 "State": "CA",
289 "CertificateCollection": {
Ed Tanous178c55a2025-02-11 15:43:33 -0800290 "@odata.id": f"{manager_uri}/NetworkProtocol/HTTPS/Certificates",
Ed Tanous7b9e2562024-04-07 20:24:12 -0700291 },
292 "AlternativeNames": [
293 commonName,
294 "DNS: localhost",
295 "IP: 127.0.0.1",
296 ],
297 }
298
Ed Tanous178c55a2025-02-11 15:43:33 -0800299 response = redfish_session.post(
Ed Tanous7b9e2562024-04-07 20:24:12 -0700300 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR",
Ed Tanous178c55a2025-02-11 15:43:33 -0800301 json=CSRRequest,
Ed Tanous7b9e2562024-04-07 20:24:12 -0700302 )
Ed Tanous178c55a2025-02-11 15:43:33 -0800303 response.raise_for_status()
Ed Tanous7b9e2562024-04-07 20:24:12 -0700304
Ed Tanous178c55a2025-02-11 15:43:33 -0800305 csrString = response.json()["CSRString"]
306 csr = x509.load_pem_x509_csr(csrString.encode())
307 if not csr.is_signature_valid:
308 raise Exception("CSR was not valid")
309 return csr
Ed Tanous7b9e2562024-04-07 20:24:12 -0700310
311
Ed Tanous178c55a2025-02-11 15:43:33 -0800312def install_ca_cert(redfish_session, ca_cert_dump, manager_uri):
313 ca_certJSON = {
314 "CertificateString": ca_cert_dump.decode(),
Ed Tanous7b9e2562024-04-07 20:24:12 -0700315 "CertificateType": "PEM",
316 }
Ed Tanous178c55a2025-02-11 15:43:33 -0800317 ca_certPath = f"{manager_uri}/Truststore/Certificates"
Ed Tanous7b9e2562024-04-07 20:24:12 -0700318 print("Attempting to install CA certificate to BMC.")
319
Ed Tanous178c55a2025-02-11 15:43:33 -0800320 response = redfish_session.post(ca_certPath, json=ca_certJSON)
321 if response.status_code == 500:
Alex Schendel47af8322023-07-21 13:32:38 -0700322 print(
323 "An existing CA certificate is likely already installed."
324 " Replacing..."
325 )
Ed Tanous178c55a2025-02-11 15:43:33 -0800326 ca_certJSON["CertificateUri"] = {
327 "@odata.id": ca_certPath + "/1",
Ed Tanous7b9e2562024-04-07 20:24:12 -0700328 }
329
Ed Tanous178c55a2025-02-11 15:43:33 -0800330 response = redfish_session.post(replaceCertPath, json=ca_certJSON)
331 if response.status_code == 200:
Alex Schendel47af8322023-07-21 13:32:38 -0700332 print("Successfully replaced existing CA certificate.")
333 else:
334 raise Exception(
335 "Could not install or replace CA certificate."
336 "Please check if a certificate is already installed. If a"
337 "certificate is already installed, try performing a factory"
338 "restore to clear such settings."
339 )
Ed Tanous178c55a2025-02-11 15:43:33 -0800340 response.raise_for_status()
341 print("Successfully installed CA certificate.")
342
343
344def install_server_cert(redfish_session, manager_uri, server_cert_dump):
345
346 server_cert_json = {
347 "CertificateString": server_cert_dump.decode(),
Ed Tanous7b9e2562024-04-07 20:24:12 -0700348 "CertificateUri": {
Ed Tanous178c55a2025-02-11 15:43:33 -0800349 "@odata.id": f"{manager_uri}/NetworkProtocol/HTTPS/Certificates/1",
Ed Tanous7b9e2562024-04-07 20:24:12 -0700350 },
351 "CertificateType": "PEM",
352 }
353
Alex Schendel47af8322023-07-21 13:32:38 -0700354 print("Replacing server certificate...")
Ed Tanous178c55a2025-02-11 15:43:33 -0800355 response = redfish_session.post(replaceCertPath, json=server_cert_json)
356 if response.status_code == 200:
Alex Schendel47af8322023-07-21 13:32:38 -0700357 print("Successfully replaced server certificate.")
358 else:
Ed Tanous178c55a2025-02-11 15:43:33 -0800359 raise Exception(f"Could not replace certificate: {response.json()}")
360
361 tls_patch_json = {"Oem": {"OpenBMC": {"AuthMethods": {"TLS": True}}}}
Alex Schendel47af8322023-07-21 13:32:38 -0700362 print("Ensuring TLS authentication is enabled.")
Ed Tanous178c55a2025-02-11 15:43:33 -0800363 response = redfish_session.patch(
364 "/redfish/v1/AccountService", json=tls_patch_json
Alex Schendel47af8322023-07-21 13:32:38 -0700365 )
Ed Tanous178c55a2025-02-11 15:43:33 -0800366 if response.status_code == 200:
Alex Schendel47af8322023-07-21 13:32:38 -0700367 print("Successfully enabled TLS authentication.")
368 else:
369 raise Exception("Could not enable TLS auth: " + response.read)
Ed Tanous178c55a2025-02-11 15:43:33 -0800370
371
372def generate_pk12(certs_dir, key, client_cert, username):
373 print("Generating p12 cert file for browser authentication.")
374 p12 = pkcs12.serialize_key_and_certificates(
375 username.encode(),
376 key,
377 client_cert,
378 None,
379 serialization.NoEncryption(),
380 )
381 with open(os.path.join(certs_dir, "client.p12"), "wb") as f:
382 f.write(p12)
383
384
385def test_mtls_auth(url, certs_dir):
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700386 with httpx.Client(
387 base_url=f"https://{url}",
Ed Tanous178c55a2025-02-11 15:43:33 -0800388 verify=os.path.join(certs_dir, "CA-cert.cer"),
Ed Tanous7b9e2562024-04-07 20:24:12 -0700389 cert=(
Ed Tanous178c55a2025-02-11 15:43:33 -0800390 os.path.join(certs_dir, "client-cert.pem"),
391 os.path.join(certs_dir, "client-key.pem"),
Ed Tanous7b9e2562024-04-07 20:24:12 -0700392 ),
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700393 ) as client:
394 print("Testing mTLS auth with CommonName")
395 response = client.get(
396 "/redfish/v1/SessionService/Sessions",
397 )
398 response.raise_for_status()
399
400 print("Changing CertificateMappingAttribute to use UPN")
401 patch_json = {
402 "MultiFactorAuth": {
403 "ClientCertificate": {
404 "CertificateMappingAttribute": "UserPrincipalName"
405 }
406 }
407 }
408 response = client.patch(
409 "/redfish/v1/AccountService",
410 json=patch_json,
411 )
412 response.raise_for_status()
413
414 with httpx.Client(
415 base_url=f"https://{url}",
416 verify=os.path.join(certs_dir, "CA-cert.cer"),
417 cert=(
418 os.path.join(certs_dir, "upn-client-cert.pem"),
419 os.path.join(certs_dir, "upn-client-key.pem"),
420 ),
421 ) as client:
422 print("Retesting mTLS auth with UPN")
423 response = client.get(
424 "/redfish/v1/SessionService/Sessions",
425 )
426 response.raise_for_status()
427
428 print("Changing CertificateMappingAttribute to use CommonName")
429 patch_json = {
430 "MultiFactorAuth": {
431 "ClientCertificate": {
432 "CertificateMappingAttribute": "CommonName"
433 }
434 }
435 }
436 response = client.patch(
437 "/redfish/v1/AccountService",
438 json=patch_json,
439 )
440 response.raise_for_status()
Ed Tanous178c55a2025-02-11 15:43:33 -0800441
442
443def setup_server_cert(
444 redfish_session,
445 ca_cert_dump,
446 certs_dir,
447 client_key,
448 client_cert,
449 username,
450 url,
451 ca_key,
452 ca_cert,
453):
454 service_root = redfish_session.get("/redfish/v1/")
455 service_root.raise_for_status()
456
457 manager_uri = service_root.json()["Links"]["ManagerProvidingService"][
458 "@odata.id"
459 ]
460
461 install_ca_cert(redfish_session, ca_cert_dump, manager_uri)
462 generate_pk12(certs_dir, client_key, client_cert, username)
463
464 csr = generateCsr(
465 redfish_session,
466 url,
467 manager_uri,
468 )
469 serverCert = generateServerCert(
470 url,
471 ca_key,
472 ca_cert,
473 csr,
474 )
475 server_cert_dump = serverCert.public_bytes(
476 encoding=serialization.Encoding.PEM
477 )
478 with open(os.path.join(certs_dir, "server-cert.pem"), "wb") as f:
479 f.write(server_cert_dump)
480 print("Server cert generated.")
481
482 install_server_cert(redfish_session, manager_uri, server_cert_dump)
483
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700484 print("Make sure setting CertificateMappingAttribute to CommonName")
485 patch_json = {
486 "MultiFactorAuth": {
487 "ClientCertificate": {"CertificateMappingAttribute": "CommonName"}
488 }
489 }
490 response = redfish_session.patch(
491 "/redfish/v1/AccountService", json=patch_json
492 )
493 response.raise_for_status()
494
Ed Tanous178c55a2025-02-11 15:43:33 -0800495
496def generate_and_load_certs(url, username, password):
497 certs_dir = os.path.expanduser("~/certs")
498 print(f"Writing certs to {certs_dir}")
499 try:
500 print("Making certs directory.")
501 os.mkdir(certs_dir)
502 except OSError as error:
503 if error.errno != errno.EEXIST:
504 raise
505
506 ca_cert_filename = os.path.join(certs_dir, "CA-cert.cer")
507 ca_key_filename = os.path.join(certs_dir, "CA-key.pem")
508 if not os.path.exists(ca_cert_filename):
509 ca_key, ca_cert = generateCA()
510
511 ca_key_dump = ca_key.private_bytes(
512 encoding=serialization.Encoding.PEM,
513 format=serialization.PrivateFormat.TraditionalOpenSSL,
514 encryption_algorithm=serialization.NoEncryption(),
515 )
516 ca_cert_dump = ca_cert.public_bytes(
517 encoding=serialization.Encoding.PEM
518 )
519
520 with open(ca_cert_filename, "wb") as f:
521 f.write(ca_cert_dump)
522 print("CA cert generated.")
523 with open(ca_key_filename, "wb") as f:
524 f.write(ca_key_dump)
525 print("CA key generated.")
526
527 with open(ca_cert_filename, "rb") as ca_cert_file:
528 ca_cert_dump = ca_cert_file.read()
529 ca_cert = x509.load_pem_x509_certificate(ca_cert_dump)
530
531 with open(ca_key_filename, "rb") as ca_key_file:
532 ca_key_dump = ca_key_file.read()
533 ca_key = load_pem_private_key(ca_key_dump, None)
534
535 client_key, client_cert = generate_client_key_and_cert(
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700536 ca_cert, ca_key, common_name=username
Ed Tanous178c55a2025-02-11 15:43:33 -0800537 )
538 client_key_dump = client_key.private_bytes(
539 encoding=serialization.Encoding.PEM,
540 format=serialization.PrivateFormat.TraditionalOpenSSL,
541 encryption_algorithm=serialization.NoEncryption(),
542 )
543
544 with open(os.path.join(certs_dir, "client-key.pem"), "wb") as f:
545 f.write(client_key_dump)
546 print("Client key generated.")
547 client_cert_dump = client_cert.public_bytes(
548 encoding=serialization.Encoding.PEM
549 )
550
551 with open(os.path.join(certs_dir, "client-cert.pem"), "wb") as f:
552 f.write(client_cert_dump)
553 print("Client cert generated.")
554
555 print(f"Connecting to {url}")
556 with httpx.Client(
557 base_url=f"https://{url}", verify=False, follow_redirects=False
558 ) as redfish_session:
559 with RedfishSessionContext(
560 redfish_session, username, password
561 ) as rf_session:
562 redfish_session.headers["X-Auth-Token"] = rf_session.x_auth_token
Malik Akbar Hashemi Rafsanjaniaca5a542025-03-12 10:43:48 -0700563
564 hostname = get_hostname(redfish_session, username, password, url)
565 print(f"Hostname: {hostname}")
566
567 upn_client_key, upn_client_cert = generate_client_key_and_cert(
568 ca_cert,
569 ca_key,
570 upn=f"{username}@{hostname}",
571 )
572 upn_client_key_dump = upn_client_key.private_bytes(
573 encoding=serialization.Encoding.PEM,
574 format=serialization.PrivateFormat.TraditionalOpenSSL,
575 encryption_algorithm=serialization.NoEncryption(),
576 )
577 with open(
578 os.path.join(certs_dir, "upn-client-key.pem"), "wb"
579 ) as f:
580 f.write(upn_client_key_dump)
581 print("UPN client key generated.")
582
583 upn_client_cert_dump = upn_client_cert.public_bytes(
584 encoding=serialization.Encoding.PEM
585 )
586 with open(
587 os.path.join(certs_dir, "upn-client-cert.pem"), "wb"
588 ) as f:
589 f.write(upn_client_cert_dump)
590 print("UPN client cert generated.")
591
Ed Tanous178c55a2025-02-11 15:43:33 -0800592 setup_server_cert(
593 redfish_session,
594 ca_cert_dump,
595 certs_dir,
596 client_key,
597 client_cert,
598 username,
599 url,
600 ca_key,
601 ca_cert,
602 )
603
604 print("Testing redfish TLS authentication with generated certs.")
Ed Tanous178c55a2025-02-11 15:43:33 -0800605 time.sleep(2)
606 test_mtls_auth(url, certs_dir)
Alex Schendel47af8322023-07-21 13:32:38 -0700607 print("Redfish TLS authentication success!")
Alex Schendel47af8322023-07-21 13:32:38 -0700608
609
Ed Tanous178c55a2025-02-11 15:43:33 -0800610def main():
611 parser = argparse.ArgumentParser()
612 parser.add_argument(
613 "--username",
614 help="Username to connect with",
615 default="root",
616 )
617 parser.add_argument(
618 "--password",
619 help="Password for user in order to install certs over Redfish.",
620 default="0penBmc",
621 )
622 parser.add_argument("host", help="Host to connect to")
623
624 args = parser.parse_args()
625 generate_and_load_certs(args.host, args.username, args.password)
626
627
Ed Tanous7b9e2562024-04-07 20:24:12 -0700628if __name__ == "__main__":
629 main()