Skip to content

Commit 3ad2e2a

Browse files
authored
Implement VDC keystore service (#41)
* Implement VDC keystore service including a sample key and certificate * Show VDC keystore as supported in readme file * Add warning to VDC keystore update method
1 parent 611967e commit 3ad2e2a

File tree

10 files changed

+101
-10
lines changed

10 files changed

+101
-10
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ The following table shows the supported endpoints per API version.
195195
+--------------------------+---------+---------+
196196
| Virtual Data Center |||
197197
+--------------------------+---------+---------+
198-
| VDC Keystore | | |
198+
| VDC Keystore | | |
199199
+--------------------------+---------+---------+
200200
| **Support** |
201201
+--------------------------+---------+---------+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import logging
2+
3+
log = logging.getLogger(__name__)
4+
5+
6+
class VdcKeystore(object):
7+
def __init__(self, connection):
8+
"""
9+
Initialize a new instance
10+
"""
11+
self.conn = connection
12+
13+
def get(self):
14+
"""
15+
Get the certificate chain being used by ECS.
16+
17+
Required role(s):
18+
19+
This call has no restrictions.
20+
21+
Example JSON result from the API:
22+
23+
{
24+
"chain": "-----BEGIN CERTIFICATE-----\nMIIDBjCCAe4..."
25+
}
26+
"""
27+
log.info("Getting the certificate chain")
28+
return self.conn.get('vdc/keystore')
29+
30+
def set(self, private_key, certificate_chain):
31+
"""
32+
Set the private key and certificate chain being used by ECS.
33+
WARNING: Note that the certificate will not be updated until ECS is
34+
restarted. Restarting ECS is out of the scope of this library.
35+
36+
Required role(s):
37+
38+
SYSTEM_ADMIN
39+
40+
Example JSON result from the API:
41+
42+
{
43+
"chain": "-----BEGIN CERTIFICATE-----\nMIIDBjCCAe4..."
44+
}
45+
46+
:param private_key: The private key to be set
47+
:param certificate_chain: The certificate chain to be set
48+
"""
49+
payload = {
50+
"key_and_certificate": {
51+
"private_key": private_key,
52+
"certificate_chain": certificate_chain
53+
}
54+
}
55+
56+
log.info("Setting the private key and certificate chain (ECS must be "
57+
"restarted for this change to take effect)")
58+
return self.conn.put('vdc/keystore', json_payload=payload)

ecsclient/schemas.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,13 @@
786786
"groups_list"
787787
]
788788
}
789+
790+
VDC_KEYSTORE = {
791+
"type": "object",
792+
"properties": {
793+
"chain": {"type": "string"}
794+
},
795+
"required": [
796+
"chain"
797+
]
798+
}

ecsclient/v2/client.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from ecsclient.v2.configuration import certificate, configuration_properties, licensing
66
from ecsclient.v2.configuration import feature
77
from ecsclient.v2.geo_replication import replication_group, temporary_failed_zone
8-
from ecsclient.v2.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center, node
8+
from ecsclient.v2.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center, node, \
9+
vdc_keystore
910
from ecsclient.v2.metering import billing
1011
from ecsclient.v2.monitoring import capacity, dashboard, events
1112
from ecsclient.v2.multitenancy import namespace
@@ -61,7 +62,7 @@ def __init__(self, *args, **kwargs):
6162
self.node = node.Node(self)
6263
self.storage_pool = storage_pool.StoragePool(self)
6364
self.vdc = virtual_data_center.VirtualDataCenter(self)
64-
# TODO: vdc_keystore = vdc_keystore.VdcKeystore(self)
65+
self.vdc_keystore = vdc_keystore.VdcKeystore(self)
6566

6667
# Support
6768
# TODO: self.call_home = call_home.CallHome(self)

ecsclient/v2/provisioning/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from ecsclient.common.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center, node
1+
from ecsclient.common.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center, node, \
2+
vdc_keystore
23

34
base_url = base_url
45
bucket = bucket
56
data_store = data_store
67
storage_pool = storage_pool
78
virtual_data_center = virtual_data_center
89
node = node
10+
vdc_keystore = vdc_keystore

ecsclient/v3/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from ecsclient.v3.monitoring import capacity, dashboard, events
99
from ecsclient.v3.multitenancy import namespace
1010
from ecsclient.v3.geo_replication import replication_group, temporary_failed_zone
11-
from ecsclient.v2.provisioning import base_url, bucket, data_store, storage_pool, \
12-
virtual_data_center, node
11+
from ecsclient.v3.provisioning import base_url, bucket, data_store, storage_pool, \
12+
virtual_data_center, node, vdc_keystore
1313
from ecsclient.v3.user_management import authentication_provider, management_user, \
1414
object_user, secret_key, password_group
1515
from ecsclient.v3.other import user_info
@@ -64,7 +64,7 @@ def __init__(self, *args, **kwargs):
6464
self.node = node.Node(self)
6565
self.storage_pool = storage_pool.StoragePool(self)
6666
self.vdc = virtual_data_center.VirtualDataCenter(self)
67-
# TODO: vdc_keystore = vdc_keystore.VdcKeystore(self)
67+
self.vdc_keystore = vdc_keystore.VdcKeystore(self)
6868

6969
# Support
7070
# TODO: self.call_home = call_home.CallHome(self)

ecsclient/v3/provisioning/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from ecsclient.common.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center
1+
from ecsclient.common.provisioning import base_url, bucket, data_store, storage_pool, virtual_data_center, vdc_keystore
22

33
base_url = base_url
44
bucket = bucket
55
data_store = data_store
66
storage_pool = storage_pool
77
virtual_data_center = virtual_data_center
8+
vdc_keystore = vdc_keystore

tests/functional/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self, *args, **kwargs):
1616

1717
def _get_config(self):
1818
config_file = os.environ.get('ECS_TEST_CONFIG_FILE',
19-
'/home/ubuntu/src/test.conf')
19+
os.path.join(os.getcwd(), "tests/test.conf"))
2020
config = configparser.ConfigParser()
2121
config.read(config_file)
2222
self.config = config

tests/functional/test_vdc_keystore.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from ecsclient import schemas
2+
from tests import functional
3+
from tests.functional import helper
4+
5+
6+
class TestVdcKeystore(functional.BaseTestCase):
7+
8+
def test_vdc_keystore_get(self):
9+
response = self.client.vdc_keystore.get()
10+
self.assertValidSchema(response, schemas.VDC_KEYSTORE)
11+
12+
def test_vdc_keystore_set(self):
13+
private_key = helper.get_sample_private_key()
14+
certificate = helper.get_sample_certificate()
15+
response = self.client.vdc_keystore.set(private_key, certificate)
16+
self.assertValidSchema(response, schemas.VDC_KEYSTORE)
17+
# Can't validate the certificate and private key at this point
18+
# because it does not take effect until the ECS is manually restarted
19+
# self.assertSameCertificate(certificate, response['chain'])

tests/sample.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ ecs_endpoint = https://10.0.1.1:4443
66
username = root
77
password = ChangeMe
88
api_version = 3
9-
license_file = /home/user/license.lic
9+
license_file = /home/user/license.lic

0 commit comments

Comments
 (0)