diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 17fa340..08e785a 100755 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_. +==================== + 5.2.3 - 2020-03-03 +==================== + +Added +_____ + +* Added NoSQLHandleConfig.set_ssl_ca_certs() to allow the user to configure SSL + CA certificates, and NoSQLHandleConfig.get_ssl_ca_certs() to get the SSL CA + certificates setting. + ==================== 5.2.2 - 2020-02-27 ==================== diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 652ff69..8b00195 100755 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -4,13 +4,12 @@ Contributing to the Oracle NoSQL Database Python SDK *Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.* -Pull requests can be made under -`The Oracle Contributor Agreement `_ (OCA). +Pull requests can be made under `The Oracle Contributor Agreement `_ (OCA). -For pull requests to be accepted, the bottom of -your commit message must have the following line using your name and -e-mail address as it appears in the OCA Signatories list:: +For pull requests to be accepted, the bottom of your commit message must have +the following line using your name and e-mail address as it appears in the OCA +Signatories list:: Signed-off-by: Your Name @@ -18,5 +17,5 @@ This can be automatically added to pull requests by committing with:: git commit --signoff -Only pull requests from committers that can be verified as having -signed the OCA can be accepted. +Only pull requests from committers that can be verified as having signed the OCA +can be accepted. diff --git a/README-DEV.rst b/README-DEV.rst index 4fe1480..68b32ce 100644 --- a/README-DEV.rst +++ b/README-DEV.rst @@ -42,6 +42,14 @@ All tests require that your PYTHONPATH be set to the development tree: $ export PYTHONPATH=/nosql-python-sdk/src:\ $PYTHONPATH +If using on-premise Oracle NoSQL database with security enabled, the certificate +path can be specified through the REQUESTS_CA_BUNDLE environment variable: + + $ export REQUESTS_CA_BUNDLE=/certificate.pem:\ + $REQUESTS_CA_BUNDLE + +Or use the API :func:`borneo.NoSQLHandleConfig.set_ssl_ca_certs` to specify it. + Run Unit Tests -------------- diff --git a/README.rst b/README.rst index fe64079..61124e6 100644 --- a/README.rst +++ b/README.rst @@ -7,17 +7,17 @@ About This is the Python SDK for Oracle NoSQL Database. Python 2.7+ and 3.5+ are supported. The SDK provides interfaces, documentation, and examples to help -develop Python applications that connect to the Oracle NoSQL -Database Cloud Service, Oracle NoSQL Database and to the Oracle NoSQL -Cloud Simulator (which runs on a local machine). +develop Python applications that connect to the Oracle NoSQL Database Cloud +Service, Oracle NoSQL Database and to the Oracle NoSQL Cloud Simulator (which +runs on a local machine). In order to run the Oracle NoSQL Cloud Simulator, a separate download is -necessary from the Oracle NoSQL OTN download page. Throughout the -documentation the Oracle NoSQL Database Cloud Service and Cloud Simulator are -referred to as the "cloud service" while the Oracle NoSQL Database is referred -to as "on-premise." In the `API reference `_ classes and interfaces are noted if they are only -relevant to a specific environment. +necessary from the Oracle NoSQL OTN download page. Throughout the documentation, +the Oracle NoSQL Database Cloud Service and Cloud Simulator are referred to as +the "cloud service" while the Oracle NoSQL Database is referred to as +"on-premise." In the `API reference `_ classes and interfaces are noted if they are only relevant to +a specific environment. The on-premise configuration requires a running instance of the Oracle NoSQL database. In addition a running proxy service is required. See `Oracle NoSQL @@ -27,9 +27,9 @@ server-downloads.html>`_ for downloads, and see `Information about the proxy database/19.3/admin&id=NSADM-GUID-C110AF57-8B35-4C48-A82E-2621C6A5ED72>`_ for proxy configuration information. -This project is open source and maintained by Oracle Corp. The home page for -the project is `here `_ +This project is open source and maintained by Oracle Corp. The home page for the +project is `here `_. ============ Installation @@ -442,5 +442,5 @@ License Copyright (C) 2018, 2020 Oracle and/or its affiliates. All rights reserved. -This SDK is licensed under the Universal Permissive License 1.0. See -`LICENSE <./LICENSE.txt>`_ for details +This SDK is licensed under the Universal Permissive License 1.0. See `LICENSE +<./LICENSE.txt>`_ for details. diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index e4ca34d..f5b3005 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -113,7 +113,7 @@ such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such -additional attribution notices cannot be construed as modifying the License. +additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or diff --git a/docs/api/borneo.NoSQLHandleConfig.rst b/docs/api/borneo.NoSQLHandleConfig.rst index 2d8f215..cfad227 100644 --- a/docs/api/borneo.NoSQLHandleConfig.rst +++ b/docs/api/borneo.NoSQLHandleConfig.rst @@ -26,6 +26,7 @@ NoSQLHandleConfig ~NoSQLHandleConfig.get_retry_handler ~NoSQLHandleConfig.get_sec_info_timeout ~NoSQLHandleConfig.get_service_url + ~NoSQLHandleConfig.get_ssl_ca_certs ~NoSQLHandleConfig.get_ssl_cipher_suites ~NoSQLHandleConfig.get_ssl_protocol ~NoSQLHandleConfig.get_table_request_timeout @@ -38,6 +39,7 @@ NoSQLHandleConfig ~NoSQLHandleConfig.set_pool_maxsize ~NoSQLHandleConfig.set_retry_handler ~NoSQLHandleConfig.set_sec_info_timeout + ~NoSQLHandleConfig.set_ssl_ca_certs ~NoSQLHandleConfig.set_ssl_cipher_suites ~NoSQLHandleConfig.set_ssl_protocol ~NoSQLHandleConfig.set_table_request_timeout @@ -61,6 +63,7 @@ NoSQLHandleConfig .. automethod:: get_retry_handler .. automethod:: get_sec_info_timeout .. automethod:: get_service_url + .. automethod:: get_ssl_ca_certs .. automethod:: get_ssl_cipher_suites .. automethod:: get_ssl_protocol .. automethod:: get_table_request_timeout @@ -73,6 +76,7 @@ NoSQLHandleConfig .. automethod:: set_pool_maxsize .. automethod:: set_retry_handler .. automethod:: set_sec_info_timeout + .. automethod:: set_ssl_ca_certs .. automethod:: set_ssl_cipher_suites .. automethod:: set_ssl_protocol .. automethod:: set_table_request_timeout diff --git a/docs/conf.py b/docs/conf.py index 031e175..755d239 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,8 +2,8 @@ # # Configuration file for the Sphinx documentation builder. # -# This file does only contain a selection of the most common options. For a -# full list see the documentation: +# This file does only contain a selection of the most common options. For a full +# list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- @@ -33,9 +33,8 @@ # # needs_sphinx = '1.0' -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', @@ -55,8 +54,8 @@ # The master toctree document. master_doc = 'index' -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. +# The language for content autogenerated by Sphinx. Refer to documentation for a +# list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. @@ -72,31 +71,30 @@ # -- Options for HTML output ------------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. +# The theme to use for HTML and HTML Help pages. See the documentation for a +# list of builtin themes. # html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the +# further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". +# relative to this directory. They are copied after the builtin static files, so +# a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] html_static_path = [] -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. +# Custom sidebar templates, must be a dictionary that maps document names to +# template names. # -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. +# The default sidebars (for documents that don't match any pattern) are defined +# by theme itself. Builtin themes are using these templates by default: +# ``['localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']``. # # html_sidebars = {} @@ -127,8 +125,8 @@ } # Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). +# (source start file, target name, title, author, +# documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'NoSQLPythonSDK.tex', u'NoSQL Database Python SDK Documentation', u'Oracle', 'manual'), @@ -146,8 +144,8 @@ # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) +# (source start file, target name, title, author, dir menu entry, description, +# category) texinfo_documents = [ (master_doc, 'NoSQLPythonSDK', u'NoSQL Database Python SDK Documentation', author, 'NoSQLPythonSDK', 'One line description of project.', @@ -159,8 +157,8 @@ # Bibliographic Dublin Core info. epub_title = project -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. +# The unique identifier of the text. This can be a ISBN number or the project +# homepage. # # epub_identifier = '' diff --git a/docs/installation.rst b/docs/installation.rst index 548ac62..62a6194 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -237,7 +237,7 @@ the region **Regions.US_ASHBURN_1**. Information on regions can be found in region = Regions.US_ASHBURN_1 # if using a specified credentials file - credentials_file= + credentials_file = # # Create an AuthorizationProvider @@ -293,11 +293,21 @@ server-downloads.html>`_ for downloads, and see `Information about the proxy database/19.3/admin&id=NSADM-GUID-C110AF57-8B35-4C48-A82E-2621C6A5ED72>`_ for proxy configuration information. -If running a secure store a user identity must be created in the store -(separately) that has permission to perform the required operations of the -application, such as manipulated tables and data. The identity is used in the -:class:`borneo.kv.StoreAccessTokenProvider`. If the store is not secure an empty -instance of :class:`borneo.kv.StoreAccessTokenProvider` is used. For example. +If running a secure store, a certificate path should be specified through the +REQUESTS_CA_BUNDLE environment variable: + + $ export REQUESTS_CA_BUNDLE=/certificate.pem:\ + $REQUESTS_CA_BUNDLE + +Or :func:`borneo.NoSQLHandleConfig.set_ssl_ca_certs`. + +In addition, a user identity must be created in the store (separately) that has +permission to perform the required operations of the application, such as +manipulated tables and data. The identity is used in the +:class:`borneo.kv.StoreAccessTokenProvider`. + +If the store is not secure, an empty instance of +:class:`borneo.kv.StoreAccessTokenProvider` is used. For example: .. code-block:: pycon @@ -317,7 +327,7 @@ instance of :class:`borneo.kv.StoreAccessTokenProvider` is used. For example. # # Create the AuthorizationProvider for a secure store: # - ap = StoreAccessTokenProvider(userName, password) + ap = StoreAccessTokenProvider(user_name, password) # # Create the AuthorizationProvider for a not secure store: @@ -329,6 +339,11 @@ instance of :class:`borneo.kv.StoreAccessTokenProvider` is used. For example. # config = NoSQLHandleConfig(endpoint).set_authorization_provider(ap) + # + # set the certificate path if running a secure store + # + config.set_ssl_ca_certs() + # # create a handle from the configuration object # diff --git a/docs/tables.rst b/docs/tables.rst index fd69b1e..496b796 100644 --- a/docs/tables.rst +++ b/docs/tables.rst @@ -43,8 +43,8 @@ default compartment for requests in default. In addition it is possible to specify a compartment is each :class:`Request` instance. -The *set_compartment* methods take either an id (OCID) or a compartment name -or path. If a compartment name is used it may be the name of a top-level +The *set_compartment* methods take either an id (OCID) or a compartment name or +path. If a compartment name is used it may be the name of a top-level compartment. If a compartment path is used to reference a nested compartment, the path is a dot-separate path that excludes the top-level compartment of the path, for example *compartmentA.compartmentB*. @@ -62,18 +62,17 @@ This usage overrides any other setting of the compartment. E.g. ... request = GetRequest().set_table_name('compartmentA.compartmentB') -If the application is authorized using an instance principal -(see :func:`borneo.iam.SignatureProvider.create_with_instance_principal`) a -compartment must be specified either using a default or in each request, and -it **must** be specified as an id, as there is no default root compartment in -this path. +If the application is authorized using an instance principal (see +:func:`borneo.iam.SignatureProvider.create_with_instance_principal`) a +compartment must be specified either using a default or in each request, and it +**must** be specified as an id, as there is no default root compartment in this +path. An example of acquiring a NoSQL Handle for the Oracle NoSQL Cloud Service: .. code-block:: pycon - from borneo import ( - AuthorizationProvider, NoSQLHandle, NoSQLHandleConfig, Regions) + from borneo import NoSQLHandle, NoSQLHandleConfig, Regions from borneo.iam import SignatureProvider # create AuthorizationProvider @@ -81,13 +80,20 @@ An example of acquiring a NoSQL Handle for the Oracle NoSQL Cloud Service: # create handle config using the correct desired region as endpoint, add a # default compartment. - config = NoSQLHandleConfig(Regions.US_ASHBURN_1) - .set_authorization_provider(provider).set_compartment('mycompartment') + config = NoSQLHandleConfig(Regions.US_ASHBURN_1).set_authorization_provider( + provider).set_compartment('mycompartment') # create the handle handle = NoSQLHandle(config) -An example using the on-premise Oracle NoSQL Database in a secure configuration: +An example using the on-premise Oracle NoSQL Database in a secure configuration, +a certificate path should be specified through the REQUESTS_CA_BUNDLE +environment variable: + + $ export REQUESTS_CA_BUNDLE=/certificate.pem:\ + $REQUESTS_CA_BUNDLE + +Or :func:`borneo.NoSQLHandleConfig.set_ssl_ca_certs`, for example: .. code-block:: pycon @@ -95,11 +101,12 @@ An example using the on-premise Oracle NoSQL Database in a secure configuration: from borneo.kv import StoreAccessTokenProvider # create AuthorizationProvider - provider = StoreAccessTokenProvider(, ) + provider = StoreAccessTokenProvider(, ) # create handle config using the correct endpoint for the running proxy config = NoSQLHandleConfig( - 'https://localhost:443').set_authorization_provider(provider) + 'https://localhost:443').set_authorization_provider( + provider).set_ssl_ca_certs() # create the handle handle = NoSQLHandle(config) @@ -112,12 +119,12 @@ Create Tables and Indexes ------------------------- Learn how to create tables and indexes in Oracle NoSQL Database. -Creating a table is the first step of developing your application. You use -the :class:`borneo.TableRequest` class and its methods to execute Data -Definition Language (DDL) statements, such as, creating, modifying, and dropping -tables. If using the Oracle NoSQL Cloud Service or Cloud Simulator you must also -set table limits using :func:`borneo.TableRequest.set_table_limits` method. -Limits are ignored on-premise, if provided. +Creating a table is the first step of developing your application. You use the +:class:`borneo.TableRequest` class and its methods to execute Data Definition +Language (DDL) statements, such as, creating, modifying, and dropping tables. If +using the Oracle NoSQL Cloud Service or Cloud Simulator you must also set table +limits using :func:`borneo.TableRequest.set_table_limits` method. Limits are +ignored on-premise, if provided. Before creating a table, learn about: @@ -152,7 +159,7 @@ exists to combine execution of the operation with waiting for completion. .. code-block:: pycon - from borneo import State, TableLimits, TableRequest + from borneo import TableLimits, TableRequest statement = 'create table if not exists users(id integer, name string, ' + 'primary key(id)' @@ -160,7 +167,7 @@ exists to combine execution of the operation with waiting for completion. # In the Cloud Service TableLimits is a required object for table creation. # It specifies the throughput and capacity for the table in ReadUnits, # WriteUnits, GB - request = TableRequest().set_statement(statement).set_tableLimits( + request = TableRequest().set_statement(statement).set_table_limits( TableLimits(20, 10, 5)) # assume that a handle has been created, as handle, make the request wait @@ -293,10 +300,10 @@ Use Queries ----------- Learn about using queries in your application. -Oracle NoSQL Database provides a rich query language to read and -update data. See the `SQL For NoSQL Specification `_ for a full -description of the query language. +Oracle NoSQL Database provides a rich query language to read and update data. +See the `SQL For NoSQL Specification `_ for a full description of the +query language. To execute a query use the :func:`borneo.NoSQLHandle.query` method. For example, to execute a *SELECT* query to read data from your table: @@ -325,6 +332,7 @@ the query loop should continue. For example: .. code-block:: pycon from borneo import QueryRequest + statement = 'select * from users where name = "Taylor"' request = QueryRequest().set_statement(statement) result = handle.query(request) @@ -396,8 +404,8 @@ value: if result.get_success(): # success -- the row was deleted - # if the row didn't exist or was not deleted for any other reason, - # False is returned + # if the row didn't exist or was not deleted for any other reason, False is + # returned Delete operations can be conditional based on a :class:`borneo.Version` returned from a get operation. See :class:`borneo.DeleteRequest`. @@ -435,11 +443,11 @@ using :func:`borneo.TableRequest.set_table_limits`, for example: # in this path the table name is required, as there is no DDL statement request = TableRequest().set_table_name('users') - request.set_tableLimits( TableLimits(40, 10, 5)) + request.set_table_limits(TableLimits(40, 10, 5)) result = handle.table_request(request) - # table_request is asynchronous, so wait for the operation to complete - # wait for 40 seconds, polling every 3 seconds + # table_request is asynchronous, so wait for the operation to complete, wait + # for 40 seconds, polling every 3 seconds result.wait_for_completion(handle, 40000, 3000) @@ -467,17 +475,16 @@ for example:: statement = 'drop table users' request = TableRequest().set_statement(statement) - # perform the operation - # wait for 40 seconds, polling every 3 seconds + # perform the operation, wait for 40 seconds, polling every 3 seconds result = handle.do_table_request(request, 40000, 3000) ------------- Handle Errors ------------- -Python errors are raised as exceptions defined as part of the API. They are -all instances of Python's :class:`RuntimeError`. Most exceptions are instances -of :class:`borneo.NoSQLException` which is a base class for exceptions raised by +Python errors are raised as exceptions defined as part of the API. They are all +instances of Python's :class:`RuntimeError`. Most exceptions are instances of +:class:`borneo.NoSQLException` which is a base class for exceptions raised by the Python driver. Exceptions are split into 2 broad categories: diff --git a/examples/parameters.py b/examples/parameters.py index 57a2f32..e306d7b 100644 --- a/examples/parameters.py +++ b/examples/parameters.py @@ -113,6 +113,11 @@ # appropriate host:port for the proxy) endpoint = 'localhost:8080' +# On-premise only: +# Non-secure store: None +# Secure store: your CA certificate path +ca_certs = None + # On-premise only: # Non-secure store: None # Secure store: your store user name diff --git a/examples/utils.py b/examples/utils.py index 6f2bec5..0bc1cf2 100644 --- a/examples/utils.py +++ b/examples/utils.py @@ -14,8 +14,8 @@ from borneo.kv import StoreAccessTokenProvider from parameters import ( - credentials_file, endpoint, password, principal, user_name, using_cloud_sim, - using_on_prem, using_service) + ca_certs, credentials_file, endpoint, password, principal, user_name, + using_cloud_sim, using_on_prem, using_service) class ExampleAuthorizationProvider(AuthorizationProvider): @@ -72,4 +72,6 @@ def get_handle(tenant_id): config = NoSQLHandleConfig(endpoint).set_authorization_provider( create_authorization_provider(tenant_id)).set_default_compartment( tenant_id) + if ca_certs is not None: + config.set_ssl_ca_certs(ca_certs) return NoSQLHandle(config) diff --git a/src/borneo/config.py b/src/borneo/config.py index dab62c2..62b1c34 100644 --- a/src/borneo/config.py +++ b/src/borneo/config.py @@ -512,6 +512,7 @@ def __init__(self, endpoint=None, provider=None): self._proxy_port = 0 self._proxy_username = None self._proxy_password = None + self._ssl_ca_certs = None self._ssl_ciphers = None self._ssl_ctx = None self._ssl_protocol = None @@ -973,6 +974,35 @@ def get_proxy_password(self): """ return self._proxy_password + def set_ssl_ca_certs(self, ssl_ca_certs): + """ + On-premise only. + + When running against on-premise Oracle NoSQL Database with security + enabled, certificates should be specified using this method. Otherwise + environment variable REQUESTS_CA_BUNDLE should be configured. See `the + installation guide `_ for the configuration of REQUESTS_CA_BUNDLE. + + :param ssl_ca_certs: ssl ca certificates. + :type ssl_ca_certs: str + :returns: self. + :raises IllegalArgumentException: raises the exception if ssl_ca_certs + is not a string. + """ + CheckValue.check_str(ssl_ca_certs, 'ssl_ca_certs') + self._ssl_ca_certs = ssl_ca_certs + return self + + def get_ssl_ca_certs(self): + """ + Returns the SSL CA certificates. + + :returns: ssl ca certificates. + :rtype: str + """ + return self._ssl_ca_certs + def set_ssl_cipher_suites(self, ssl_ciphers): """ Set SSL cipher suites to enable. diff --git a/src/borneo/driver.py b/src/borneo/driver.py index 6b90723..ad2b7d2 100644 --- a/src/borneo/driver.py +++ b/src/borneo/driver.py @@ -692,6 +692,8 @@ def _config_ssl_context(config): ctx = SSLContext(config.get_ssl_protocol()) if config.get_ssl_cipher_suites() is not None: ctx.set_ciphers(config.get_ssl_cipher_suites()) + if config.get_ssl_ca_certs() is not None: + ctx.load_verify_locations(config.get_ssl_ca_certs()) config.set_ssl_context(ctx) except (SSLError, ValueError) as err: raise IllegalArgumentException(str(err)) diff --git a/src/borneo/version.py b/src/borneo/version.py index 617e4f2..583cb77 100644 --- a/src/borneo/version.py +++ b/src/borneo/version.py @@ -7,4 +7,4 @@ # appropriate download for a copy of the license and additional information. # -__version__ = '5.2.0' +__version__ = '5.2.3' diff --git a/test/handle_config.py b/test/handle_config.py index 9d121dc..0387b4a 100644 --- a/test/handle_config.py +++ b/test/handle_config.py @@ -16,11 +16,11 @@ DefaultRetryHandler, Regions, RetryableException, RetryHandler, SecurityInfoNotReadyException, NoSQLHandle, NoSQLHandleConfig, TableRequest) from parameters import ( - consistency, endpoint, pool_connections, pool_maxsize, security, table_name, - tenant_id, timeout, table_request_timeout) + ca_certs, consistency, endpoint, pool_connections, pool_maxsize, security, + table_name, tenant_id, timeout, table_request_timeout) from testutils import ( - get_handle_config, get_simple_handle_config, proxy_host, proxy_port, - proxy_username, proxy_password, retry_handler, sec_info_timeout, + fake_key_file, get_handle_config, get_simple_handle_config, proxy_host, + proxy_port, proxy_username, proxy_password, retry_handler, sec_info_timeout, ssl_cipher_suites, ssl_protocol) @@ -162,6 +162,16 @@ def testNoSQLHandleConfigSetIllegalLogger(self): self.assertRaises(IllegalArgumentException, self.config.set_logger, 'IllegalLogger') + def testNoSQLHandleConfigSetIllegalSSLCACerts(self): + self.assertRaises(IllegalArgumentException, + self.config.set_ssl_ca_certs, + {'IllegalCACerts': 'IllegalCACerts'}) + if security(): + # set illegal CA certs + config = get_simple_handle_config(tenant_id).set_ssl_ca_certs( + fake_key_file) + self.assertRaises(IllegalArgumentException, NoSQLHandle, config) + def testNoSQLHandleConfigSetIllegalSSLCipherSuites(self): self.assertRaises(IllegalArgumentException, self.config.set_ssl_cipher_suites, @@ -363,6 +373,8 @@ def _check_config(self, config, service_url, handler): self.assertEqual(config.get_proxy_password(), proxy_password) # check authorization provider self.assertIsNotNone(config.get_authorization_provider()) + # check ssl ca certs + self.assertEqual(config.get_ssl_ca_certs(), ca_certs) # check ssl cipher suites self.assertEqual(config.get_ssl_cipher_suites(), ssl_cipher_suites) # check ssl protocol diff --git a/test/parameters.py b/test/parameters.py index 69018a9..55a8a7f 100644 --- a/test/parameters.py +++ b/test/parameters.py @@ -51,6 +51,10 @@ # on-prem proxy started by the customer. Unit tests can be run against both the # Cloud Simulator and on-prem proxy. endpoint = 'localhost:8080' +# SSL CA certificates for on-prem proxy. Configure it to specify CA certificates +# or set REQUESTS_CA_BUNDLE environment variable when running against a secure +# store. For non-secure store, use the default None. +ca_certs = None # User name for on-prem proxy, for non-secure store, use the default None. user_name = None # Password for on-prem proxy, for non-secure store, use the default None. diff --git a/test/testutils.py b/test/testutils.py index fd02295..7df976d 100644 --- a/test/testutils.py +++ b/test/testutils.py @@ -22,9 +22,9 @@ from borneo.iam import SignatureProvider from borneo.kv import StoreAccessTokenProvider from parameters import ( - consistency, endpoint, iam_principal, is_cloudsim, is_dev_pod, is_minicloud, - is_onprem, is_prod_pod, logger_level, password, pool_connections, - pool_maxsize, table_request_timeout, timeout, user_name) + ca_certs, consistency, endpoint, iam_principal, is_cloudsim, is_dev_pod, + is_minicloud, is_onprem, is_prod_pod, logger_level, password, + pool_connections, pool_maxsize, table_request_timeout, timeout, user_name) # The sc endpoint port for setting the tier. sc_endpoint = 'localhost:13600' @@ -80,6 +80,12 @@ def get_handle_config(tenant_id): config.set_proxy_username(proxy_username) if proxy_password is not None: config.set_proxy_password(proxy_password) + if ssl_cipher_suites is not None: + config.set_ssl_cipher_suites(ssl_cipher_suites) + if ssl_protocol is not None: + config.set_ssl_protocol(ssl_protocol) + if ca_certs is not None: + config.set_ssl_ca_certs(ca_certs) set_authorization_provider(config, tenant_id) return config