Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #340 from HewlettPackard/enhancement/enable-ssl-ce…
Browse files Browse the repository at this point in the history
…rtificate

Fixed #339
  • Loading branch information
fgbulsoni authored Nov 27, 2017
2 parents 99dbd76 + ed79be8 commit c47cb42
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@ docs/source/*
!docs/source/conf.py
!docs/source/index.rst
.vscode

#certificate files
*.crt
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# 4.4.0(Unreleased)
# 4.4.0
#### Notes
Enabled usage of a CA Certificate file for establishing a SSL connection to the HPE OneView Appliance.

#### New Resources:
- Version

#### Bug fixes & Enhancements
- [#332](https://github.com/HewlettPackard/python-hpOneView/issues/332) example scmb.py is broken with v4.x libray
- [#339](https://github.com/HewlettPackard/python-hpOneView/issues/339) Validate secure connection to OneView using a certificate file

# 4.3.0
#### Notes
Expand Down
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export ONEVIEWSDK_SESSIONID='123'
# Optional
export ONEVIEWSDK_API_VERSION='300'
export ONEVIEWSDK_AUTH_LOGIN_DOMAIN='authdomain'
export ONEVIEWSDK_SSL_CERTIFICATE='<path_to_cert.crt_file>'
export ONEVIEWSDK_PROXY='<proxy_host>:<proxy_port>'
```

Expand Down Expand Up @@ -140,6 +141,43 @@ oneview_client = OneViewClient(config)

:lock: Tip: Check the file permissions because the password is stored in clear-text.

### SSL Server Certificate

To enable the SDK to establish a SSL connection to the HPE OneView server, it is necessary to generate a CA Cert file containing the server credentials.

1. Fetch the HPE OneView Appliance CA certificate.
```bash
$ openssl s_client -showcerts -host <host> -port 443
```

2. Copy the server certificate wrapped with a header line and a footer line into a `<file_name>.crt` file.
```
-----BEGIN CERTIFICATE-----
... (HPE OneView Appliance certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----
```
When using HPE Image Streamer, the server certificate for the HPE Image Streamer should also be added to the certificates file. Example:
```
-----BEGIN CERTIFICATE-----
... (HPE OneView Appliance certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (HPE Image Streamer Appliance certificate in base64 PEM encoding) ...
-----END CERTIFICATE-----
```

3. Declare the CA Certificate location when creating a `config` dictionary.
```python
config = {
"ip": "172.16.102.82",
"credentials": {
"userName": "Administrator",
"password": "secret123"
},
"ssl_certificate": "/home/python-hpOneView/my_ov_certificate.crt"
}
```

### Proxy

If your environment requires a proxy, define the proxy properties in the JSON file using the following syntax:
Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@
# built documents.
#
# The short X.Y version.
version = u'4.3.0'
version = u'4.4.0'
# The full version, including alpha/beta/rc tags.
release = u'4.3.0'
release = u'4.4.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
3 changes: 2 additions & 1 deletion examples/config-rename.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"ip": "172.16.102.59",
"image_streamer_ip": "172.16.102.60",
"api_version": 300,
"api_version": 500,
"ssl_certificate": "",
"credentials": {
"userName": "administrator",
"authLoginDomain": "",
Expand Down
2 changes: 1 addition & 1 deletion hpOneView/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
standard_library.install_aliases()

__title__ = 'hpOneView'
__version__ = '4.3.0'
__version__ = '4.4.0'
__copyright__ = '(C) Copyright (2012-2017) Hewlett Packard Enterprise Development LP'
__license__ = 'MIT'

Expand Down
52 changes: 26 additions & 26 deletions hpOneView/connection.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
# -*- coding: utf-8 -*

"""
connection.py
~~~~~~~~~~~~~~
This module maintains communication with the appliance.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from builtins import open
from builtins import str
from future import standard_library
from future.utils import raise_from

standard_library.install_aliases()


###
# (C) Copyright (2012-2017) Hewlett Packard Enterprise Development LP
#
Expand All @@ -41,6 +21,23 @@
# THE SOFTWARE.
###

"""
connection.py
~~~~~~~~~~~~~~
This module maintains communication with the appliance.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from builtins import open
from builtins import str
from future import standard_library

standard_library.install_aliases()

import http.client
import json
import logging
Expand All @@ -49,14 +46,15 @@
import os
import ssl
import time
import traceback

from hpOneView.exceptions import HPOneViewException

logger = logging.getLogger(__name__)


class connection(object):
def __init__(self, applianceIp, api_version=300):
def __init__(self, applianceIp, api_version=300, sslBundle=False):
self._session = None
self._host = applianceIp
self._cred = None
Expand All @@ -68,8 +66,9 @@ def __init__(self, applianceIp, api_version=300):
self._proxyHost = None
self._proxyPort = None
self._doProxy = False
self._sslTrustedBundle = None
self._sslTrustAll = True
self._sslBundle = sslBundle
self._sslTrustedBundle = self.set_trusted_ssl_bundle(sslBundle)
self._nextPage = None
self._prevPage = None
self._numTotalRecords = 0
Expand All @@ -92,8 +91,9 @@ def set_proxy(self, proxyHost, proxyPort):
self._doProxy = True

def set_trusted_ssl_bundle(self, sslBundle):
self._sslTrustAll = False
self._sslTrustedBundle = sslBundle
if sslBundle:
self._sslTrustAll = False
return sslBundle

def get_session(self):
return self._session
Expand Down Expand Up @@ -434,8 +434,8 @@ def login(self, cred, verbose=False):
try:
if self._validateVersion is False:
self.validateVersion()
except Exception as e:
raise_from(HPOneViewException('Failure during login attempt.'), e)
except Exception:
raise(HPOneViewException('Failure during login attempt.\n %s' % traceback.format_exc()))

self._cred = cred
try:
Expand Down
4 changes: 2 additions & 2 deletions hpOneView/image_streamer/image_streamer_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@


class ImageStreamerClient(object):
def __init__(self, ip, session_id, api_version):
self.__connection = connection(ip, api_version)
def __init__(self, ip, session_id, api_version, sslBundle=False):
self.__connection = connection(ip, api_version, sslBundle)
self.__connection.set_session_id(session_id)
self.__golden_images = None
self.__plan_scripts = None
Expand Down
11 changes: 7 additions & 4 deletions hpOneView/oneview_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class OneViewClient(object):
DEFAULT_API_VERSION = 300

def __init__(self, config):
self.__connection = connection(config["ip"], config.get('api_version', self.DEFAULT_API_VERSION))
self.__connection = connection(config["ip"], config.get('api_version', self.DEFAULT_API_VERSION), config.get('ssl_certificate', False))
self.__image_streamer_ip = config.get("image_streamer_ip")
self.__set_proxy(config)
self.__connection.login(config["credentials"])
Expand Down Expand Up @@ -193,7 +193,6 @@ def __init__(self, config):
self.__versions = None
self.__backups = None
self.__login_details = None
# TODO: Implement: con.set_trusted_ssl_bundle(args.cert)

@classmethod
def from_json_file(cls, file_name):
Expand All @@ -217,14 +216,16 @@ def from_environment_variables(cls):
Construct OneViewClient using environment variables.
Allowed variables: ONEVIEWSDK_IP (required), ONEVIEWSDK_USERNAME (required), ONEVIEWSDK_PASSWORD (required),
ONEVIEWSDK_AUTH_LOGIN_DOMAIN, ONEVIEWSDK_API_VERSION, ONEVIEWSDK_IMAGE_STREAMER_IP, ONEVIEWSDK_SESSIONID and ONEVIEWSDK_PROXY.
ONEVIEWSDK_AUTH_LOGIN_DOMAIN, ONEVIEWSDK_API_VERSION, ONEVIEWSDK_IMAGE_STREAMER_IP, ONEVIEWSDK_SESSIONID, ONEVIEWSDK_SSL_CERTIFICATE
and ONEVIEWSDK_PROXY.
Returns:
OneViewClient:
"""
ip = os.environ.get('ONEVIEWSDK_IP', '')
image_streamer_ip = os.environ.get('ONEVIEWSDK_IMAGE_STREAMER_IP', '')
api_version = int(os.environ.get('ONEVIEWSDK_API_VERSION', OneViewClient.DEFAULT_API_VERSION))
ssl_certificate = os.environ.get('ONEVIEWSDK_SSL_CERTIFICATE', '')
username = os.environ.get('ONEVIEWSDK_USERNAME', '')
auth_login_domain = os.environ.get('ONEVIEWSDK_AUTH_LOGIN_DOMAIN', '')
password = os.environ.get('ONEVIEWSDK_PASSWORD', '')
Expand All @@ -234,6 +235,7 @@ def from_environment_variables(cls):
config = dict(ip=ip,
image_streamer_ip=image_streamer_ip,
api_version=api_version,
ssl_certificate=ssl_certificate,
credentials=dict(userName=username, authLoginDomain=auth_login_domain, password=password, sessionID=sessionID),
proxy=proxy)

Expand Down Expand Up @@ -284,7 +286,8 @@ def create_image_streamer_client(self):
"""
image_streamer = ImageStreamerClient(self.__image_streamer_ip,
self.__connection.get_session_id(),
self.__connection._apiVersion)
self.__connection._apiVersion,
self.__connection._sslBundle)

return image_streamer

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
from setuptools import setup

setup(name='hpOneView',
version='4.3.0',
version='4.4.0',
description='HPE OneView Python Library',
url='https://github.com/HewlettPackard/python-hpOneView',
download_url="https://github.com/HewlettPackard/python-hpOneView/tarball/v4.3.0",
download_url="https://github.com/HewlettPackard/python-hpOneView/tarball/v4.4.0",
author='Hewlett Packard Enterprise Development LP',
author_email='[email protected]',
license='MIT',
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ def test_get_connection_ssl_trust_all_with_proxy(self):
def test_get_connection_trusted_ssl_bundle_with_proxy(self, mock_lvl):

self.connection.set_proxy('10.0.0.1', 3128)
self.connection.set_trusted_ssl_bundle(None)
self.connection.set_trusted_ssl_bundle('/test')

conn = self.connection.get_connection()

Expand All @@ -995,7 +995,7 @@ def test_get_connection_trusted_ssl_bundle_with_proxy(self, mock_lvl):
@patch.object(ssl.SSLContext, 'load_verify_locations')
def test_get_connection_trusted_ssl_bundle(self, mock_lvl):

self.connection.set_trusted_ssl_bundle(None)
self.connection.set_trusted_ssl_bundle('/test')

conn = self.connection.get_connection()

Expand Down
3 changes: 3 additions & 0 deletions tests/unit/test_oneview_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ def test_from_environment_variables_is_passing_right_arguments_to_the_constructo
mock_cls.assert_called_once_with({'api_version': 201,
'proxy': '172.16.100.195:9999',
'ip': '172.16.100.199',
'ssl_certificate': '',
'image_streamer_ip': '172.172.172.172',
'credentials':
{'userName': 'admin',
Expand All @@ -313,6 +314,7 @@ def test_from_environment_variables_is_passing_right_arguments_to_the_constructo
'proxy': '172.16.100.195:9999',
'ip': '172.16.100.199',
'image_streamer_ip': '172.172.172.172',
'ssl_certificate': '',
'credentials':
{'userName': 'admin',
'password': 'secret123',
Expand All @@ -328,6 +330,7 @@ def test_from_environment_variables_is_passing_right_arguments_to_the_constructo
'proxy': '',
'ip': '172.16.100.199',
'image_streamer_ip': '',
'ssl_certificate': '',
'credentials':
{'userName': '',
'password': '',
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ skip_missing_interpreters = true

[flake8]
ignore = E402
max-line-length = 140
max-line-length = 160
exclude = hpOneView/__init__.py
max-complexity = 14

Expand Down

0 comments on commit c47cb42

Please sign in to comment.