Skip to content
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

Unable to Programmatically Update Nessus Scanners with Renewed Certificate and Passphrase Using PyTenable #887

Open
devepatil opened this issue Feb 24, 2025 · 1 comment
Labels
question This is a DX or General question Tenable.sc Tenable.sc Package

Comments

@devepatil
Copy link

I am currently working on a use case where I need to programmatically update/edit Nessus scanners managed in Tenable SC using PyTenable. We have 100+ Nessus scanners configured in Tenable SC, with authentication type set as Certificate with a Passphrase/Password. The certificate used for mutual authentication is about to expire, and I need to update each scanner to use the renewed certificate along with a new passphrase.

Manually updating each scanner one by one isn't feasible, so I am attempting to use the PyTenable functions and management APIs to automate this process via a Python script. However, I am encountering difficulties using the respective PyTenable functions/API endpoints to perform this task.

I have tried several approaches, but I am unable to get the script to work as expected. I need expert help in identifying and fixing the issues in my code. Since I am new to both Python and Tenable SC, I would appreciate guidance in resolving this.

Attached is my script for review. In my approach, I am using the File Upload function to upload the renewed certificate to Tenable SC, and then using the returned file identifier or object in the Scanner Edit function. However, despite my efforts, the uploaded file is not replacing the existing certificate for each identified scanner. The script includes some troubleshooting logic where I am verifying the certificate's CN and SET pre- and post-update to ensure the changes are being applied, but the issue persists.

It is quite possible not using the file upload and scanner edit function correctly, so please verify if there any issues with that usage.

Please note: In attached script I am filtering the scanner based on certificate CN name which is about to expire, I have updated the script with dummy CN name.

Scanner_AuthType_Certificate_Update.txt

Any assistance in debugging and addressing this issue would be greatly appreciated.

@SteveMcGrath SteveMcGrath added question This is a DX or General question Tenable.sc Tenable.sc Package labels Feb 24, 2025
@SteveMcGrath
Copy link
Contributor

Normally not the right place for code snippets, and I don't have a Cert-based scanner to test against, so my suggestions may be a bit more general around the cert.

  • If you want to use the fileapi, no need to call it out like you have, as it's already pulled in as part of the base SC class.
with open('example.txt', 'rb') as fobj:
    fname = sc.files.upload(fobj)
## https://pytenable.readthedocs.io/en/stable/api/sc/files.html
  • Environment variables shouldn't be declared within a script. if you want to ensure that your always using a specific set of keys, either pull them from a config file or statically declare them within the script.
  • I'd suggest using the fields parameter in the sc.scanners.list() to see if you can avoid hitting every single scanner's get call (L19) https://docs.tenable.com/security-center/api/Scanner.htm#scanner_GET
  • Just a suggestion, but you can always remove the OpenSSL library requirements if you feed the cert in the correct format instead of trying to convert the pem file here.
  • Id suggest you take a look at the typer library for CLI tools. It'll save you a lot of manual handling of data.
  • You have a lot of try blocks that are likely masking the responses when something errors. I'd suggest removing them to start and then always follow the rule of making your try block specific instead of generic whenever possible.
  • Your update_ssl_scanners function might be better handled as working on a single scanner instead. This also means you can wrap everything up pretty nicely like so:
def update_scanner(
    sc: TenableSC,
    scanner_id: str,
    cert: BytesIO,
    password: str | None = None
) -> dict:
    """
    Updates the specified scanner with the new certificate.

    Args:
        sc: Security Center Instance
        scanner_id: Scanner to update
        cert: Certificate file object.
        password: Certificate password
    
    Returns:
        The updated scanner response object
    """
    fname = sc.files.upload(cert)
    return sc.scanner.edit(
        id=scanner_id,
        cert=fname,
        password=password
    )

if the password ends up being an issue as a NoneType, you can always change that line to be like so:

        password=password if password else ""

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question This is a DX or General question Tenable.sc Tenable.sc Package
Projects
None yet
Development

No branches or pull requests

2 participants