2323from cryptography import x509
2424from cryptography .hazmat .backends import default_backend
2525from cryptography .x509 import SignatureAlgorithmOID as AlgOID
26+ from six .moves .urllib import parse as url_parse
2627
2728from .pem import parse_pem
2829from .common import CertField , CommonConnection , CertificateRequest , CSR_ORIGIN_LOCAL , CSR_ORIGIN_PROVIDED , \
3435from .policy .pm_tpp import TPPPolicy , is_service_generated_csr , SetAttrResponse , validate_policy_spec , \
3536 get_int_value
3637from .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
3840from .tpp_utils import IssuerHint
3941
4042POLICY_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 )
0 commit comments