Skip to content

Commit 4151b08

Browse files
authored
Merge pull request #88 from Venafi/svc_gen_csr_fixes
Added step to fill empty request attributes with zone default values
2 parents 3472909 + 80685c6 commit 4151b08

6 files changed

Lines changed: 90 additions & 61 deletions

File tree

vcert/common.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def __init__(self, policy_id=None, company_id=None, name=None, system_generated=
183183
:param str status:
184184
:param str reason:
185185
:param str validity_period:
186-
:param RecommendedSettings recommended_settings:
186+
:param vaas_utils.RecommendedSettings recommended_settings:
187187
"""
188188
self.id = policy_id
189189
self.company_id = company_id
@@ -264,11 +264,11 @@ def __init__(self, cert_id=None,
264264
:param str friendly_name: Name for certificate in the platform. If not specified common name will be used.
265265
:param str common_name: Common name of certificate. Usually domain name.
266266
:param str thumbprint: Certificate thumbprint. Can be used for identifying certificate on the platform.
267-
:param organization:
268-
:param organizational_unit:
269-
:param country:
270-
:param province:
271-
:param locality:
267+
:param str organization:
268+
:param str or list[str] organizational_unit:
269+
:param str country:
270+
:param str province:
271+
:param str locality:
272272
:param str origin: application identifier
273273
:param list[CustomField] custom_fields: list of custom fields values to be added to the certificate.
274274
:param int timeout: Timeout for the certificate to be retrieved from server. Measured in seconds.
@@ -496,7 +496,6 @@ def public_key_pem(self):
496496
).decode()
497497

498498
def update_from_zone_config(self, zone):
499-
# TODO: check request against zone configuration
500499
"""
501500
:param ZoneConfig zone:
502501
"""
@@ -588,6 +587,8 @@ def __init__(self, user=None, password=None, access_token=None, refresh_token=No
588587

589588

590589
class CommonConnection:
590+
def __init__(self):
591+
pass
591592

592593
def auth(self):
593594
"""

vcert/connection_cloud.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import requests
2626
import six.moves.urllib.parse as urlparse
2727
from nacl.public import SealedBox
28+
from six import string_types
2829

2930
from .common import (ZoneConfig, CertificateRequest, CommonConnection, Policy, get_ip_address, log_errors, MIME_JSON,
3031
MIME_TEXT, MIME_ANY, CertField, KeyType, DEFAULT_TIMEOUT,
@@ -357,6 +358,9 @@ def request_cert(self, request, zone):
357358
'identifier': ip_address
358359
}
359360
}
361+
zone_config = self.read_zone_conf(zone)
362+
request.update_from_zone_config(zone_config)
363+
360364
if request.csr_origin != CSR_ORIGIN_SERVICE:
361365
if not request.csr:
362366
request.build_csr()
@@ -540,12 +544,25 @@ def search_by_thumbprint(self, thumbprint, timeout=DEFAULT_TIMEOUT):
540544

541545
def read_zone_conf(self, zone):
542546
policy = self._get_template_by_id(zone)
547+
rs = policy.recommended_settings
548+
org = CertField("")
549+
org_unit = CertField("")
550+
locality = CertField("")
551+
state = CertField("")
552+
country = CertField("")
553+
if rs:
554+
org = CertField(rs.subjectOValue)
555+
org_unit = CertField(rs.subjectOUValue)
556+
locality = CertField(rs.subjectLValue)
557+
state = CertField(rs.subjectSTValue)
558+
country = CertField(rs.subjectCValue)
559+
543560
z = ZoneConfig(
544-
organization=CertField(""),
545-
organizational_unit=CertField(""),
546-
country=CertField(""),
547-
province=CertField(""),
548-
locality=CertField(""),
561+
organization=org,
562+
organizational_unit=org_unit,
563+
country=country,
564+
province=state,
565+
locality=locality,
549566
policy=policy,
550567
key_type=policy.key_types[0] if policy.key_types else None,
551568
)
@@ -736,9 +753,16 @@ def _get_service_generated_csr_attr(self, request, zone):
736753
csr_attr_map[CSR_ATTR_ORG] = ps.defaults.subject.org
737754

738755
if request.organizational_unit:
756+
if isinstance(request.organizational_unit, string_types):
757+
org_units = [request.organizational_unit]
758+
else:
759+
org_units = request.organizational_unit
760+
739761
if ps.policy and ps.policy.subject:
740762
policy_ous = ps.policy.subject.org_units
741-
valid = value_matches_regex(value=request.organizational_unit, pattern_list=policy_ous)
763+
valid = all(
764+
value_matches_regex(value=ou, pattern_list=policy_ous) for ou in org_units
765+
)
742766
if not valid:
743767
ou_str = "Organizational Unit"
744768
log.error(MSG_VALUE_NOT_MATCH_POLICY % (ou_str, ou_str+"s", request.organizational_unit,

vcert/connection_tpp_abstract.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,26 @@ def __init__(self):
7979

8080

8181
class AbstractTPPConnection(CommonConnection):
82+
def __init__(self):
83+
CommonConnection.__init__(self)
84+
85+
ARG_URL = 'url'
86+
ARG_PARAMS = 'params'
87+
ARG_CHECK_TOKEN = 'check_token' # nosec
88+
ARG_INCLUDE_TOKEN_HEADER = 'include_token_header' # nosec
89+
ARG_DATA = 'data'
90+
91+
def auth(self):
92+
raise NotImplementedError
8293

8394
def request_cert(self, request, zone):
84-
request_data = {'PolicyDN': self._normalize_zone(zone),
85-
'ObjectName': request.friendly_name,
86-
'DisableAutomaticRenewal': "true"
87-
}
95+
request_data = {
96+
'PolicyDN': self._normalize_zone(zone),
97+
'ObjectName': request.friendly_name,
98+
'DisableAutomaticRenewal': "true"
99+
}
100+
zone_config = self.read_zone_conf(zone)
101+
request.update_from_zone_config(zone_config)
88102

89103
if request.csr_origin == CSR_ORIGIN_LOCAL:
90104
request.build_csr()
@@ -143,8 +157,11 @@ def request_cert(self, request, zone):
143157
else:
144158
request_data['CustomFields'] = [custom_field_json]
145159

146-
147-
status, data = self._post(URLS.CERTIFICATE_REQUESTS, data=request_data)
160+
args = {
161+
self.ARG_URL: URLS.CERTIFICATE_REQUESTS,
162+
self.ARG_DATA: request_data
163+
}
164+
status, data = self.post(args)
148165
if status == HTTPStatus.OK:
149166
request.id = data['CertificateDN']
150167
request.cert_guid = data['Guid']
@@ -321,6 +338,18 @@ def revoke_cert(self, request):
321338
def import_cert(self, request):
322339
raise NotImplementedError
323340

341+
def read_zone_conf(self, tag):
342+
args = {
343+
self.ARG_URL: URLS.ZONE_CONFIG,
344+
self.ARG_DATA: {
345+
'PolicyDN': self._normalize_zone(tag)
346+
}
347+
}
348+
status, data = self.post(args=args)
349+
if status != HTTPStatus.OK:
350+
raise ServerUnexptedBehavior("Server returns %d status on reading zone configuration." % status)
351+
return self._parse_zone_data_to_object(data)
352+
324353
def get_policy(self, zone):
325354
# get policy spec from name
326355
policy_name = self._normalize_zone(zone)
@@ -630,12 +659,6 @@ def retrieve_ssh_config(self, ca_request):
630659
raise ServerUnexptedBehavior("Server returns %d status on requesting SSH CA Public Key Data for %s = %s."
631660
% (status, key, value))
632661

633-
ARG_URL = 'url'
634-
ARG_PARAMS = 'params'
635-
ARG_CHECK_TOKEN = 'check_token' # nosec
636-
ARG_INCLUDE_TOKEN_HEADER = 'include_token_header' # nosec
637-
ARG_DATA = 'data'
638-
639662
def get(self, args):
640663
"""
641664
@@ -725,22 +748,13 @@ def _reset_policy_attr(self, zone, attr_name):
725748
return status, response
726749

727750
def _reset_policy(self, zone):
728-
self._reset_policy_attr(zone, SPA.TPP_DOMAIN_SUFFIX_WHITELIST)
729-
self._reset_policy_attr(zone, SPA.TPP_PROHIBIT_WILDCARD)
730-
self._reset_policy_attr(zone, SPA.TPP_CERT_AUTHORITY)
731-
self._reset_policy_attr(zone, SPA.TPP_ORGANIZATION)
732-
self._reset_policy_attr(zone, SPA.TPP_ORG_UNIT)
733-
self._reset_policy_attr(zone, SPA.TPP_CITY)
734-
self._reset_policy_attr(zone, SPA.TPP_STATE)
735-
self._reset_policy_attr(zone, SPA.TPP_COUNTRY)
736-
self._reset_policy_attr(zone, SPA.TPP_KEY_ALGORITHM)
737-
self._reset_policy_attr(zone, SPA.TPP_KEY_BIT_STR)
738-
self._reset_policy_attr(zone, SPA.TPP_ELLIPTIC_CURVE)
739-
self._reset_policy_attr(zone, SPA.TPP_MANUAL_CSR)
740-
self._reset_policy_attr(zone, SPA.TPP_PROHIBITED_SAN_TYPES)
741-
self._reset_policy_attr(zone, SPA.TPP_ALLOWED_PRIVATE_KEY_REUSE)
742-
self._reset_policy_attr(zone, SPA.TPP_WANT_RENEWAL)
743-
self._reset_policy_attr(zone, SPA.TPP_MANAGEMENT_TYPE)
751+
atrr_list = [SPA.TPP_DOMAIN_SUFFIX_WHITELIST, SPA.TPP_PROHIBIT_WILDCARD, SPA.TPP_CERT_AUTHORITY,
752+
SPA.TPP_ORGANIZATION, SPA.TPP_ORG_UNIT, SPA.TPP_CITY, SPA.TPP_STATE, SPA.TPP_COUNTRY,
753+
SPA.TPP_KEY_ALGORITHM, SPA.TPP_KEY_BIT_STR, SPA.TPP_ELLIPTIC_CURVE, SPA.TPP_MANUAL_CSR,
754+
SPA.TPP_PROHIBITED_SAN_TYPES, SPA.TPP_ALLOWED_PRIVATE_KEY_REUSE, SPA.TPP_WANT_RENEWAL,
755+
SPA.TPP_MANAGEMENT_TYPE]
756+
for attr in atrr_list:
757+
self._reset_policy_attr(zone, attr)
744758

745759
@staticmethod
746760
def _parse_attr_response(response):
@@ -873,6 +887,7 @@ def _parse_zone_data_to_object(data):
873887
key_type = KeyType(KeyType.ECDSA, data['Policy']['KeyPair']['EllipticCurve']['Value'])
874888
else:
875889
key_type = None
890+
876891
z = ZoneConfig(
877892
organization=CertField(s['Organization']['Value'], locked=s['Organization']['Locked']),
878893
organizational_unit=CertField(ou, locked=s['OrganizationalUnit']['Locked']),
@@ -884,12 +899,6 @@ def _parse_zone_data_to_object(data):
884899
)
885900
return z
886901

887-
def read_zone_conf(self, tag):
888-
status, data = self._post(URLS.ZONE_CONFIG, {'PolicyDN': self._normalize_zone(tag)})
889-
if status != HTTPStatus.OK:
890-
raise ServerUnexptedBehavior("Server returns %d status on reading zone configuration." % status)
891-
return self._parse_zone_data_to_object(data)
892-
893902
def _get_certificate_details(self, cert_guid):
894903
status, data = self._get(URLS.CERTIFICATE_SEARCH + cert_guid)
895904
if status != HTTPStatus.OK:

vcert/connection_tpp_token.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@
2424

2525
import requests
2626

27-
from .common import MIME_JSON, TokenInfo, Authentication, KeyType, Policy, ZoneConfig, CertField
27+
from .common import MIME_JSON, TokenInfo, Authentication
2828
from .connection_tpp_abstract import AbstractTPPConnection, URLS
2929
from .errors import (ClientBadData, ServerUnexptedBehavior, AuthenticationError)
3030
from .http import HTTPStatus
3131

32-
HEADER_AUTHORIZATION = "Authorization" # type: str
32+
HEADER_AUTHORIZATION = 'Authorization'
3333

34-
KEY_ACCESS_TOKEN = "access_token" # type: str # nosec
35-
KEY_REFRESH_TOKEN = "refresh_token" # type: str # nosec
36-
KEY_EXPIRATION_DATE = "expiration_date" # type: str
34+
KEY_ACCESS_TOKEN = 'access_token' # nosec
35+
KEY_REFRESH_TOKEN = 'refresh_token' # nosec
36+
KEY_EXPIRATION_DATE = 'expiration_date'
3737

3838

3939
class TPPTokenConnection(AbstractTPPConnection):
@@ -46,6 +46,8 @@ def __init__(self, url, user=None, password=None, access_token=None, refresh_tok
4646
:param str refresh_token:
4747
:param dict[str,Any] http_request_kwargs:
4848
"""
49+
AbstractTPPConnection.__init__(self)
50+
4951
self._base_url = url # type: str
5052
self._auth = Authentication(user=user, password=password, access_token=access_token,
5153
refresh_token=refresh_token) # type: Authentication

vcert/policy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self):
3333
# tpp read policy attributes - RPA
3434
class RPA(CommonPA):
3535
def __init__(self):
36-
pass
36+
CommonPA.__init__(self)
3737

3838
TPP_CERT_AUTHORITY = "CertificateAuthority" # "Certificate Authority"
3939
TPP_WILDCARDS_ALLOWED = "WildcardsAllowed"
@@ -57,7 +57,7 @@ def __init__(self):
5757
# tpp set policy attributes - SPA
5858
class SPA(CommonPA):
5959
def __init__(self):
60-
pass
60+
CommonPA.__init__(self)
6161

6262
TPP_CERT_AUTHORITY = "Certificate Authority"
6363
TPP_PROHIBIT_WILDCARD = "Prohibit Wildcard"

vcert/vaas_utils.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ def zip_to_pem(data, chain_option):
9292
"""
9393
zip_data = zipfile.ZipFile(io.BytesIO(data))
9494
private_key = None
95-
certs = []
9695
chain = []
9796
certificate = None
9897
for info in zip_data.infolist():
@@ -125,9 +124,3 @@ def value_matches_regex(value, pattern_list):
125124
:rtype: bool
126125
"""
127126
return any((re.match(pattern, value) is not None) for pattern in pattern_list)
128-
# for regex in regex_list:
129-
# result = re.match(regex, value)
130-
# if not result:
131-
# return False
132-
#
133-
# return True

0 commit comments

Comments
 (0)