Skip to content

Commit a201439

Browse files
committed
- Added method to retrieve public key data from SSH Certificate Authority.
- Updated SSH methods responses to include the processing details.
1 parent fe61b78 commit a201439

5 files changed

Lines changed: 208 additions & 63 deletions

File tree

vcert/common.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
from .errors import VenafiConnectionError, ServerUnexptedBehavior, BadData, ClientBadData
3737
from .http import HTTPStatus
3838
from .policy import PolicySpecification
39-
from .ssh_utils import SSHCertRequest, SSHRetrieveResponse
39+
from .ssh_utils import SSHCertRequest, SSHRetrieveResponse, SSHCATemplateRequest, SSHConfig
4040
from .tpp_utils import IssuerHint
4141

4242
MIME_JSON = "application/json"
@@ -691,6 +691,14 @@ def retrieve_ssh_cert(self, request):
691691
"""
692692
raise NotImplementedError
693693

694+
def retrieve_ssh_config(self, ca_request):
695+
"""
696+
697+
:param SSHCATemplateRequest ca_request:
698+
:rtype: SSHConfig
699+
"""
700+
raise NotImplementedError
701+
694702
@staticmethod
695703
def process_server_response(r):
696704
if r.status_code not in (HTTPStatus.OK, HTTPStatus.ACCEPTED, HTTPStatus.CREATED, HTTPStatus.CONFLICT):

vcert/connection_tpp.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,8 @@ def _read_config_dn(self, dn, attribute_name):
116116
if status != HTTPStatus.OK:
117117
raise ServerUnexptedBehavior("")
118118
return data
119+
120+
def _is_valid_auth(self):
121+
if self._token:
122+
return True
123+
return False

vcert/connection_tpp_abstract.py

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from cryptography import x509
2424
from cryptography.hazmat.backends import default_backend
2525
from cryptography.x509 import SignatureAlgorithmOID as AlgOID
26+
from six.moves.urllib import parse as url_parse
2627

2728
from .pem import parse_pem
2829
from .common import CertField, CommonConnection, CertificateRequest, CSR_ORIGIN_LOCAL, CSR_ORIGIN_PROVIDED, \
@@ -34,7 +35,8 @@
3435
from .policy.pm_tpp import TPPPolicy, is_service_generated_csr, SetAttrResponse, validate_policy_spec, \
3536
get_int_value
3637
from .ssh_utils import SSHCertRequest, SSHCertResponse, build_tpp_retrieve_request, SSHResponse, \
37-
SSHRetrieveResponse, build_tpp_request
38+
SSHRetrieveResponse, build_tpp_request, SSHCATemplateRequest, SSHConfig, PATH_SEPARATOR, CA_ROOT_PATH, \
39+
SSHTPPCADetails
3840
from .tpp_utils import IssuerHint
3941

4042
POLICY_ATTR_CLASS = "X509 Certificate" # type: str
@@ -69,6 +71,8 @@ class URLS:
6971
SSH_BASE_URL = API_BASE_URL + "SSHCertificates/"
7072
SSH_CERTIFICATE_REQUEST = SSH_BASE_URL + "request"
7173
SSH_CERTIFICATE_RETRIEVE = SSH_BASE_URL + "retrieve"
74+
SSH_CA_DETAILS = SSH_BASE_URL + "Template/Retrieve"
75+
SSH_CA_PUBLIC_KEY = SSH_CA_DETAILS + "/PublicKeyData"
7276

7377
def __init__(self):
7478
pass
@@ -536,18 +540,19 @@ def request_ssh_cert(self, request):
536540
log.info("Requesting SSH Certificate with id %s" % request.key_id)
537541
status, data = self._post(URLS.SSH_CERTIFICATE_REQUEST, json_request)
538542

539-
if status != HTTPStatus.OK:
543+
if status == HTTPStatus.OK:
544+
response_object = SSHResponse(data['Response'])
545+
if response_object.success:
546+
cert_req_response = SSHCertResponse(data)
547+
request.pickup_id = cert_req_response.dn
548+
request.guid = cert_req_response.guid
549+
return True
550+
else:
551+
raise VenafiError("An error occurred with status %s. Message: %s"
552+
% (response_object.error_code, response_object.error_msg))
553+
else:
540554
raise ServerUnexptedBehavior("Server returns %d status on requesting SSH certificate." % status)
541555

542-
response = SSHCertResponse(data)
543-
if not response.response.success:
544-
raise VenafiError("An error occurred with status %s. Message: %s"
545-
% (response.response.error_code, response.response.error_msg))
546-
request.pickup_id = response.dn
547-
request.guid = response.guid
548-
549-
return True
550-
551556
def retrieve_ssh_cert(self, request):
552557
"""
553558
@@ -566,7 +571,7 @@ def retrieve_ssh_cert(self, request):
566571
status = 0
567572

568573
if status == HTTPStatus.OK:
569-
response_object = SSHResponse(data["Response"])
574+
response_object = SSHResponse(data['Response'])
570575
if response_object.success:
571576
return SSHRetrieveResponse(data)
572577
else:
@@ -583,6 +588,42 @@ def retrieve_ssh_cert(self, request):
583588
'Operation timed out at %d seconds while retrieving SSH certificate with id %s'
584589
% (request.timeout, request.pickup_id))
585590

591+
def retrieve_ssh_config(self, ca_request):
592+
"""
593+
594+
:param SSHCATemplateRequest ca_request:
595+
:rtype: SSHConfig
596+
"""
597+
key = None
598+
value = None
599+
if ca_request.template:
600+
key = 'DN'
601+
value = "%s%s%s" % (CA_ROOT_PATH, PATH_SEPARATOR, ca_request.guid)
602+
elif ca_request.guid:
603+
key = 'guid'
604+
value = ca_request.guid
605+
else:
606+
raise ClientBadData("CA Guid or CA template must be provided to retrieve SSH config.")
607+
608+
query = "%s=%s" % (key, value)
609+
query = url_parse.quote(query)
610+
url = "%s?%s" % (URLS.SSH_CA_PUBLIC_KEY, query)
611+
612+
status, data = self._get(url=url, params=None)
613+
if status == HTTPStatus.OK:
614+
ssh_config_response = SSHConfig()
615+
ssh_config_response.ca_public_key = data
616+
if self._is_valid_auth():
617+
details = self._retrieve_ssh_ca_details(ca_request)
618+
ssh_config_response.ca_principals = details.access_control.default_principals
619+
return ssh_config_response
620+
else:
621+
raise ServerUnexptedBehavior("Server returns %d status on requesting SSH CA Public Key Data for %s = %s."
622+
% (status, key, value))
623+
624+
# ======================================== API IMPLEMENTATION ENDS ======================================== #
625+
# ========================================================================================================= #
626+
586627
def _policy_exists(self, zone):
587628
"""
588629
:param str zone:
@@ -823,3 +864,31 @@ def _get_certificate_details(self, cert_guid):
823864
if status != HTTPStatus.OK:
824865
raise ServerUnexptedBehavior("")
825866
return data
867+
868+
def _is_valid_auth(self):
869+
raise NotImplementedError
870+
871+
def _retrieve_ssh_ca_details(self, ca_request):
872+
"""
873+
874+
:param SSHCATemplateRequest ca_request:
875+
:rtype: SSHTPPCADetails
876+
"""
877+
json_request = dict()
878+
if ca_request.template:
879+
json_request['DN'] = "%s%s%s" % (CA_ROOT_PATH, PATH_SEPARATOR, ca_request.guid)
880+
elif ca_request.guid:
881+
json_request['Guid'] = ca_request.guid
882+
else:
883+
raise ClientBadData("CA Guid or CA template must be provided to retrieve SSH CA details.")
884+
885+
status, data = self._post(URLS.SSH_CA_DETAILS, json_request)
886+
if status == HTTPStatus.OK:
887+
response_object = SSHResponse(data['Response'])
888+
if response_object.success:
889+
return SSHTPPCADetails(data)
890+
else:
891+
raise VenafiError("An error occurred with status %s. Message: %s"
892+
% (response_object.error_code, response_object.error_msg))
893+
else:
894+
raise ServerUnexptedBehavior("Server returns %d status on requesting SSH CA details." % status)

vcert/connection_tpp_token.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,8 @@ def _parse_access_token_data_to_object(data):
185185
refresh_token=data["refresh_token"],
186186
)
187187
return token_info
188+
189+
def _is_valid_auth(self):
190+
if self._auth and self._auth.access_token:
191+
return True
192+
return False

0 commit comments

Comments
 (0)