diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 210bcc97f6..794a0a03ec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,14 @@ Change Log All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_. +==================== +2.118.2 - 2024-01-11 +==================== + +Fixed +----- +* Removed dependency on python-pkcs11 + ==================== 2.118.1 - 2024-01-09 ==================== diff --git a/examples/yubikey_example.py b/examples/yubikey_example.py deleted file mode 100644 index c8178d945f..0000000000 --- a/examples/yubikey_example.py +++ /dev/null @@ -1,34 +0,0 @@ -# coding: utf-8 -# Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. -# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. - -import oci -import sys - -""" -Example showing how to initialize and use the Yubikey signer. - -This example shows the Yubikey signer being used with the -DBaaS service. The instance must be set up for Yubikey for -this example to work. - -The compartment ID must be provided when running the example. - -python yubikey_example -""" - - -if len(sys.argv) != 2: - raise RuntimeError('A compartment ID must be provided') - -compartment_id = sys.argv[1] - -# Create a YubiKey signer -print("Intializing new signer") -config = oci.config.from_file() -ykpin = oci.auth.signers.YubikeyRequestSigner.get_yubikey_pin() -ybsSigner = oci.auth.signers.YubikeyRequestSigner.get_yubikey_signer(config, ykpin) -print("=" * 80) -print("Get Objectstorage namespace") -object_storage_client = oci.object_storage.ObjectStorageClient(config, signer=ybsSigner) -print(object_storage_client.get_namespace().data) diff --git a/requirements.txt b/requirements.txt index b84c5c269a..0481ca7649 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,5 +18,4 @@ vcrpy==2.0.1 wheel<=0.39.0 circuitbreaker>=1.3.1,<2.0.0 docutils<0.18 -Jinja2<3.1 -python-pkcs11==0.7.0 ; python_version >= "3.7" and platform_system != "Windows" +Jinja2<3.1 \ No newline at end of file diff --git a/setup.py b/setup.py index f5a126ee1d..bff5d7cf05 100644 --- a/setup.py +++ b/setup.py @@ -36,8 +36,7 @@ def open_relative(*path): "pyOpenSSL>=17.5.0,<24.0.0", "python-dateutil>=2.5.3,<3.0.0", "pytz>=2016.10", - "circuitbreaker>=1.3.1,< 2.0.0", - 'python-pkcs11==0.7.0 ; python_version >= "3.7" and platform_system != "Windows"' + "circuitbreaker>=1.3.1,< 2.0.0" ] setup( diff --git a/src/oci/auth/__init__.py b/src/oci/auth/__init__.py index b4fb1da023..055e153882 100644 --- a/src/oci/auth/__init__.py +++ b/src/oci/auth/__init__.py @@ -9,7 +9,3 @@ from . import session_key_supplier # noqa: F401 from . import signers # noqa: F401 from . import rpt_path_providers # noqa: F401 -try: - from .yubikey_signer import YubikeyRequestSigner, Yubikey # noqa: F401 -except ModuleNotFoundError: - pass diff --git a/src/oci/auth/signers/yubikey_signer.py b/src/oci/auth/signers/yubikey_signer.py deleted file mode 100644 index 3523b4be46..0000000000 --- a/src/oci/auth/signers/yubikey_signer.py +++ /dev/null @@ -1,140 +0,0 @@ -# coding: utf-8 -# Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. -# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. - -import base64 -import pkcs11 -import urllib -import hashlib -import platform -import threading -from oci.auth import signers -from pkcs11.constants import Attribute -from pkcs11.mechanisms import Mechanism -from getpass import getpass -import oci.signer - -system = platform.system() - -platforms = { - "Darwin": "/usr/local/lib/opensc-pkcs11.so", - "Linux": "/usr/lib64/pkcs11/opensc-pkcs11.so", -} - -if system == 'Darwin': - provider = platforms["Darwin"] -elif system == 'Linux': - provider = platforms["Linux"] -else: - raise RuntimeError('Unsupported platform {}'.format(system)) - - -class Yubikey: - lock = threading.Lock() - - def __init__(self, pin): - self.pin = pin - - with self.lock: - self.lib = pkcs11.lib(provider) - self.token = self.lib.get_token() - - with self.token.open(user_pin=self.pin) as session: - key = session.get_key(label='PIV AUTH pubkey') - hasher = hashlib.md5() - - hasher.update(key[Attribute.VALUE]) - digest = hasher.hexdigest() - - self.fingerprint = ':'.join(a + b for a, b in zip(digest[::2], digest[1::2])) - - def sign(self, data, mechanism=Mechanism.SHA256_RSA_PKCS): - with self.lock, self.token.open(user_pin=self.pin) as session: - key = session.get_key(label='PIV AUTH key') - - return key.sign(data, mechanism=mechanism) - - def verify(self, data, signature, mechanism=Mechanism.SHA256_RSA_PKCS): - with self.lock, self.token.open(user_pin=self.pin) as session: - key = session.get_key(label='PIV AUTH pubkey') - - return key.verify(data, signature, mechanism=mechanism) - - -class YubikeyRequestSigner(signers.SecurityTokenSigner): - generic_headers = [ - 'date', - '(request-target)', - 'host' - ] - body_headers = [ - 'content-length', - 'content-type', - 'x-content-sha256', - ] - required_headers = { - 'get': generic_headers, - 'head': generic_headers, - 'delete': generic_headers, - 'put': generic_headers + body_headers, - 'post': generic_headers + body_headers - } - - def __init__(self, user, tenancy, pin): - self.yubikey = Yubikey(pin) - self.keyid = '{}/{}/{}'.format(tenancy, user, self.yubikey.fingerprint) - - def sign(self, request): - verb = request.method.lower() - host = urllib.parse.urlparse(request.url).netloc - path = request.path_url - values = [] - - for header in self.required_headers[verb]: - header = header.lower() - - if header == '(request-target)': - values.append('{}: {} {}'.format(header, verb, path)) - elif header == 'host': - values.append('{}: {}'.format(header, host)) - elif header == 'date': - values.append('{}: {}'.format(header, request.headers.get('date'))) - else: - values.append('{}: {}'.format(header, request.headers.get(header))) - - data = '\n'.join(values).encode('ascii') - signature = self.yubikey.sign(data) - - return { - 'authorization': 'Signature keyId="{}",version="{}",algorithm="{}",headers="{}",signature="{}"'.format( - self.keyid, - '1', - 'rsa-sha256', - ' '.join(self.required_headers[verb]), - base64.b64encode(signature).decode('ascii') - ) - } - - def __call__(self, request): - verb = request.method.lower() - - if verb == 'options': - return request - - oci.signer.inject_missing_headers(request, verb in ['put', 'post'], enforce_content_headers=True) - auth_header = self.sign(request) - request.headers.update(auth_header) - return request - - def get_yubikey_signer(client_config, ykpin): - signer = YubikeyRequestSigner( - client_config['user'], - client_config['tenancy'], - ykpin - ) - return signer - - def get_yubikey_pin(): - ykpin_supplier = (lambda: getpass(prompt='Enter your yubikey pin: ')) - ykpin = ykpin_supplier() - return ykpin diff --git a/src/oci/version.py b/src/oci/version.py index 444ab3b476..cc0f274367 100644 --- a/src/oci/version.py +++ b/src/oci/version.py @@ -2,4 +2,4 @@ # Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. -__version__ = "2.118.1" +__version__ = "2.118.2"