schrodinger.application.licensing.licserver.install module

License Installation APIs

APIs in this module optionally accept a logger for user-facing info/debug-level messages. If not provided, they log to an internal NullHandler by default.

class schrodinger.application.licensing.licserver.install.LicenseFileType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: enum.StrEnum

Describes the type of a license file to be installed.

This enum should remain private; it contains values that are only relevant to license installation, and never for client application purposes.

SERVER_IDENTIFIER = 'server-identifier'

points to license server; contents are exactly as expected by mmlic3

LOCAL_ENTITLEMENT = 'local-entitlement'

contains entitlements; contents are exactly as expected by mmlic3

SERVER_ENTITLEMENT = 'server-entitlement'

contains entitlements; contents are exactly as expected by licserverd

LOCAL_ENTITLEMENT_BLOB = 'local-entitlement-blob'

Raw JSON blob where the “licenseFile” key contains a LOCAL_ENTITLEMENT. This file is usually sent in emails.

SERVER_ENTITLEMENT_BLOB = 'server-entitlement-blob'

Raw JSON blob where the “licenseFile” key contains a SERVER_ENTITLEMENT. This file is usually sent in emails.

Distinguished from LOCAL_ENTITLEMENT_BLOB because it also contains TLS info: - “tlsKey” contains a private key (see footnote [1]) - “tlsCert” contains the public certificate corresponding to “tlsKey”, bundled with a chain to the root.

[1] For those interested in the security aspects:

Generally transmitting a private key over a network is discouraged, even if the connection is secured with TLS. However, we are ok with it because this private key is ONLY used to secure connections to the license server, which only serves Schrodinger Licensing.

The root Certificate Authority here is privately owned and managed by Schrodinger, and is not used for any other purpose besides licensing infrastructure.

If you’re still not convinced, we allow generation of a private key locally and then only sending a public key + Certificate Signing Request to websvc. This lets us deliver a valid certificate bundle without your private key ever leaving your machine, remaining private :)

This is not an automated process yet, so reach out to Licensing if interested.

RAW_WEBSVC_RESPONSE = 'raw-websvc-response'

completely raw netsuite response from websvc endpoint; “license_key” field contains either SERVER_ENTITLEMENT_BLOB or LOCAL_ENTITLEMENT_BLOB

schrodinger.application.licensing.licserver.install.install_server_identifier(server_address: str, license_dir: str | None = None, *, tls_server_name: str | None = None, tls_verify: bool = False, logger: logging.Logger | None = None) str

An opinionated helper to install a server-identifier license file for the specified server.

The server address string MAY NOT contain advanced server configuration options; specify those as keyword arguments, instead.

Parameters
  • server_address – license server address in the form ‘hostname:port’

  • license_dir – directory to write the license file. If unspecified, uses first writeable directory from search_path().

  • tls_server_name – optional custom server name to use for TLS Hostname Verification.

  • tls_verify – if True, verifies that TLS will work with the hostname provided.

  • logger – logger to use for messages

Returns

path to the written license file

Raises

AddressError for an incorrect server address

Raises

NoWritableDirectoryError if no license directory can be written to

Raises

TLSVerifyError if we couldn’t fetch TLS information from the server

Raises

TLSHostnameError if the server does not have a valid TLS certificate for the hostname

Raises

LicenseError otherwise

schrodinger.application.licensing.licserver.install.detect_license_file_type(filename: str) tuple[str, schrodinger.application.licensing.licserver.install.LicenseFileType]

Detect the type of a license file.

Returns

a tuple of the file contents and the LicenseFileType

Raises

LicenseError for any filesystem-level problems reading the file

Raises

BadLicenseInput if the file is not a recognized format

schrodinger.application.licensing.licserver.install.install_local_entitlement(filepath: str, license_dir: str | None = None, *, skip_validation: bool = False, root_cert: str = '', logger: logging.Logger | None = None) str

Install a local-entitlement file from an existing file.

The file contents may specify either a local-entitlement or a local-entitlement blob, and will be checked.

Parameters
  • filepath – the source license file

  • license_dir – directory to write the license file. If unspecified, uses first writable directory from search_path().

  • skip_validation – whether to skip validation of the entitlement file.

  • root_cert – trusted root certificate to verify the certificate chain. This is optional and used for testing to use test root certificate. Otherwise default to production one.

  • logger – logger to use for messages

Returns

path to the written license file

Raises

BadLicenseInputError if the contents are not a recognized format

Raises

WrongFileType if the contents are not a local-entitlement file

Raises

LicenseVerificationError if the entitlement could not be validated

Raises

LicenseError otherwise

schrodinger.application.licensing.licserver.install.install_local_entitlement_from_key(key: str, license_dir: str | None = None, *, hostnames: list[str], machine_ids: list[str], netsuite_info: dict | None = None, logger: logging.Logger | None = None) str

Install a local-entitlement license file from a netsuite key. The license will be valid for the specified machine IDs. The file will be installed to license_dir if specified, or else the first writable directory from search_path().

Parameters
  • key – license key string

  • license_dir – directory to write the license file (or None to use default)

  • hostnames – list of hostnames, sent for informational purposes

  • machine_ids – list of machine IDs that the license will be valid for

  • netsuite_info – info about the key, if already known, to avoid another call to netsuite. Otherwise, will be queried.

  • logger – logger to use for messages

Returns

path to the written license file

Raises

NetsuiteError if querying or validating the key fails

Raises

WrongFileType if the key is not for a local-entitlement file

Raises

NoWritableDirectoryError if no license directory can be written to

Raises

LicenseError otherwise

schrodinger.application.licensing.licserver.install.archive_license_file(license_file: str) str

Move the license file from its current location to an “archived” directory.

The “archived” directory is created in the same directory as the license file.

For example, a license file at:

/opt/schrodinger/licenses/license.lic

will be archived to:

/opt/schrodinger/licenses/archived/license.lic

Parameters

license_file – path to the license file

Returns

the new path to the archived file

Raises

LicenseError if the file does not exist or cannot be archived