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

[Key Vault] Create Security Domain library #37929

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

mccoyp
Copy link
Member

@mccoyp mccoyp commented Oct 16, 2024

Description

This is a new library that is mostly generated directly from TypeSpec. The goal of this library is to provide a track 2 Security Domain client for the CLI, as well as external customers. There are currently no plans for shipping this library in other languages.

Initial preview timeline: public preview release by April 8th, 2025.

Customer library request: Azure/azure-cli#29998

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

@mccoyp mccoyp added KeyVault Client This issue points to a problem in the data-plane of the library. labels Oct 16, 2024
@azure-sdk
Copy link
Collaborator

azure-sdk commented Oct 16, 2024

API change check

APIView has identified API level changes in this PR and created following API reviews.

azure-keyvault-securitydomain

"""

@distributed_trace
def begin_download(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm rather confused by this method - it's very unusual to have a download function that is also a poller?
I see the _initial method is returning Iterable[bytes] like I would expect from a download, but this poller seems to return a result of None.....
If this method is not actually downloading any data locally, then we should probably find a different name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type here actually seems to be a generation bug -- the poller is supposed to return a SecurityDomainObject (and the track 1 library that the CLI uses does this correctly). Azure PowerShell and the CLI even accept an output file parameter for this operation, so returning None is definitely unexpected. I'm looking into that now

Copy link
Member Author

@mccoyp mccoyp Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some more testing, this is a weird method. The initial response contains the SecurityDomainObject, even when get_download_status still returns "InProgress". The actual download operation doesn't seem to be an LRO, but the operation is marked as one because HSM activation, which is started by the operation, does take some time to complete.

This may have to do with this comment in the CLI's vendored package, stating the operation was apparently changed from returning a 200 to a 202 in the 7.2 API version: https://github.com/Azure/azure-cli/blob/424e80464cdba4c241fade9d966cce61ebe4513a/src/azure-cli/azure/cli/command_modules/keyvault/vendored_sdks/azure_keyvault_t1/v7_2/key_vault_client.py#L118-L122

The REST API documentation is correct -- the download endpoint just returns a value of the security domain. To make this work with our LRO logic though, I think we'd have to make this return SecurityDomainOperationStatus, and add a value property to that model. @heaths, @annatisch, what do you think?

EDIT: The get_download_status/downloadPending endpoint doesn't return a value containing the security domain -- it just returns the status of HSM activation. This operation wants to return the initial response as the final result once the status is "Success". I guess we still need a SecurityDomainObject return type, but I need to find a way to get this to work with TypeSpec...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a custom polling method to correctly handle this return type (and the non-standard "Success" status), and plugged it into an override for the begin_download operation: 4aac19c. The client method now agrees with the service specification and past behavior, though I'll need to sync with Laurent on whether there's anything we can do to correct the return type in the generated methods. Either way, we still need the custom polling to handle the LRO flow here.

return deserialized # type: ignore

@overload
def begin_upload(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure if upload is the best name here - again it's a bit weird to pair this with a poller, but I'm assuming the "upload" triggers some process that the poller then monitors?

Copy link
Member Author

@mccoyp mccoyp Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For operation context, this uploads a security domain to an HSM. The CLI's documentation says this "start[s] to restore the HSM" -- the same command in Azure PowerShell uses Import as the verb. I don't have the full context, but it seems like the long-running process is restoring an HSM to some state

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a good documentation page that walks through the process of recovering a lost HSM by uploading its security domain to a new HSM: https://learn.microsoft.com/azure/key-vault/managed-hsm/disaster-recovery-guide.

To upload a security domain, you need to have activated a previous HSM and downloaded its security domain. Then the transfer key is fetched from a new, inactive HSM -- which is used to encrypt the original security domain. The encrypted domain is can then be uploaded to the new HSM, activating it in the process. Testing it locally, the upload operation takes about a minute; the operation is considered successful once the HSM is active.

Based on that context, upload makes some sense as a verb. restore could possibly be an option, like the CLI documentation mentions, but restoring is already used as a verb in azure-keyvault-administration to refer to restoring the backed-up contents of an HSM. export/import or download/upload seem like the best options to me

@mccoyp mccoyp force-pushed the kv-securitydomain branch from 98bf2c5 to ac1bf76 Compare October 23, 2024 06:33
Copy link

Hi @mccoyp. Thank you for your interest in helping to improve the Azure SDK experience and for your contribution. We've noticed that there hasn't been recent engagement on this pull request. If this is still an active work stream, please let us know by pushing some changes or leaving a comment. Otherwise, we'll close this out in 7 days.

@github-actions github-actions bot added the no-recent-activity There has been no recent activity on this issue. label Jan 10, 2025
@mccoyp mccoyp removed the no-recent-activity There has been no recent activity on this issue. label Jan 10, 2025
@xuzhang3
Copy link

xuzhang3 commented Feb 6, 2025

@mccoyp any update of this SDK?

@mccoyp
Copy link
Member Author

mccoyp commented Feb 6, 2025

@xuzhang3 Our current estimate is that we'd like to release an initial Python preview in early April.

@mccoyp mccoyp force-pushed the kv-securitydomain branch from 000f7af to 0e3b36c Compare March 26, 2025 00:48


# Azure Keyvault Securitydomain client library for Python
<!-- write necessary description of service -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like readme needs to be filled out

:paramtype api_version: str
"""

def __init__(self, vault_base_url: str, credential: "TokenCredential", **kwargs: Any) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that other keyvault libraries use vault_url. Is there a reason this library should have a different name?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user-facing client, SecurityDomainClient, exposes vault_url instead to match other libraries. Generated clients across KV consistently use vault_base_url because of the spec definition, but we always adjust this in the convenience layer.

PollingReturnType_co = TypeVar("PollingReturnType_co", covariant=True)


class AsyncPollingTerminationMixin(AsyncLROBasePolling):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we inherit from AsyncLROBasePolling here b/c of finished? Could finished be defined on AsyncSecurityDomainDownloadPollingMethod and AsyncSecurityDomainUploadPollingMethod?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the polling methods that use this mixin already inherit from AsyncLROBasePolling as well, we could possibly drop this inheritance -- we would just need to implement _SansIOLROBasePolling.status here. I defined this in a mixin to share the functionality across the two polling methods that use it (the same goes for the AsyncNoPollingMixin)

certificate_info_object: Union[CertificateInfoObject, JSON, IO[bytes]],
*,
content_type: str = "application/json",
polling: Optional[Literal[False]] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we've ever exposed polling as a public, documented keyword. Curious what our architects think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is a main point where I think the design could be improved. If we don't split up begin_download into two methods (one for getting the security domain immediately, and one for polling on HSM activation) then I think we should probably change this to something like skip_activation_polling (or something with a better name). cc @annatisch

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: I changed this to skip_activation_polling for now. Clearer on what the argument does, and doesn't expose the polling kwarg


#### Prequisites

- Python 3.8 or later is required to use this package.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3.9 :)

"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

py 313 will need to be added here :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Client This issue points to a problem in the data-plane of the library. KeyVault
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants