-
Notifications
You must be signed in to change notification settings - Fork 49
Added check for certificate expiration issue #407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
asraf-khan
wants to merge
8
commits into
datacenter:v4.2.0-dev
Choose a base branch
from
asraf-khan:issue6-SSL-expire
base: v4.2.0-dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3f9965b
Added Function check for certificate expiration
asraf-khan 6a1cc35
fixed pytest issues
asraf-khan 9264ead
fixed pytest issues
asraf-khan 9a7f043
Combined PR #390 validation here
asraf-khan dd98e04
updated code as common error recommended_action message
asraf-khan d8a4791
updated code as common error recommended_action message
asraf-khan a52878d
updated code as common error recommended_action message
asraf-khan 9975bb9
Removing leaf/spine certs check from validation
asraf-khan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6702,6 +6702,122 @@ def stale_dbgacEpgSummaryTask_check(tversion, **kwargs): | |
| return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) | ||
|
|
||
|
|
||
| @check_wrapper(check_title='Certificate Expiration Check') | ||
| def certificate_expiration_check(cversion, username, password, fabric_nodes, **kwargs): | ||
| result = PASS | ||
| headers = ["Fault Code", "Severity", "Description"] | ||
| data = [] | ||
| recommended_action = "" | ||
| doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#certificate-expiration-check' | ||
|
|
||
| fault_min_versions = [ | ||
| ("F4501", "6.0(4c)"), ("F4502", "6.0(4c)"), # KeyRing cert expiring/expired | ||
| ("F4503", "6.1(1e)"), ("F4617", "6.1(1e)"), # TP cert expired/expiring | ||
| ("F3081", "3.1(2f)"), ("F3082", "3.1(2f)"), # SAML encryption cert expiring/expired | ||
| ("F4752", "6.1(5e)"), ("F4753", "6.1(5e)"), # Factory certificate expired/expiring | ||
| ] | ||
| FACTORY_CERT_MIN_VERSION = "6.1(5e)" | ||
| CERT_EXPIRING_DAYS = 30 | ||
|
|
||
| has_critical = has_major = has_error = False | ||
|
|
||
| applicable_codes = [code for code, ver in fault_min_versions if not cversion.older_than(ver)] | ||
| if applicable_codes: | ||
| fault_filter = ",".join('eq(faultInst.code,"{}")'.format(code) for code in applicable_codes) | ||
| for faultInst in icurl('class', 'faultInst.json?query-target-filter=or({})'.format(fault_filter)): | ||
| fault_attrs = faultInst['faultInst']['attributes'] | ||
| if fault_attrs['lc'] not in ("raised", "soaking"): | ||
| continue | ||
| data.append([fault_attrs['code'], fault_attrs['severity'], fault_attrs['descr']]) | ||
| if fault_attrs['severity'] == 'critical': | ||
| has_critical = True | ||
| elif fault_attrs['severity'] == 'major': | ||
| has_major = True | ||
|
|
||
| if cversion.older_than(FACTORY_CERT_MIN_VERSION) and username and password: | ||
| date_format = "%b %d %H:%M:%S %Y" | ||
| current_date_re = re.compile( | ||
| r'[A-Z][a-z]{2}\s+(?P<mon>[A-Z][a-z]{2})\s+(?P<day>\d+)\s+(?P<time>\d{2}:\d{2}:\d{2})\s+\w+\s+(?P<year>\d{4})' | ||
| ) | ||
| cert_expiry_re = re.compile( | ||
| r'notAfter=(?P<date>[A-Z][a-z]{2}\s+\d+\s+\d{2}:\d{2}:\d{2}\s+\d{4})' | ||
| ) | ||
|
|
||
| for controller in (node for node in fabric_nodes if node.get("fabricNode", {}).get("attributes", {}).get("role") == "controller"): | ||
| controller_attrs = controller.get("fabricNode", {}).get("attributes", {}) | ||
| controller_id = controller_attrs.get("id", "N/A") | ||
| controller_name = controller_attrs.get("name", "N/A") | ||
| controller_address = controller_attrs.get("address") | ||
|
|
||
| if not controller_address: | ||
| data.append(["N/A", "error", | ||
| "APIC {} ({}): unable to determine controller address".format(controller_id, controller_name)]) | ||
| has_error = True | ||
| continue | ||
|
|
||
| try: | ||
| c = Connection(controller_address) | ||
| c.username = username | ||
| c.password = password | ||
| c.log = LOG_FILE | ||
| c.connect() | ||
|
|
||
| c.cmd("date; acidiag verifyapic") | ||
| current_date_match = current_date_re.search(c.output) | ||
| cert_expiry_match = cert_expiry_re.search(c.output) | ||
| except Exception as e: | ||
| data.append(["N/A", "error", | ||
| "APIC {} ({}): unable to verify factory certificate - {}".format(controller_id, controller_name, e)]) | ||
| has_error = True | ||
| continue | ||
|
|
||
| try: | ||
| current_date = datetime.strptime( | ||
| "{mon} {day} {time} {year}".format(**current_date_match.groupdict()), date_format | ||
| ) | ||
| except (AttributeError, ValueError): | ||
| data.append(["N/A", "error", | ||
| "APIC {} ({}): unable to determine current date".format(controller_id, controller_name)]) | ||
| has_error = True | ||
| continue | ||
|
|
||
| try: | ||
| cert_expiry = datetime.strptime(" ".join(cert_expiry_match.group("date").split()), date_format) | ||
| except (AttributeError, ValueError): | ||
| data.append(["N/A", "error", | ||
| "APIC {} ({}): unable to determine factory certificate expiry date".format(controller_id, controller_name)]) | ||
| has_error = True | ||
| continue | ||
|
|
||
| if cert_expiry <= current_date: | ||
| data.append(["N/A", "critical", | ||
| "APIC {} ({}): factory certificate expired on {} UTC".format(controller_id, controller_name, cert_expiry)]) | ||
| has_critical = True | ||
| elif (cert_expiry - current_date).days <= CERT_EXPIRING_DAYS: | ||
| data.append(["N/A", "major", | ||
| "APIC {} ({}): factory certificate expiring on {} UTC".format(controller_id, controller_name, cert_expiry)]) | ||
| has_major = True | ||
|
|
||
| if data: | ||
| if has_error: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No test covers the case where fault API returns expired certs (has_critical=True) AND SSH to a controller fails (has_error=True) at the same time. In that scenario the code returns ERROR and hides the confirmed FAIL_O finding. |
||
| result = ERROR | ||
| recommended_action = ( | ||
| "Manually verify certificate expiry for all affected nodes. " | ||
| "\n\tFor APIC factory certificates, run `acidiag verifyapic` on each affected APIC." | ||
| ) | ||
| elif has_critical and has_major: | ||
| result = FAIL_O | ||
| recommended_action = 'Renew expired certificate(s) immediately. For certificate(s) approaching expiry, renew before they expire to avoid service disruption.' | ||
| elif has_critical: | ||
| result = FAIL_O | ||
| recommended_action = 'Renew the certificate(s) immediately to restore functionality.' | ||
| elif has_major: | ||
| result = MANUAL | ||
| recommended_action = 'Renew the certificate(s) before they expire to avoid service disruption.' | ||
|
|
||
| return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) | ||
|
|
||
|
|
||
| # ---- Script Execution ---- | ||
|
|
||
|
|
||
|
|
@@ -6816,6 +6932,7 @@ class CheckManager: | |
| equipment_disk_limits_exceeded, | ||
| apic_vmm_inventory_sync_faults_check, | ||
| apic_storage_inode_check, | ||
| certificate_expiration_check, | ||
|
|
||
| # Configurations | ||
| vpc_paired_switches_check, | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F3081.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F3081", | ||
| "severity": "major", | ||
| "lc": "raised", | ||
| "descr": "SAML Signing Certificate expiring in one month", | ||
| "dn": "uni/userext/samlext/samlidp-IDP1/fault-F3081" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F3082.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F3082", | ||
| "severity": "critical", | ||
| "lc": "raised", | ||
| "descr": "SAML Encryption Certificate has expired", | ||
| "dn": "uni/userext/samlext/samlencert-default/fault-F3082" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4501.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4501", | ||
| "severity": "major", | ||
| "lc": "raised", | ||
| "descr": "KeyRing Certificate THD_KEYRING expiring", | ||
| "dn": "uni/userext/pkiext/keyring-THD_KEYRING/fault-F4501" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4502.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4502", | ||
| "severity": "critical", | ||
| "lc": "raised", | ||
| "descr": "KeyRing Certificate THD_KEYRING expired", | ||
| "dn": "uni/userext/pkiext/keyring-THD_KEYRING/fault-F4502" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4503.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4503", | ||
| "severity": "critical", | ||
| "lc": "raised", | ||
| "descr": "TP Certificate THD_CA expired", | ||
| "dn": "uni/userext/pkiext/tp-THD_CA/fault-F4503" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4617.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4617", | ||
| "severity": "major", | ||
| "lc": "raised", | ||
| "descr": "TP Certificate expiring", | ||
| "dn": "uni/fabric/comm-default/https/fault-F4617" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4752.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4752", | ||
| "severity": "major", | ||
| "lc": "raised", | ||
| "descr": "Factory certificate expiring", | ||
| "dn": "topology/pod-1/node-1/sys/ch/fault-F4752" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_F4753.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4753", | ||
| "severity": "critical", | ||
| "lc": "raised", | ||
| "descr": "Factory certificate expired", | ||
| "dn": "topology/pod-1/node-1/sys/ch/fault-F4753" | ||
| } | ||
| } | ||
| } | ||
| ] |
13 changes: 13 additions & 0 deletions
13
tests/checks/certificate_expiration_check/faultInst_cleared.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [ | ||
| { | ||
| "faultInst": { | ||
| "attributes": { | ||
| "code": "F4502", | ||
| "severity": "critical", | ||
| "lc": "retaining", | ||
| "descr": "KeyRing Certificate THD_KEYRING expired", | ||
| "dn": "uni/userext/pkiext/keyring-THD_KEYRING/fault-F4502" | ||
| } | ||
| } | ||
| } | ||
| ] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using severity attribute to classify expired vs expiring is fragile. Better to check the fault code directly against the known expired/expiring sets.