Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Async APIs for attestation SDK #18735

Merged
merged 19 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
da0f1f5
Added Async APIs for attestation SDK
LarryOsterman May 13, 2021
4ec7026
Initial cut of attestation samples
LarryOsterman May 14, 2021
958ab83
Integrated samples into docstrings for a couple of APIs, more to come
LarryOsterman May 15, 2021
f39c384
Added attest enclave sample
LarryOsterman May 17, 2021
eb8b673
Added samples for remaining attestation apis
LarryOsterman May 17, 2021
af70193
Fixed sample test run
LarryOsterman May 17, 2021
d4a3dc3
More AZURE_XXX_ID->ATTESTATION_XXX_ID to get tests to work
LarryOsterman May 18, 2021
054ec80
Moved manifest entries around to try to figure out whl issue
LarryOsterman May 18, 2021
e08ee12
Pull request feedback
LarryOsterman May 18, 2021
1f39161
Deleted samples\__init__.py to unconfused the wheel validation
LarryOsterman May 18, 2021
cd8d321
Removed memory leaks in samples
LarryOsterman May 18, 2021
4dc06d0
Switched samples to use with and async with
LarryOsterman May 18, 2021
3f0c52d
Moved async samples to current directory
LarryOsterman May 18, 2021
3df5298
Removed closing from samples
LarryOsterman May 18, 2021
cb081e0
Moved client credential logic to sample_utils for common origin.
LarryOsterman May 18, 2021
44e40d9
Removed samples. from async samples
LarryOsterman May 18, 2021
22f6138
Try to work around py27 failure in attestation callback
LarryOsterman May 18, 2021
487a2d6
Try to work around py27 failure in attestation callback 2
LarryOsterman May 18, 2021
04e9cc9
Try to work around py27 failure in attestation callback 3
LarryOsterman May 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sdk/attestation/azure-security-attestation/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
recursive-include tests *.py *.yaml
include *.md
include azure/__init__.py
include azure/security/__init__.py

recursive-include samples *.py *.md
recursive-include tests *.py *.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ def get_policy(self, attestation_type, **kwargs):

:param azure.security.attestation.AttestationType attestation_type: :class:`azure.security.attestation.AttestationType` for
which to retrieve the policy.
:return AttestationResponse[str]: Attestation service response encapsulating a string attestation policy.
:return azure.security.attestation.AttestationResponse[str]: Attestation service response encapsulating a string attestation policy.

:raises AttestationTokenValidationException: Raised when an attestation token is invalid.
:raises azure.security.attestation.AttestationTokenValidationException: Raised when an attestation token is invalid.

"""

Expand All @@ -93,17 +93,17 @@ def get_policy(self, attestation_type, **kwargs):
return AttestationResponse[str](token, actual_policy.decode('utf-8'))

@distributed_trace
def set_policy(self, attestation_type, attestation_policy, **kwargs):
def set_policy(self, attestation_type, attestation_policy, signing_key=None, **kwargs):
#type:(AttestationType, str, Optional[AttestationSigningKey], **Any) -> AttestationResponse[PolicyResult]
""" Sets the attestation policy for the specified attestation type.

:param azure.security.attestation.AttestationType attestation_type: :class:`azure.security.attestation.AttestationType` for
which to set the policy.
:param str attestation_policy: Attestation policy to be set.
:keyword AttestationSigningKey signing_key: Signing key to be
:keyword azure.security.attestation.AttestationSigningKey signing_key: Signing key to be
used to sign the policy before sending it to the service.
:return AttestationResponse[PolicyResult]: Attestation service response encapsulating a :class:`PolicyResult`.
:raises AttestationTokenValidationException: Raised when an attestation token is invalid.
:return azure.security.attestation.AttestationResponse[azure.security.attestation.PolicyResult]: Attestation service response encapsulating a :class:`PolicyResult`.
:raises azure.security.attestation.AttestationTokenValidationException: Raised when an attestation token is invalid.

.. note::
If the attestation instance is in *Isolated* mode, then the
Expand All @@ -115,7 +115,6 @@ def set_policy(self, attestation_type, attestation_policy, **kwargs):

"""

signing_key = kwargs.get('signing_key', None) #type:AttestationSigningKey
policy_token = AttestationToken[GeneratedStoredAttestationPolicy](
body=GeneratedStoredAttestationPolicy(attestation_policy = attestation_policy.encode('ascii')),
signer=signing_key,
Expand All @@ -130,17 +129,17 @@ def set_policy(self, attestation_type, attestation_policy, **kwargs):
return AttestationResponse[PolicyResult](token, PolicyResult._from_generated(token.get_body()))

@distributed_trace
def reset_policy(self, attestation_type, **kwargs):
#type:(AttestationType, **dict[str, Any]) -> AttestationResponse[PolicyResult]
def reset_policy(self, attestation_type, signing_key=None, **kwargs):
#type:(AttestationType, Optional[AttestationSigningKey], **dict[str, Any]) -> AttestationResponse[PolicyResult]
""" Resets the attestation policy for the specified attestation type to the default value.

:param azure.security.attestation.AttestationType attestation_type: :class:`azure.security.attestation.AttestationType` for
which to set the policy.
:param str attestation_policy: Attestation policy to be reset.
:keyword AttestationSigningKey signing_key: Signing key to be
:keyword azure.security.attestation.AttestationSigningKey signing_key: Signing key to be
used to sign the policy before sending it to the service.
:return AttestationResponse[PolicyResult]: Attestation service response encapsulating a :class:`PolicyResult`.
:raises AttestationTokenValidationException: Raised when an attestation token is invalid.
:return azure.security.attestation.AttestationResponse[azure.security.attestation.PolicyResult]: Attestation service response encapsulating a :class:`PolicyResult`.
:raises azure.security.attestation.AttestationTokenValidationException: Raised when an attestation token is invalid.

.. note::
If the attestation instance is in *Isolated* mode, then the
Expand All @@ -150,7 +149,6 @@ def reset_policy(self, attestation_type, **kwargs):
If the attestation instance is in *AAD* mode, then the `signing_key`
parameter does not need to be provided.
"""
signing_key = kwargs.get('signing_key', None) #type:AttestationSigningKey
policy_token = AttestationToken(
body=None,
signer=signing_key)
Expand All @@ -172,7 +170,7 @@ def get_policy_management_certificates(self, **kwargs):
The list of policy management certificates will only be non-empty if the
attestation service instance is in Isolated mode.

:return AttestationResponse[list[list[bytes]]: Attestation service response
:return azure.security.attestation.AttestationResponse[list[list[bytes]]: Attestation service response
encapsulating a list of DER encoded X.509 certificate chains.
"""

Expand All @@ -199,9 +197,9 @@ def add_policy_management_certificate(self, certificate_to_add, signing_key, **k

:param bytes certificate_to_add: DER encoded X.509 certificate to add to
the list of attestation policy management certificates.
:param AttestationSigningKey signing_key: Signing Key representing one of
:param azure.security.attestation.AttestationSigningKey signing_key: Signing Key representing one of
the *existing* attestation signing certificates.
:return AttestationResponse[PolicyCertificatesModificationResult]: Attestation service response
:return azure.security.attestation.AttestationResponse[azure.security.attestation.PolicyCertificatesModificationResult]: Attestation service response
encapsulating the status of the add request.

The :class:`PolicyCertificatesModificationResult` response to the
Expand Down Expand Up @@ -240,9 +238,9 @@ def remove_policy_management_certificate(self, certificate_to_add, signing_key,

:param bytes certificate_to_add: DER encoded X.509 certificate to add to
the list of attestation policy management certificates.
:param AttestationSigningKey signing_key: Signing Key representing one of
:param azure.security.attestation.AttestationSigningKey signing_key: Signing Key representing one of
the *existing* attestation signing certificates.
:return AttestationResponse[PolicyCertificatesModificationResult]: Attestation service response
:return azure.security.attestation.AttestationResponse[azure.security.attestation.PolicyCertificatesModificationResult]: Attestation service response
encapsulating a list of DER encoded X.509 certificate chains.

The :class:`PolicyCertificatesModificationResult` response to the
Expand Down Expand Up @@ -285,11 +283,7 @@ def _get_signers(self, **kwargs):
self._signing_certificates = []
for key in signing_certificates.keys:
# Convert the returned certificate chain into an array of X.509 Certificates.
certificates = []
for x5c in key.x5_c:
der_cert = base64.b64decode(x5c)
certificates.append(der_cert)
self._signing_certificates.append(AttestationSigner(certificates, key.kid))
self._signing_certificates.append(AttestationSigner._from_generated(key))
signers = self._signing_certificates
return signers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def get_signing_certificates(self, **kwargs):
# type: (Any) ->list[AttestationSigner]
""" Returns the set of signing certificates used to sign attestation tokens.

:return list[AttestationSigner]: A list of :class:`AttestationSigner` objects.
:return list[azure.security.attestation.AttestationSigner]: A list of :class:`azure.security.attestation.AttestationSigner` objects.

For additional request configuration options, please see `Python Request Options <https://aka.ms/azsdk/python/options>`_.

Expand All @@ -87,8 +87,7 @@ def get_signing_certificates(self, **kwargs):
signers = []
for key in signing_certificates.keys:
# Convert the returned certificate chain into an array of X.509 Certificates.
certificates = [base64.b64decode(x5c) for x5c in key.x5_c]
signers.append(AttestationSigner(certificates, key.kid))
signers.append(AttestationSigner._from_generated(key))
return signers

@distributed_trace
Expand All @@ -97,19 +96,28 @@ def attest_sgx_enclave(self, quote, inittime_data=None, runtime_data=None, **kwa
""" Attests the validity of an SGX quote.

:param bytes quote: An SGX quote generated from an Intel(tm) SGX enclave
:keyword AttestationData inittime_data: Data presented at the time that the SGX enclave was initialized.
:keyword AttestationData runtime_data: Data presented at the time that the SGX quote was created.
:keyword azure.security.attestation.AttestationData inittime_data: Data presented at the time that the SGX enclave was initialized.
:keyword azure.security.attestation.AttestationData runtime_data: Data presented at the time that the SGX quote was created.
:keyword str draft_policy: "draft" or "experimental" policy to be used with
this attestation request. If this parameter is provided, then this
policy document will be used for the attestation request.
This allows a caller to test various policy documents against actual data
before applying the policy document via the set_policy API

:return AttestationResponse[AttestationResult]: Attestation service response encapsulating an :class:`AttestationResult`.
:return azure.security.attestation.AttestationResponse[azure.security.attestation.AttestationResult]: Attestation service response encapsulating an :class:`AttestationResult`.

.. note::
Note that if the `draft_policy` parameter is provided, the resulting attestation token will be an unsecured attestation token.

.. admonition:: Example:

.. literalinclude:: ../samples/sample_attest_enclave.py
:start-after: [START attest_sgx_enclave_shared]
:end-before: [END attest_sgx_enclave_shared]
:language: python
:dedent: 8
:caption: Attesting an SGX Enclave

For additional request configuration options, please see `Python Request Options <https://aka.ms/azsdk/python/options>`_.

"""
Expand All @@ -125,7 +133,7 @@ def attest_sgx_enclave(self, quote, inittime_data=None, runtime_data=None, **kwa
quote=quote,
init_time_data = inittime,
runtime_data = runtime,
draft_policy_for_attestation=kwargs.get('draft_policy', None))
draft_policy_for_attestation=kwargs.pop('draft_policy', None))

result = self._client.attestation.attest_sgx_enclave(request, **kwargs)
token = AttestationToken[GeneratedAttestationResult](token=result.token,
Expand All @@ -139,14 +147,34 @@ def attest_open_enclave(self, report, inittime_data=None, runtime_data=None, **k
""" Attests the validity of an Open Enclave report.

:param bytes report: An open_enclave report generated from an Intel(tm) SGX enclave
:keyword AttestationData inittime_data: Data presented at the time that the SGX enclave was initialized.
:keyword AttestationData runtime_data: Data presented at the time that the open_enclave report was created.
:keyword azure.security.attestation.AttestationData inittime_data: Data presented at the time that the SGX enclave was initialized.
:keyword azure.security.attestation.AttestationData runtime_data: Data presented at the time that the open_enclave report was created.
:keyword str draft_policy: "draft" or "experimental" policy to be used with
this attestation request. If this parameter is provided, then this
policy document will be used for the attestation request.
This allows a caller to test various policy documents against actual data
before applying the policy document via the set_policy API.
:return AttestationResponse[AttestationResult]: Attestation service response encapsulating an :class:`AttestationResult`.
:return azure.security.attestation.AttestationResponse[azure.security.attestation.AttestationResult]: Attestation service response encapsulating an :class:`AttestationResult`.

.. admonition:: Example: Simple OpenEnclave attestation.

.. literalinclude:: ../samples/sample_attest_enclave.py
:start-after: [START attest_open_enclave_shared]
:end-before: [END attest_open_enclave_shared]
:language: python
:dedent: 8
:caption: Attesting an open_enclave report for an SGX enclave.

.. admonition:: Example: Simple OpenEnclave attestation with draft attestation policy.


.. literalinclude:: ../samples/sample_attest_enclave.py
:start-after: [START attest_open_enclave_shared_draft]
:end-before: [END attest_open_enclave_shared_draft]
:language: python
:dedent: 8
:caption: Attesting using a draft attestation policy.


.. note::
Note that if the `draft_policy` parameter is provided, the resulting attestation token will be an unsecured attestation token.
Expand All @@ -166,7 +194,7 @@ def attest_open_enclave(self, report, inittime_data=None, runtime_data=None, **k
report=report,
init_time_data = inittime,
runtime_data = runtime,
draft_policy_for_attestation = kwargs.get('draft_policy', None))
draft_policy_for_attestation = kwargs.pop('draft_policy', None))
result = self._client.attestation.attest_open_enclave(request, **kwargs)
token = AttestationToken[GeneratedAttestationResult](token=result.token,
body_type=GeneratedAttestationResult)
Expand All @@ -180,8 +208,8 @@ def attest_tpm(self, request, **kwargs):

See the `TPM Attestation Protocol Reference <https://docs.microsoft.com/en-us/azure/attestation/virtualization-based-security-protocol>`_ for more information.

:param TpmAttestationRequest request: Incoming request to send to the TPM attestation service.
:returns TpmAttestationResponse: A structure containing the response from the TPM attestation.
:param azure.security.attestation.TpmAttestationRequest request: Incoming request to send to the TPM attestation service.
:returns azure.security.attestation.TpmAttestationResponse: A structure containing the response from the TPM attestation.

"""
response = self._client.attestation.attest_tpm(request.data, **kwargs)
Expand All @@ -198,8 +226,7 @@ def _get_signers(self, **kwargs):
self._signing_certificates = []
for key in signing_certificates.keys:
# Convert the returned certificate chain into an array of X.509 Certificates.
certificates = [base64.b64decode(x5c) for x5c in key.x5_c]
self._signing_certificates.append(AttestationSigner(certificates, key.kid))
self._signing_certificates.append(AttestationSigner._from_generated(key))
signers = self._signing_certificates
return signers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(
# raise ValueError("Parameter 'instance_url' must not be None.")
super(AttestationClientConfiguration, self).__init__(**kwargs)

self.token_validation_options = kwargs.get('token_validation_options',
self.token_validation_options = kwargs.pop('token_validation_options',
TokenValidationOptions(validate_token=True)) # type: TokenValidationOptions
# self.credential = credential
# self.instance_url = instance_url
Loading