Skip to content

Commit

Permalink
SIMPLE-5949 Deprecated licensing certificate support in PCL (#66)
Browse files Browse the repository at this point in the history
* SIMPLE-5949 Deprecated licensing certificate support in PCL since version 2.7

Include the whole controller version in checks
  • Loading branch information
tmikuska authored Nov 7, 2023
1 parent 9aaaa6f commit 467c0cc
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 34 deletions.
24 changes: 2 additions & 22 deletions examples/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,6 @@

from virl2_client import ClientLibrary

# Licensing setup configuration
CERT = """-----BEGIN CERTIFICATE-----
MIIDGzCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMQ4wDAYDVQQKEwVDaXNj
WhcNMzMwNDI0MjE1NTQzWjAvMQ4wDAYDVQQKEwVDaXNjbzEdMBsGA1UEAxMUTGlj
ZW5zaW5nIFJvb3QgLSBERVYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCcVnEB1h7fLrzDunrg27JBs7QyipsA64qA0Cqob17xrr/etnvWrX2te0P1gnU7
/8wcpaeEGgdpNNOvmQeO9heRlvpPs/LtOULHVr8coKnMmKen+eQ3JNnmHUeJ6eeS
3Z8ntFF8K97Q61uaeHughdm78APwVjvgpEUMjxJ7VYM+vBOFLZutmGjTrgdcJ5h8
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRDIUUhtfshehpNG7cCNuZky+yLZTANBgkq
hkiG9w0BAQsFAAOCAQEAhfGx8q6ufS+cqwNRwynj8a6YLfEfXjyQ9gCzze1aFJH7
3wfgbKoPQyWftMSuIID2dYw7esVOqqA+xbUKL2cK/4ftpkYvz8Q5Z8AkqzLuPM3P
oEudrhu6u9rI31WHz1HLHABaKC+LUYpajG+bPKq6NEYy7zp1wvRUUHqbz9MMi+VK
EYct4M8SANDRAY/ZrGhZaBZ+Qhybw5Ttm8hUY4OygUYHsr3t38FgW00WAHtocj4l
z1LPIlCn0j76n2sH+w9jhp3MO7xlJQaTOM9rpsuO/Q==
-----END CERTIFICATE-----"""

SSMS = "https://sch-alpha.cisco.com/its/service/oddce/services/DDCEService"

TOKEN = (
Expand All @@ -63,7 +47,6 @@

# Set up licensing configuration
client_library.licensing.set_transport(ssms=SSMS)
client_library.licensing.install_certificate(cert=CERT)
client_library.licensing.register_wait(token=TOKEN)

# Get a list of existing labs and print their details
Expand Down Expand Up @@ -116,10 +99,7 @@
lab.wipe()
lab.remove() # or client_library.remove_lab(lab_id)

# Deregister and remove the certificate (optional)
client_library.licensing.deregister()
client_library.licensing.remove_certificate()

# Set licensing back to the default transport (optional)
# Deregister (optional) and set licensing back to the default transport (optional)
# Default SSMS is "https://smartreceiver.cisco.com/licservice/license"
client_library.licensing.deregister()
client_library.licensing.set_default_transport()
33 changes: 31 additions & 2 deletions virl2_client/models/licensing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import logging
import time
import warnings
from typing import TYPE_CHECKING, Any

from ..utils import get_url_from_template
Expand Down Expand Up @@ -52,13 +53,15 @@ class Licensing:
max_wait = 30
wait_interval = 1.5

def __init__(self, session: httpx.Client) -> None:
def __init__(self, session: httpx.Client, is_cert_deprecated: bool) -> None:
"""
Manage licensing.
:param session: The httpx-based HTTP client for this session with the server.
:param is_cert_deprecated: Whether the certificate supported is deprecated.
"""
self._session = session
self._is_cert_deprecated = is_cert_deprecated

def _url_for(self, endpoint, **kwargs):
"""
Expand Down Expand Up @@ -117,7 +120,17 @@ def set_product_license(self, product_license: str) -> bool:
return response.status_code == 204

def get_certificate(self) -> str | None:
"""Get the currently installed licensing public certificate."""
"""
DEPRECATED: There is no replacement as the certificate support was dropped.
(Reason: the certificate support was dropped in CML 2.7.0)
Get the currently installed licensing public certificate.
"""
if self._is_cert_deprecated:
warnings.warn(
"'Licensing.get_certificate' is deprecated.", DeprecationWarning
)
return None
url = self._url_for("certificate")
response = self._session.get(url)
if response.is_success:
Expand All @@ -127,19 +140,35 @@ def get_certificate(self) -> str | None:

def install_certificate(self, cert: str) -> bool:
"""
DEPRECATED: There is no replacement as the certificate support was dropped.
(Reason: the certificate support was dropped in CML 2.7.0)
Set up a licensing public certificate for internal deployment
of an unregistered product instance.
"""
if self._is_cert_deprecated:
warnings.warn(
"'Licensing.install_certificate' is deprecated.", DeprecationWarning
)
return False
url = self._url_for("certificate")
response = self._session.post(url, content=cert)
_LOGGER.info("Certificate was accepted by the agent.")
return response.status_code == 204

def remove_certificate(self) -> bool:
"""
DEPRECATED: There is no replacement as the certificate support was dropped.
(Reason: the certificate support was dropped in CML 2.7.0)
Clear any licensing public certificate for internal deployment
of an unregistered product instance.
"""
if self._is_cert_deprecated:
warnings.warn(
"'Licensing.remove_certificate' is deprecated.", DeprecationWarning
)
return False
url = self._url_for("certificate")
response = self._session.delete(url)
_LOGGER.info("Certificate was removed.")
Expand Down
22 changes: 12 additions & 10 deletions virl2_client/virl2_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ def __init__(
except httpx.InvalidURL as exc:
raise InitializationError(exc) from None
# checks version from system_info against self.VERSION
self.check_controller_version()
controller_version = self.check_controller_version()

self._session.auth = TokenAuth(self)
# Note: session.auth is defined in the httpx module to be of type Auth,
Expand All @@ -273,7 +273,9 @@ def __init__(
self.raise_for_auth_failure = raise_for_auth_failure
self._labs: dict[str, Lab] = {}

self.licensing = Licensing(self._session)
self.licensing = Licensing(
self._session, is_cert_deprecated=controller_version >= Version("2.7.0")
)
self.user_management = UserManagement(self._session)
self.group_management = GroupManagement(self._session)
self.system_management = SystemManagement(
Expand Down Expand Up @@ -405,22 +407,21 @@ def system_info(self) -> dict:
url = self._url_for("system_info")
return self._session.get(url).json()

def check_controller_version(self) -> None:
def check_controller_version(self) -> Version | None:
"""
Check remote controller version against current client version
(specified in `self.VERSION`) and against controller version
blacklist (specified in `self.INCOMPATIBLE_CONTROLLER_VERSIONS`).
Raise exception if versions are incompatible, or print warning
if the client minor version is lower than the controller minor version.
"""
controller_version = self.system_info().get("version", "").split("-")[0]

# are we running against a test version?
if controller_version == "testing":
_LOGGER.warning("testing version detected!")
return
controller_version = self.system_info().get("version")
try:
controller_version_obj = Version(controller_version)
except (TypeError, ValueError):
_LOGGER.warning(f"Invalid version detected: {controller_version}!")
return None

controller_version_obj = Version(controller_version)
if controller_version_obj in self.INCOMPATIBLE_CONTROLLER_VERSIONS:
raise InitializationError(
f"Controller version {controller_version_obj} is marked incompatible! "
Expand All @@ -439,6 +440,7 @@ def check_controller_version(self) -> None:
f"Please ensure the client version is compatible with the controller "
f"version. Client {self.VERSION}, controller {controller_version_obj}."
)
return controller_version_obj

def is_system_ready(
self, wait: bool = False, max_wait: int = 60, sleep: int = 5
Expand Down

0 comments on commit 467c0cc

Please sign in to comment.