schrodinger.application.licensing.licserver.client module

client provides the main APIs for end user license information collection.

The “client” term refers to consumption of both: - offline “local-entitlement” files - network-based “server-identifier” files

The APIs in this module are mainly for read-only license configuration querying.

For license configuration management, read+write operations, see schrodinger.application.licensing.licserver.install

schrodinger.application.licensing.licserver.client.system_license_dir() str

Returns default location of the system-wide license directory, outside of any specific installation.

Generally, licenses are tied to a machine rather than any particular user or installation, so this is the preferred location to keep local-entitlement and server-identifier license files.

schrodinger.application.licensing.licserver.client.schrodinger_license_dir(schrod: Optional[str] = None) str

Returns location of the license directory inside a Schrodinger installation.

Parameters

schrod – Path to Schrodinger installation. If None, uses $SCHRODINGER environment variable.

schrodinger.application.licensing.licserver.client.search_path(*, use_override_envs: bool) list[str]

The list of filepaths from which to read/write license files.

It follows the standard search path for Schrodinger license files, which are the following two directories: - system_license_dir() (e.g. /opt/schrodinger/licenses) - schrodinger_license_dir() ($SCHRODINGER/licenses)

If the SCHRODINGER_LICENSE_FILE_OVERRIDE environment variable is set, it will be used instead. This behavior can be disabled via the use_override_envs parameter.

In general, the APIs in this module have the following behavior when it comes to the search path: - Read operations respect the override environment variables. - Write operations in this module ignore the override environment variables and default to the first writeable location from the standard search path.

This allows debugging tools to read from the same location as other Schrodinger Suite programs, while setup/config tools can use the standard locations.

Parameters

use_override_envs – whether to use environment variables for overrides; see above

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

Bases: enum.StrEnum

Describes the type of client license files to parse and collect.

SERVER_IDENTIFIER = 'server-identifier'
LOCAL_ENTITLEMENT = 'local-entitlement'
class schrodinger.application.licensing.licserver.client.SignatureAlgorithm(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: enum.StrEnum

Describes the signature algorithm supported to sign the license file. This is currently used to validate the signature field of LicenseFileType.LOCAL_ENTITLEMENT schema.

SHA256WithRSA = 'SHA256WithRSA'
SHA384WithRSA = 'SHA384WithRSA'
SHA512WithRSA = 'SHA512WithRSA'
ECDSAWithSHA256 = 'ECDSAWithSHA256'
ECDSAWithSHA384 = 'ECDSAWithSHA384'
ECDSAWithSHA512 = 'ECDSAWithSHA512'
SHA256WithRSAPSS = 'SHA256WithRSAPSS'
SHA384WithRSAPSS = 'SHA384WithRSAPSS'
SHA512WithRSAPSS = 'SHA512WithRSAPSS'
PureEd25519 = 'PureEd25519'
class schrodinger.application.licensing.licserver.client.ServerIdentifierSourceType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: enum.StrEnum

Available source types to parse LicenseFileType.SERVER_IDENTIFIER.

PATH = 'path'
ENV = 'var'
class schrodinger.application.licensing.licserver.client.ServerIdentifier(sourceType: schrodinger.application.licensing.licserver.client.ServerIdentifierSourceType, sourceValue: str, serverAddress: str, tlsServerName=None, **kwargs)

Bases: object

Fields collected in parsing license file of type LicenseFileType.SERVER_IDENTIFIER to use in the config GUI.

__init__(sourceType: schrodinger.application.licensing.licserver.client.ServerIdentifierSourceType, sourceValue: str, serverAddress: str, tlsServerName=None, **kwargs)
sourceType: schrodinger.application.licensing.licserver.client.ServerIdentifierSourceType
sourceValue: str
serverAddress: str
tlsServerName: str | None
err: str | None
class schrodinger.application.licensing.licserver.client.LocalEntitlement(sourceValue: str, *, startDate=None, endDate=None, err=None, machineId=None, **kwargs)

Bases: object

Fields collected in parsing license file of type LicenseFileType.LOCAL_ENTITLEMENT to use in the config GUI.

__init__(sourceValue: str, *, startDate=None, endDate=None, err=None, machineId=None, **kwargs)
sourceValue: str
startDate: str
endDate: str
err: str | None
machineId: list[str] | None
class schrodinger.application.licensing.licserver.client.LocalEntitlementValidation(chain: str, cert: str, algorithm: str, signature: str, **kwargs)

Bases: object

Representation of the validation field contained in the LicenseFileType.LOCAL_ENTITLEMENT license file to allow validating the encoded license description and certificate chain from the file.

__init__(chain: str, cert: str, algorithm: str, signature: str, **kwargs)
chain: str
cert: str
algorithm: str
signature: str
schrodinger.application.licensing.licserver.client.parse_license_server_env() List[schrodinger.application.licensing.licserver.client.ServerIdentifier]

Parses the SCHRODINGER_LICENSE_SERVERS environment variable, and returns a list of LicenseFileType.SERVER_IDENTIFIER configurations.

Returns

List of LicenseFileType.SERVER_IDENTIFIER configurations.

schrodinger.application.licensing.licserver.client.find_license_files(search_paths: List[str]) List[str]

Get the list of available license files going through the search paths. Any error in accessing the search path will be ignored, and moved to the next one.

The sources are discovered using the following logic, and follows the same logic as C++ client does -
  1. If the search path is a file, it will be considered resolving symlink if needed.

  2. If the search path is a directory, it will be traversed for immediate child files ending with “.lic” or “.stub” extension. Any subdirectories, or symlink of immediate files will be ignored.. The list of files are sorted lexicographically, and for each we continue with step 1.

Param

search_path: List of license search paths.

Returns

List of available license files from search paths.

schrodinger.application.licensing.licserver.client.parse_server_identifier(license_file_path: str, data: Dict[str, Any]) List[schrodinger.application.licensing.licserver.client.ServerIdentifier]

Returns the list of ServerIdentifier parsing the json data of the license file.

This function assumes data has already been validated against the JSON schema.

Param

license_file_path: license file path of LicenseFileType.SERVER_IDENTIFIER

Param

data: json data parsing the license_file_path.

Returns

List of ServerIdentifier depending on whether json data contains either a single or multiple servers. Any error encountered will be recorded in its ServerIdentifier.

schrodinger.application.licensing.licserver.client.verify_license(encoded_description: str, local_validation: schrodinger.application.licensing.licserver.client.LocalEntitlementValidation, root_cert: Optional[str] = '') Dict[str, Any]

Verifies that the license is valid by checking the signature of the encoded description.

Returns the decoded JSON description.

NOTE: This function does not verify the JSON description schema, or whether it is valid on the current machine.

Param

encoded_description: base64 encoding of the license description.

Param

local_validation: validation fields to verify the cryptography of the license.

Param

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.

Returns

dict of json data representing the license description.

Raises

LicenseVerificationError if verifying signature of the license description or checking the trust of certificate chain fails

schrodinger.application.licensing.licserver.client.parse_local_entitlement(license_file_path: str, data: Dict[str, Any], root_cert: Optional[str] = '') schrodinger.application.licensing.licserver.client.LocalEntitlement

Returns the LocalEntitlement parsing the json data corresponding to license_file_path.

Param

license_file_path: license file path of type LicenseFileType.LOCAL_ENTITLEMENT

Param

data: json data parsing the license file path.

Returns

A LocalEntitlement indicating the start and end date of the license. This assumes that all standaloneLicenses are of same validity range, and just looks for the first feature entitlement to get the date range. Any error in verifying the license file, is recorded as part of LocalEntitlement.

schrodinger.application.licensing.licserver.client.parse_license_sources(license_file_paths: List[str], root_cert: Optional[str] = '') tuple[List[schrodinger.application.licensing.licserver.client.ServerIdentifier], List[schrodinger.application.licensing.licserver.client.LocalEntitlement], List[str]]

Parses the license file paths into one of the recognized LicenseFileType.

Param

license_file_paths: list of license file paths to parse.

Param

root_cert: Optional trusted root certificate to use to verify the license file of type LicenseType.LOCAL_ENTITLEMENT. This is used for testing, and defaults to production one otherwise.

Returns

tuple containing list of ServerIdentifier, LocalEntitlement and errors in parsing the file and cannot be categorized into one of the LicenseFileType.

schrodinger.application.licensing.licserver.client.post_process_server_identifiers(explored_server_identifiers: List[schrodinger.application.licensing.licserver.client.ServerIdentifier], server_identifiers_from_env: List[schrodinger.application.licensing.licserver.client.ServerIdentifier]) List[schrodinger.application.licensing.licserver.client.ServerIdentifier]

Combine the explored license configurations related to ServerIdentifier removing the duplicates considering sources from the environment and file search paths.

For removing duplicates this follows the same logic as c++ -
  1. We give priority to the ServerIdentifier from the environment. The filesystem follows next.

  2. If a server address is already available in the order, we consider the SAN set in tls if one is not available. This allows the server to be reached with different name. And skip the duplicate LicenseServerConfig to be considered as source.

  3. Add the ServerIdentifier to the list.

Param

explored_server_identifiers: list of ServerIdentifier explored from file search paths.

Param

server_identifiers_from_env: list of ServerIdentifier explored from the environment (SCHRODINGER_LICENSE_SERVERS for now).

Returns

list of ServerIdentifier removing the duplicates

schrodinger.application.licensing.licserver.client.get_license_sources(root_cert: Optional[str] = '') tuple[List[schrodinger.application.licensing.licserver.client.ServerIdentifier], List[schrodinger.application.licensing.licserver.client.LocalEntitlement], List[str]]

Get the list of available server-identifier and local-entitlement license sources.

NOTE: This will be used by config GUI to get the list of LicenseType sources to show.

Returns

a tuple of the list of server-identifier, local-entitlement license sources and list of error strings for information if the license file cannot be parsed or failed in schema-validation.

class schrodinger.application.licensing.licserver.client.GeneralInfo(hostname: str, username: str, currentDir: str, localEntitlements: List[schrodinger.application.licensing.licserver.client.LocalEntitlement], serverIdentifiers: List[schrodinger.application.licensing.licserver.client.ServerIdentifier], environment: Dict[str, str], machid: str)

Bases: object

Fields collected to report general information as part of licserver diagnostics.

hostname: str
__init__(hostname: str, username: str, currentDir: str, localEntitlements: List[schrodinger.application.licensing.licserver.client.LocalEntitlement], serverIdentifiers: List[schrodinger.application.licensing.licserver.client.ServerIdentifier], environment: Dict[str, str], machid: str) None
username: str
currentDir: str
localEntitlements: List[schrodinger.application.licensing.licserver.client.LocalEntitlement]
serverIdentifiers: List[schrodinger.application.licensing.licserver.client.ServerIdentifier]
environment: Dict[str, str]
machid: str
schrodinger.application.licensing.licserver.client.create_archive_file(archive_file: str, archive_dir: str)

Create a zip archive with the contents of archive_dir

Param

archive_file: filename of the zip archive to create.

Param

archive_dir: directory to archive.

schrodinger.application.licensing.licserver.client.execute_lictool(args: List[str], fp)

Execute the lictool program with the given commandline arguments. The output, and error get redirected to the file object.

schrodinger.application.licensing.licserver.client.safe_filename(filepath: str, ext: str | None = None) str

Returns a safe filename to use by replacing the directory separators with underscopre. And replacing the file extension with the optional provided one.

This can be used to dump a file in a flat-namespace if a file by name already exists.

Param

filepath: source filepath to use to return a safe filename.

Param

ext: optional extension to replace the existing one in getting safe filename.

schrodinger.application.licensing.licserver.client.system_hosts_file() str

Return the pathname of the /etc/hosts file, or its equivalent for platforms.

schrodinger.application.licensing.licserver.client.collect_diagnostics(root_cert: Optional[str] = '') str

Collects the information for diagnostics to troubleshoot licserver issues, and returns the archive file path.

Returns

archive file path containing diagnositcs.

Raises

DiagnosticsCollectionError