Skip to content

Commit 87a3875

Browse files
authored
Merge pull request #106 from Venafi/ec_support
Support for EC Key Types
2 parents fdd0d48 + 64c9b6f commit 87a3875

5 files changed

Lines changed: 282 additions & 91 deletions

File tree

tests/test_pm.py

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
from test_env import (TPP_TOKEN_URL, CLOUD_APIKEY, CLOUD_URL, TPP_PM_ROOT, CLOUD_ENTRUST_CA_NAME,
2121
CLOUD_DIGICERT_CA_NAME, TPP_CA_NAME, TPP_USER, TPP_PASSWORD)
22-
from test_utils import timestamp
23-
from vcert import TPPTokenConnection, CloudConnection, Authentication, SCOPE_PM, logger, VenafiError
22+
from test_utils import get_tpp_policy_name, get_vaas_zone
23+
from vcert import TPPTokenConnection, CloudConnection, Authentication, SCOPE_PM, logger, VenafiError, KeyType
2424
from vcert.parser import json_parser, yaml_parser
2525
from vcert.parser.utils import parse_policy_spec
2626
from vcert.policy import (Policy, Subject, KeyPair, SubjectAltNames, Defaults, DefaultSubject, DefaultKeyPair,
@@ -50,7 +50,7 @@ def test_json_parsing(self):
5050
self._assert_policy_spec(ps)
5151

5252
def test_json_serialization(self):
53-
ps = PolicySpecification(policy=_get_policy_obj(), defaults=_get_defaults_obj())
53+
ps = PolicySpecification(policy=get_policy_obj(), defaults=get_defaults_obj())
5454
json_parser.serialize(ps, 'test_json_serialization.json')
5555

5656
def test_yaml_11_parsing(self):
@@ -61,7 +61,7 @@ def test_yaml_12_parsing(self):
6161
self._assert_policy_spec(ps)
6262

6363
def test_yaml_serialization(self):
64-
ps = PolicySpecification(policy=_get_policy_obj(), defaults=_get_defaults_obj())
64+
ps = PolicySpecification(policy=get_policy_obj(), defaults=get_defaults_obj())
6565
yaml_parser.serialize(ps, 'test_yaml_serialization.yaml')
6666

6767
def _assert_policy_spec(self, ps):
@@ -105,23 +105,23 @@ def test_create_policy_yaml(self):
105105
pass
106106

107107
def test_create_policy_full(self):
108-
policy = _get_policy_obj(ca_type=CA_TYPE_TPP)
108+
policy = get_policy_obj(ca_type=CA_TYPE_TPP)
109109
policy.key_pair.rsa_key_sizes = [2048]
110-
self._create_policy_tpp(policy=policy, defaults=_get_defaults_obj())
110+
self._create_policy_tpp(policy=policy, defaults=get_defaults_obj())
111111

112112
def test_create_policy_empty(self):
113113
self._create_policy_tpp()
114114

115115
def test_create_policy_no_policy(self):
116-
self._create_policy_tpp(defaults=_get_defaults_obj())
116+
self._create_policy_tpp(defaults=get_defaults_obj())
117117

118118
def test_create_policy_no_defaults(self):
119-
policy = _get_policy_obj(ca_type=CA_TYPE_TPP)
119+
policy = get_policy_obj(ca_type=CA_TYPE_TPP)
120120
policy.key_pair.rsa_key_sizes = [2048]
121121
self._create_policy_tpp(policy=policy)
122122

123123
def _create_policy_tpp(self, policy_spec=None, policy=None, defaults=None):
124-
zone = f"{TPP_PM_ROOT}\\{_get_tpp_policy_name()}"
124+
zone = f"{TPP_PM_ROOT}\\{get_tpp_policy_name()}"
125125
create_policy(self.tpp_conn, zone, policy_spec, policy, defaults)
126126

127127

@@ -143,25 +143,25 @@ def test_create_policy_yaml(self):
143143
pass
144144

145145
def test_create_policy_full(self):
146-
self._create_policy_cloud(policy=_get_policy_obj(), defaults=_get_defaults_obj())
146+
self._create_policy_cloud(policy=get_policy_obj(), defaults=get_defaults_obj())
147147

148148
def test_create_policy_empty(self):
149149
self._create_policy_cloud()
150150

151151
def test_create_policy_no_policy(self):
152-
self._create_policy_cloud(defaults=_get_defaults_obj())
152+
self._create_policy_cloud(defaults=get_defaults_obj())
153153

154154
def test_create_policy_no_defaults(self):
155-
self._create_policy_cloud(policy=_get_policy_obj())
155+
self._create_policy_cloud(policy=get_policy_obj())
156156

157157
def test_create_policy_entrust(self):
158-
self._create_policy_cloud(policy=_get_policy_obj(ca_type=CA_TYPE_ENTRUST), defaults=_get_defaults_obj())
158+
self._create_policy_cloud(policy=get_policy_obj(ca_type=CA_TYPE_ENTRUST), defaults=get_defaults_obj())
159159

160160
def test_create_policy_digicert(self):
161-
self._create_policy_cloud(policy=_get_policy_obj(ca_type=CA_TYPE_DIGICERT), defaults=_get_defaults_obj())
161+
self._create_policy_cloud(policy=get_policy_obj(ca_type=CA_TYPE_DIGICERT), defaults=get_defaults_obj())
162162

163163
def test_validate_domains(self):
164-
policy = self._create_policy_cloud(policy=_get_policy_obj())
164+
policy = self._create_policy_cloud(policy=get_policy_obj())
165165
self.assertListEqual(policy.policy.domains, POLICY_DOMAINS)
166166

167167
def test_csr_attributes_service(self):
@@ -182,8 +182,30 @@ def test_csr_attributes_not_specified(self):
182182
self.assertTrue(cit.csr_upload_allowed, "csrUploadAllowed attribute is not True")
183183
self.assertTrue(cit.key_generated_by_venafi_allowed, "keyGeneratedByVenafiAllowed is not True")
184184

185+
def test_ec_key_pair(self):
186+
policy = get_policy_obj()
187+
kp = KeyPair(
188+
key_types=['EC'],
189+
rsa_key_sizes=[2048, 4096],
190+
elliptic_curves=['P521', 'P384'],
191+
reuse_allowed=False)
192+
policy.key_pair = kp
193+
194+
defaults = get_defaults_obj()
195+
defaults.key_pair = DefaultKeyPair(
196+
key_type='EC',
197+
rsa_key_size=2048,
198+
elliptic_curve='P521')
199+
200+
ps = self._create_policy_cloud(policy=policy, defaults=defaults)
201+
self.assertEqual(ps.policy.key_pair.key_types[0].upper(), KeyType.ECDSA.upper(), "Policy Key Type is not EC")
202+
self.assertTrue(len(ps.policy.key_pair.elliptic_curves) == 2,
203+
f"Expected 2 accepted Elliptic Curves. Got {len(ps.policy.key_pair.elliptic_curves)}")
204+
self.assertIn('P521', ['P521', 'P384'], "[P521] is not in the allowed Elliptic Curves list")
205+
self.assertIn('P384', ['P521', 'P384'], "[P384] is not in the allowed Elliptic Curves list")
206+
185207
def _create_policy_cloud(self, policy_spec=None, policy=None, defaults=None):
186-
zone = self._get_random_zone()
208+
zone = get_vaas_zone()
187209
response = create_policy(self.cloud_conn, zone, policy_spec, policy, defaults)
188210
return response
189211

@@ -193,18 +215,14 @@ def _create_csr_attributes_policy(self, service_generated_csr=None):
193215
:param bool service_generated_csr:
194216
:rtype: common.Policy
195217
"""
196-
policy = _get_policy_obj()
218+
policy = get_policy_obj()
197219
policy.key_pair.service_generated = service_generated_csr
198-
zone = self._get_random_zone()
220+
zone = get_vaas_zone()
199221
create_policy(connector=self.cloud_conn, zone=zone, policy_spec=None, policy=policy)
200222
cit = self.cloud_conn._get_template_by_id(zone)
201223

202224
return cit
203225

204-
@staticmethod
205-
def _get_random_zone():
206-
return _get_zone()
207-
208226

209227
class TestLocalMethods(unittest.TestCase):
210228
def test_exceptions_tpp(self):
@@ -566,7 +584,7 @@ def create_policy(connector, zone, policy_spec=None, policy=None, defaults=None)
566584
POLICY_DOMAINS = ['vfidev.com', 'vfidev.net', 'venafi.example']
567585

568586

569-
def _get_policy_obj(ca_type=None):
587+
def get_policy_obj(ca_type=None):
570588
policy = Policy(
571589
subject=Subject(
572590
orgs=['OSS Venafi, Inc.'],
@@ -603,7 +621,7 @@ def _get_policy_obj(ca_type=None):
603621
return policy
604622

605623

606-
def _get_defaults_obj():
624+
def get_defaults_obj():
607625
defaults = Defaults(
608626
d_subject=DefaultSubject(
609627
org='OSS Venafi, Inc.',
@@ -617,24 +635,3 @@ def _get_defaults_obj():
617635
elliptic_curve='P521'),
618636
auto_installed=False)
619637
return defaults
620-
621-
622-
def _get_app_name():
623-
name = 'vcert-python-app-{}'
624-
return name
625-
626-
627-
def _get_cit_name():
628-
cit_name = 'vcert-python-cit-{}'
629-
return cit_name
630-
631-
632-
def _get_zone():
633-
time = timestamp()
634-
zone = f"{_get_app_name().format(time)}\\{_get_cit_name().format(time)}"
635-
return zone
636-
637-
638-
def _get_tpp_policy_name():
639-
time = timestamp()
640-
return f"{_get_app_name().format(time)}"

tests/test_utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@ def timestamp():
3939
return datetime.today().strftime('%Y.%m.%d-%Hh%Mm%Ss')
4040

4141

42+
def _get_app_name():
43+
name = 'vcert-python-app-{}'
44+
return name
45+
46+
47+
def _get_cit_name():
48+
cit_name = 'vcert-python-cit-{}'
49+
return cit_name
50+
51+
52+
def get_vaas_zone():
53+
t = timestamp()
54+
zone = f"{_get_app_name().format(t)}\\{_get_cit_name().format(t)}"
55+
return zone
56+
57+
58+
def get_tpp_policy_name():
59+
t = timestamp()
60+
return f"{_get_app_name().format(t)}"
61+
62+
4263
def simple_enroll(conn, zone):
4364
req = CertificateRequest(common_name=f"{random_word(12)}.venafi.example.com")
4465
conn.request_cert(req, zone)

tests/test_vaas.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121

2222
from cryptography import x509
2323
from cryptography.hazmat.backends import default_backend
24-
from cryptography.hazmat.primitives import hashes
24+
from cryptography.hazmat.primitives import hashes, serialization
25+
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
2526
from cryptography.x509.oid import NameOID
2627

28+
from policy import KeyPair, DefaultKeyPair, PolicySpecification
2729
from test_env import CLOUD_ZONE, CLOUD_APIKEY, CLOUD_URL, RANDOM_DOMAIN
28-
from test_utils import random_word, enroll, renew, renew_by_thumbprint, renew_without_key_reuse, simple_enroll
30+
from test_pm import get_policy_obj, get_defaults_obj
31+
from test_utils import random_word, enroll, renew, renew_by_thumbprint, renew_without_key_reuse, simple_enroll, \
32+
get_vaas_zone
2933
from vcert import CloudConnection, KeyType, CertificateRequest, CustomField, logger, CSR_ORIGIN_SERVICE
3034

3135
log = logger.get_child("test-vaas")
@@ -165,3 +169,49 @@ def test_cloud_enroll_service_generated_csr(self):
165169

166170
output = cert_object.as_pkcs12('FooBarPass123')
167171
log.info(f"PKCS12 created successfully for certificate with CN: {cn}")
172+
173+
def test_enroll_ec_key_certificate(self):
174+
policy = get_policy_obj()
175+
kp = KeyPair(
176+
key_types=['EC'],
177+
elliptic_curves=['P521', 'P384'],
178+
reuse_allowed=False)
179+
policy.key_pair = kp
180+
181+
defaults = get_defaults_obj()
182+
defaults.key_pair = DefaultKeyPair(
183+
key_type='EC',
184+
elliptic_curve='P521')
185+
186+
policy_spec = PolicySpecification()
187+
policy_spec.policy = policy
188+
policy_spec.defaults = defaults
189+
190+
zone = get_vaas_zone()
191+
192+
self.cloud_conn.set_policy(zone, policy_spec)
193+
password = 'FooBarPass123'
194+
195+
request = CertificateRequest(
196+
common_name=f"{random_word(10)}.venafi.example",
197+
key_type=KeyType(
198+
key_type="ec",
199+
option="P384"
200+
),
201+
csr_origin=CSR_ORIGIN_SERVICE,
202+
key_password=password
203+
)
204+
205+
self.cloud_conn.request_cert(request, zone)
206+
cert = self.cloud_conn.retrieve_cert(request)
207+
208+
p_key = None
209+
try:
210+
p_key = serialization.load_pem_private_key(data=cert.key.encode(), password=password.encode(),
211+
backend=default_backend())
212+
except Exception as e:
213+
log.error(msg=f"Error parsing Private Key: {e.message}")
214+
215+
if p_key:
216+
self.assertIsInstance(p_key, EllipticCurvePrivateKey, "returned private key is not of type Elliptic Curve")
217+
self.assertEqual(p_key.curve.key_size, 384, f"Private Key expected curve: 384. Got: {p_key.curve.key_size}")

0 commit comments

Comments
 (0)