Samples & readmes (#2744)
* samples * readme1 * rename misnamed type, readmes * readmes, first pass, no links * undo some uneeded changes * PR comments
This commit is contained in:
parent
68100a543c
commit
512ae655b2
@ -78,7 +78,7 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
add_subdirectory(test/ut)
|
||||
add_subdirectory(test/sample)
|
||||
add_subdirectory(test/test-app)
|
||||
endif()
|
||||
|
||||
if (BUILD_PERFORMANCE_TESTS)
|
||||
@ -86,7 +86,7 @@ if (BUILD_PERFORMANCE_TESTS)
|
||||
endif()
|
||||
|
||||
if(BUILD_SAMPLES)
|
||||
#add_subdirectory(test/samples)
|
||||
add_subdirectory(test/samples)
|
||||
endif()
|
||||
|
||||
az_vcpkg_export(
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#to be edited to something more useful before first release
|
||||
# Azure Security Keyvault Secrets Package client library for C++
|
||||
|
||||
Azure Security Keyvault Secrets Package client library for C++ (`azure-security-keyvault-secrets`) matches necessary patterns that the development team has established to create a unified SDK written in the C++ programming language. These libraries follow the Azure SDK Design Guidelines for C++.
|
||||
@ -7,23 +6,176 @@ The library allows client libraries to expose common functionality in a consiste
|
||||
|
||||
## Getting started
|
||||
|
||||
For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md)
|
||||
### Install the package
|
||||
Install the Azure Key Vault secrets client library for C++ with vcpkg:
|
||||
|
||||
# Key concepts
|
||||
```cmd
|
||||
vcpkg install azure-security-keyvault-secrets-cpp
|
||||
```
|
||||
|
||||
Bullet point list of your library's main concepts.
|
||||
### Prerequisites
|
||||
* An [Azure subscription][azure_sub].
|
||||
* An existing Azure Key Vault. If you need to create an Azure Key Vault, you can use the Azure Portal or [Azure CLI][azure_cli].
|
||||
|
||||
# Examples
|
||||
If you use the Azure CLI, replace `<your-resource-group-name>` and `<your-key-vault-name>` with your own, unique names:
|
||||
|
||||
Examples of some of the key concepts for your library.
|
||||
```PowerShell
|
||||
az keyvault create --resource-group <your-resource-group-name> --name <your-key-vault-name>
|
||||
```
|
||||
|
||||
# Troubleshooting
|
||||
## Key concepts
|
||||
|
||||
### SecretClient
|
||||
`SecretClient` provides synchronous operations exists in the SDK. Once you've initialized a `SecretClient`, you can interact with the primary resource types in Azure Key Vault.
|
||||
|
||||
### Thread safety
|
||||
|
||||
We guarantee that all client instance methods are thread-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/cpp_introduction.html#thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across threads.
|
||||
|
||||
### Additional concepts
|
||||
|
||||
<!-- CLIENT COMMON BAR -->
|
||||
|
||||
[Replaceable HTTP transport adapter](https://github.com/Azure/azure-sdk-for-cpp/tree/main/sdk/core/azure-core#http-transport-adapter) |
|
||||
[Long-running operations](https://github.com/Azure/azure-sdk-for-cpp/tree/main/sdk/core/azure-core#long-running-operations) |
|
||||
|
||||
<!-- CLIENT COMMON BAR -->
|
||||
|
||||
## Examples
|
||||
|
||||
For detailed samples please review the samples provided.
|
||||
|
||||
### Create a client
|
||||
|
||||
First step is to create a SecretClient.
|
||||
|
||||
```cpp Snippet:SecretSample1CreateCredential
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
// create client
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
### Create a secret
|
||||
|
||||
We call the secret client to create a secret.
|
||||
|
||||
```cpp Snippet:SecretSample1SetSecret
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
```
|
||||
|
||||
### Get a secret
|
||||
|
||||
We retrieve a secret by name.
|
||||
|
||||
```cpp Snippet:SecretSample1GetSecret
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
### Update a secret
|
||||
|
||||
Updating an existing secret
|
||||
|
||||
```cpp Snippet:SecretSample1UpdateSecretProperties
|
||||
// change one of the properties
|
||||
secret.Properties.ContentType = "my content";
|
||||
// update the secret
|
||||
Secret updatedSecret = secretClient.UpdateSecretProperties(secret.Name, secret.Properties.Version, secret.Properties)
|
||||
.Value;
|
||||
std::cout << "Secret's content type is now " << updatedSecret.Properties.ContentType.Value()
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
### Delete a secret
|
||||
|
||||
Delete an existing secret.
|
||||
|
||||
```cpp Snippet:SecretSample1DeleteSecret
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
```
|
||||
|
||||
### Delete and purge a secret
|
||||
|
||||
Delete and Purge a secret.
|
||||
|
||||
```cpp Snippet:SecretSample1DeleteSecret
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
// purge the deleted secret
|
||||
secretClient.PurgeDeletedSecret(secret.Name);
|
||||
```
|
||||
|
||||
### List Secrets
|
||||
|
||||
List all the secrets in keyvault.
|
||||
|
||||
```cpp Snippet:SecretSample4ListAllSecrets
|
||||
// get properties of secrets
|
||||
for (auto secrets = secretClient.GetPropertiesOfSecrets(); secrets.HasPage(); secrets.MoveToNextPage())
|
||||
{ // go through every secret of each page returned
|
||||
for (auto const& secret : secrets.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << secret.Name << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
When you interact with the Azure Key Vault Secrets client library using the C++ SDK, errors returned by the service correspond to the same HTTP status codes returned for requests.
|
||||
|
||||
For example, if you try to retrieve a key that doesn't exist in your Azure Key Vault, a `404` error is returned, indicating "Not Found".
|
||||
|
||||
```cpp
|
||||
try
|
||||
{
|
||||
Secret secret = client.GetSecret("some_secret").Value;
|
||||
}
|
||||
catch (const Azure::Core::RequestFailedException& ex)
|
||||
{
|
||||
std::cout << std::underlying_type<Azure::Core::Http::HttpStatusCode>::type(ex.StatusCode);
|
||||
}
|
||||
```
|
||||
|
||||
You will notice that additional information is logged, like the client request ID of the operation.
|
||||
|
||||
Running into issues? This section should contain details as to what to do there.
|
||||
|
||||
# Next steps
|
||||
|
||||
More sample code should go here, along with links out to the appropriate example tests.
|
||||
Several Azure Key Vault secrets client library samples are available to you in this GitHub repository. These samples provide example code for additional scenarios commonly encountered while working with Azure Key Vault:
|
||||
|
||||
* Sample1-Basic-Operations:
|
||||
* Create a secret
|
||||
* Get a secret
|
||||
* Update a secret
|
||||
* Delete and Purge a secret
|
||||
|
||||
* Sample2-Backup-Restore
|
||||
* Backup a secret
|
||||
* Restore a deleted secret
|
||||
|
||||
* Sample3-Delete-Recover
|
||||
* Delete a secret
|
||||
* Recover a deleted Secret
|
||||
|
||||
* Sample4-Get-Secrets-Deleted
|
||||
* List all secrets
|
||||
* List all of a secrets versions
|
||||
* List all deletes secrets
|
||||
* Get properties of a deleted secret
|
||||
|
||||
## Contributing
|
||||
For details on contributing to this repository, see the [contributing guide][azure_sdk_for_cpp_contributing].
|
||||
|
||||
@ -20,7 +20,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
/**
|
||||
* @brief Represents a long running operation to restore a deleted secret.
|
||||
*/
|
||||
class RestoreDeletedSecretOperation final : public Azure::Core::Operation<Secret> {
|
||||
class RecoverDeletedSecretOperation final : public Azure::Core::Operation<Secret> {
|
||||
|
||||
private:
|
||||
friend class SecretClient;
|
||||
@ -41,11 +41,11 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
*
|
||||
* Since C++ doesn't offer `internal` access, we use friends-only instead.
|
||||
*/
|
||||
RestoreDeletedSecretOperation(
|
||||
RecoverDeletedSecretOperation(
|
||||
std::shared_ptr<SecretClient> secretClient,
|
||||
Azure::Response<Secret> response);
|
||||
|
||||
RestoreDeletedSecretOperation(
|
||||
RecoverDeletedSecretOperation(
|
||||
std::string resumeToken,
|
||||
std::shared_ptr<SecretClient> secretClient);
|
||||
|
||||
@ -75,7 +75,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
std::string GetResumeToken() const override { return m_continuationToken; }
|
||||
|
||||
/**
|
||||
* @brief Create a #RestoreDeletedSecretOperation from the \p resumeToken fetched from
|
||||
* @brief Create a #RecoverDeletedSecretOperation from the \p resumeToken fetched from
|
||||
* another `Operation<T>`, updated to the the latest operation status.
|
||||
*
|
||||
* @remark After the operation is initialized, it is used to poll the last update from the
|
||||
@ -85,9 +85,9 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
* operation.
|
||||
* @param client A #secretClient that is used for getting status updates.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return RestoreDeletedSecretOperation
|
||||
* @return RecoverDeletedSecretOperation
|
||||
*/
|
||||
static RestoreDeletedSecretOperation CreateFromResumeToken(
|
||||
static RecoverDeletedSecretOperation CreateFromResumeToken(
|
||||
std::string const& resumeToken,
|
||||
SecretClient const& client,
|
||||
Azure::Core::Context const& context = Azure::Core::Context());
|
||||
|
||||
@ -23,10 +23,11 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
* @brief Define a single page to list the secrets from the Key Vault.
|
||||
*
|
||||
*/
|
||||
class SecretPropertiesPagedResponse final : public Azure::Core::PagedResponse<SecretProperties> {
|
||||
class SecretPropertiesPagedResponse final
|
||||
: public Azure::Core::PagedResponse<SecretPropertiesPagedResponse> {
|
||||
private:
|
||||
friend class SecretClient;
|
||||
friend class Azure::Core::PagedResponse<SecretProperties>;
|
||||
friend class Azure::Core::PagedResponse<SecretPropertiesPagedResponse>;
|
||||
|
||||
std::string m_secretName;
|
||||
std::shared_ptr<SecretClient> m_secretClient;
|
||||
|
||||
@ -239,7 +239,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
* @param name The name of the secret.
|
||||
* @param context The context for the operation can be used for request cancellation.
|
||||
*/
|
||||
Azure::Security::KeyVault::Secrets::RestoreDeletedSecretOperation StartRecoverDeletedSecret(
|
||||
Azure::Security::KeyVault::Secrets::RecoverDeletedSecretOperation StartRecoverDeletedSecret(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
|
||||
@ -9,9 +9,8 @@
|
||||
#include "azure/keyvault/secrets/keyvault_operations.hpp"
|
||||
#include "azure/keyvault/secrets/secret_client.hpp"
|
||||
#include "private/secret_serializers.hpp"
|
||||
// RestoreDeletedSecretOperation
|
||||
|
||||
Azure::Response<Secret> RestoreDeletedSecretOperation::PollUntilDoneInternal(
|
||||
Azure::Response<Secret> RecoverDeletedSecretOperation::PollUntilDoneInternal(
|
||||
std::chrono::milliseconds period,
|
||||
Azure::Core::Context& context)
|
||||
{
|
||||
@ -30,46 +29,44 @@ Azure::Response<Secret> RestoreDeletedSecretOperation::PollUntilDoneInternal(
|
||||
m_value, std::make_unique<Azure::Core::Http::RawResponse>(*m_rawResponse));
|
||||
}
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> RestoreDeletedSecretOperation::PollInternal(
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> RecoverDeletedSecretOperation::PollInternal(
|
||||
Azure::Core::Context const& context)
|
||||
{
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> rawResponse;
|
||||
if (IsDone())
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
rawResponse
|
||||
= m_secretClient->GetSecret(m_value.Name, GetSecretOptions(), context).RawResponse;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException& error)
|
||||
{
|
||||
rawResponse = std::move(error.RawResponse);
|
||||
}
|
||||
|
||||
switch (rawResponse->GetStatusCode())
|
||||
{
|
||||
case Azure::Core::Http::HttpStatusCode::Ok:
|
||||
case Azure::Core::Http::HttpStatusCode::Forbidden: {
|
||||
m_status = Azure::Core::OperationStatus::Succeeded;
|
||||
break;
|
||||
}
|
||||
case Azure::Core::Http::HttpStatusCode::NotFound: {
|
||||
m_status = Azure::Core::OperationStatus::Running;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Azure::Core::RequestFailedException(rawResponse);
|
||||
}
|
||||
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value = _detail::SecretSerializer::Deserialize(m_value.Name, *rawResponse);
|
||||
}
|
||||
rawResponse = m_secretClient->GetSecret(m_value.Name, GetSecretOptions(), context).RawResponse;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException& error)
|
||||
{
|
||||
rawResponse = std::move(error.RawResponse);
|
||||
}
|
||||
|
||||
switch (rawResponse->GetStatusCode())
|
||||
{
|
||||
case Azure::Core::Http::HttpStatusCode::Ok:
|
||||
case Azure::Core::Http::HttpStatusCode::Forbidden: {
|
||||
m_status = Azure::Core::OperationStatus::Succeeded;
|
||||
break;
|
||||
}
|
||||
case Azure::Core::Http::HttpStatusCode::NotFound: {
|
||||
m_status = Azure::Core::OperationStatus::Running;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Azure::Core::RequestFailedException(rawResponse);
|
||||
}
|
||||
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value = _detail::SecretSerializer::Deserialize(m_value.Name, *rawResponse);
|
||||
}
|
||||
|
||||
return rawResponse;
|
||||
}
|
||||
|
||||
RestoreDeletedSecretOperation::RestoreDeletedSecretOperation(
|
||||
RecoverDeletedSecretOperation::RecoverDeletedSecretOperation(
|
||||
std::shared_ptr<SecretClient> secretClient,
|
||||
Azure::Response<Secret> response)
|
||||
: m_secretClient(secretClient)
|
||||
@ -86,7 +83,7 @@ RestoreDeletedSecretOperation::RestoreDeletedSecretOperation(
|
||||
}
|
||||
}
|
||||
|
||||
RestoreDeletedSecretOperation::RestoreDeletedSecretOperation(
|
||||
RecoverDeletedSecretOperation::RecoverDeletedSecretOperation(
|
||||
std::string resumeToken,
|
||||
std::shared_ptr<SecretClient> secretClient)
|
||||
: m_secretClient(secretClient), m_continuationToken(std::move(resumeToken))
|
||||
@ -94,16 +91,16 @@ RestoreDeletedSecretOperation::RestoreDeletedSecretOperation(
|
||||
m_value.Name = resumeToken;
|
||||
}
|
||||
|
||||
RestoreDeletedSecretOperation RestoreDeletedSecretOperation::CreateFromResumeToken(
|
||||
RecoverDeletedSecretOperation RecoverDeletedSecretOperation::CreateFromResumeToken(
|
||||
std::string const& resumeToken,
|
||||
SecretClient const& client,
|
||||
Azure::Core::Context const& context)
|
||||
{
|
||||
RestoreDeletedSecretOperation operation(resumeToken, std::make_shared<SecretClient>(client));
|
||||
RecoverDeletedSecretOperation operation(resumeToken, std::make_shared<SecretClient>(client));
|
||||
operation.Poll(context);
|
||||
return operation;
|
||||
}
|
||||
// DeleteSecretOperation
|
||||
|
||||
Azure::Response<DeletedSecret> DeleteSecretOperation::PollUntilDoneInternal(
|
||||
std::chrono::milliseconds period,
|
||||
Azure::Core::Context& context)
|
||||
@ -126,36 +123,34 @@ std::unique_ptr<Azure::Core::Http::RawResponse> DeleteSecretOperation::PollInter
|
||||
Azure::Core::Context const& context)
|
||||
{
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> rawResponse;
|
||||
if (!IsDone())
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
rawResponse = m_secretClient->GetDeletedSecret(m_value.Name, context).RawResponse;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException& error)
|
||||
{
|
||||
rawResponse = std::move(error.RawResponse);
|
||||
}
|
||||
rawResponse = m_secretClient->GetDeletedSecret(m_value.Name, context).RawResponse;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException& error)
|
||||
{
|
||||
rawResponse = std::move(error.RawResponse);
|
||||
}
|
||||
|
||||
switch (rawResponse->GetStatusCode())
|
||||
{
|
||||
case Azure::Core::Http::HttpStatusCode::Ok:
|
||||
case Azure::Core::Http::HttpStatusCode::Forbidden: {
|
||||
m_status = Azure::Core::OperationStatus::Succeeded;
|
||||
break;
|
||||
}
|
||||
case Azure::Core::Http::HttpStatusCode::NotFound: {
|
||||
m_status = Azure::Core::OperationStatus::Running;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Azure::Core::RequestFailedException(rawResponse);
|
||||
switch (rawResponse->GetStatusCode())
|
||||
{
|
||||
case Azure::Core::Http::HttpStatusCode::Ok:
|
||||
case Azure::Core::Http::HttpStatusCode::Forbidden: {
|
||||
m_status = Azure::Core::OperationStatus::Succeeded;
|
||||
break;
|
||||
}
|
||||
case Azure::Core::Http::HttpStatusCode::NotFound: {
|
||||
m_status = Azure::Core::OperationStatus::Running;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Azure::Core::RequestFailedException(rawResponse);
|
||||
}
|
||||
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value = _detail::DeletedSecretSerializer::Deserialize(m_value.Name, *rawResponse);
|
||||
}
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value = _detail::DeletedSecretSerializer::Deserialize(m_value.Name, *rawResponse);
|
||||
}
|
||||
return rawResponse;
|
||||
}
|
||||
|
||||
@ -209,10 +209,10 @@ Azure::Security::KeyVault::Secrets::DeleteSecretOperation SecretClient::StartDel
|
||||
{_detail::SecretPath, name}));
|
||||
}
|
||||
|
||||
Azure::Security::KeyVault::Secrets::RestoreDeletedSecretOperation SecretClient::
|
||||
Azure::Security::KeyVault::Secrets::RecoverDeletedSecretOperation SecretClient::
|
||||
StartRecoverDeletedSecret(std::string const& name, Azure::Core::Context const& context) const
|
||||
{
|
||||
return Azure::Security::KeyVault::Secrets::RestoreDeletedSecretOperation(
|
||||
return Azure::Security::KeyVault::Secrets::RecoverDeletedSecretOperation(
|
||||
std::make_shared<SecretClient>(*this),
|
||||
m_protocolClient->SendRequest<Secret>(
|
||||
context,
|
||||
|
||||
@ -350,6 +350,7 @@ DeletedSecretPagedResponse DeletedSecretPagedResultSerializer::Deserialize(
|
||||
DeletedSecret item;
|
||||
item.Id = secretProperties[_detail::IdPropertyName].get<std::string>();
|
||||
_detail::SecretSerializer::ParseIDUrl(item.Properties, item.Id);
|
||||
item.Name = item.Properties.Name;
|
||||
// Parse URL for the various attributes
|
||||
if (secretProperties.contains(_detail::AttributesPropertyName))
|
||||
{
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
add_subdirectory(sample1-basic-operations)
|
||||
add_subdirectory(sample2-backup-restore)
|
||||
add_subdirectory(sample3-delete-recover)
|
||||
add_subdirectory(sample4-get-secrets-deleted)
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample1-basic-operations LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample1-basic-operations
|
||||
sample1-basic-operations.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample1-basic-operations PRIVATE azure-security-keyvault-secrets azure-identity)
|
||||
@ -0,0 +1,86 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault Secrets SDK client for
|
||||
* C++ to create, get, update, delete and purge a secret.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the Key Vault account URL.
|
||||
* - AZURE_TENANT_ID: Tenant ID for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The Client ID to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The client secret.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/keyvault_secrets.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
// create client
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
try
|
||||
{
|
||||
// create secret
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
|
||||
// change one of the properties
|
||||
secret.Properties.ContentType = "my content";
|
||||
// update the secret
|
||||
Secret updatedSecret
|
||||
= secretClient
|
||||
.UpdateSecretProperties(secret.Name, secret.Properties.Version, secret.Properties)
|
||||
.Value;
|
||||
std::cout << "Secret's content type is now " << updatedSecret.Properties.ContentType.Value()
|
||||
<< std::endl;
|
||||
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// purge the deleted secret
|
||||
secretClient.PurgeDeletedSecret(secret.Name);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException const& e)
|
||||
{
|
||||
std::cout << "Key Vault Secret Client Exception happened:" << std::endl
|
||||
<< e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
# Creating, getting, updating, and deleting secrets
|
||||
|
||||
This sample demonstrates how to create, get, update, and delete and purge a secret in Azure Key Vault.
|
||||
To get started, you'll need a URI to an Azure Key Vault.
|
||||
|
||||
## Creating a SecretClient
|
||||
|
||||
To create a new `SecretClient` to create, get, update, or delete secrets, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Secrets client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the Tenant ID, Client ID and Client Secret as environment variables.
|
||||
|
||||
```cpp Snippet:SecretSample1CreateCredential
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:SecretSample1SecretClient
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a Secret
|
||||
|
||||
To create a secret all you need to set id the name and secret value.
|
||||
|
||||
```cpp Snippet:SecretSample1SetSecret
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
```
|
||||
|
||||
## Getting a Secret
|
||||
|
||||
To get a secret from the keyvault you will need to call GetSecret.
|
||||
|
||||
```cpp Snippet:SecretSample1GetSecret
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
## Updating secret properties
|
||||
|
||||
We forgot to set the content type for the secret we created, we can do that using the UpdateSecretProperties method.
|
||||
|
||||
|
||||
```cpp Snippet:SecretSample1UpdateSecretProperties
|
||||
// change one of the properties
|
||||
secret.Properties.ContentType = "my content";
|
||||
// update the secret
|
||||
Secret updatedSecret = secretClient.UpdateSecretProperties(secret.Name, secret.Properties.Version, secret.Properties)
|
||||
.Value;
|
||||
std::cout << "Secret's content type is now " << updatedSecret.Properties.ContentType.Value()
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
## Deleting a secret
|
||||
|
||||
The secret is no longer needed so we need to delete it.
|
||||
|
||||
```cpp Snippet:SecretSample1DeleteSecret
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
```
|
||||
|
||||
## Purging a deleted key
|
||||
|
||||
If the Azure Key Vault is soft delete-enabled and you want to permanently delete the secret before its `ScheduledPurgeDate`, the secret needs to be purged.
|
||||
|
||||
```cpp Snippet:SecretSample1PurgeSecret
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// purge the deleted secret
|
||||
secretClient.PurgeDeletedSecret(secret.Name);
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample2-backup-restore LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample2-backup-restore
|
||||
sample2-backup-restore.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample2-backup-restore PRIVATE azure-security-keyvault-secrets azure-identity)
|
||||
@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault Secrets SDK client for
|
||||
* C++ to backup, restore, delete and purge a secret.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the Key Vault account URL.
|
||||
* - AZURE_TENANT_ID: Tenant ID for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The Client ID to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The client secret.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/keyvault_secrets.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace std::chrono_literals;
|
||||
void AssertSecretsEqual(Secret const& expected, Secret const& actual);
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
// create client
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string secretName("MySampleSecret2");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
try
|
||||
{
|
||||
// create secret
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
|
||||
size_t backUpSize = 0;
|
||||
{
|
||||
std::cout << "\t-Backup Key" << std::endl;
|
||||
auto backupSecretResult = secretClient.BackupSecret(secret.Name).Value;
|
||||
auto const& backedupSecret = backupSecretResult.Secret;
|
||||
backUpSize = backedupSecret.size();
|
||||
|
||||
// save data to file
|
||||
std::cout << "\t-Save to file" << std::endl;
|
||||
std::ofstream savedFile;
|
||||
savedFile.open("backup.dat");
|
||||
for (auto const& data : backedupSecret)
|
||||
{
|
||||
savedFile << data;
|
||||
}
|
||||
savedFile.close();
|
||||
}
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
// purge the deleted secret
|
||||
secretClient.PurgeDeletedSecret(secret.Name);
|
||||
|
||||
// let's wait for one minute so we know the key was purged.
|
||||
std::this_thread::sleep_for(60s);
|
||||
|
||||
// Restore the key from the file backup
|
||||
std::cout << "\t-Read from file." << std::endl;
|
||||
std::ifstream inFile;
|
||||
inFile.open("backup.dat");
|
||||
std::vector<uint8_t> inMemoryBackup(backUpSize);
|
||||
inFile >> inMemoryBackup.data();
|
||||
inFile.close();
|
||||
|
||||
std::cout << "\t-Restore Key" << std::endl;
|
||||
auto restoredSecret = secretClient.RestoreSecretBackup(inMemoryBackup).Value;
|
||||
|
||||
AssertSecretsEqual(secret, restoredSecret);
|
||||
|
||||
operation = secretClient.StartDeleteSecret(restoredSecret.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
operation.PollUntilDone(2s);
|
||||
secretClient.PurgeDeletedSecret(restoredSecret.Name);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException const& e)
|
||||
{
|
||||
std::cout << "Key Vault Secret Client Exception happened:" << std::endl
|
||||
<< e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AssertSecretsEqual(Secret const& expected, Secret const& actual)
|
||||
{
|
||||
#if defined(NDEBUG)
|
||||
// Use (void) to silence unused warnings.
|
||||
(void)expected;
|
||||
(void)actual;
|
||||
#endif
|
||||
assert(expected.Name == actual.Name);
|
||||
assert(expected.Properties.Version == actual.Properties.Version);
|
||||
assert(expected.Id == actual.Id);
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
# Backup and Restore secrets
|
||||
|
||||
This sample demonstrates how to backup and restore in Azure Key Vault.
|
||||
To get started, you'll need a URI to an Azure Key Vault.
|
||||
|
||||
## Creating a SecretClient
|
||||
|
||||
To create a new `SecretClient` to create, get, update, or delete secrets, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Secrets client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the Tenant ID, Client ID and Client Secret as environment variables.
|
||||
|
||||
```cpp Snippet:SecretSample2CreateCredential
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:SecretSample2SecretClient
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a Secret
|
||||
|
||||
To create a secret all you need to set id the name and secret value.
|
||||
|
||||
```cpp Snippet:SecretSample2SetSecret
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
```
|
||||
|
||||
## Getting a Secret
|
||||
|
||||
To get a secret from the keyvault you will need to call GetSecret.
|
||||
|
||||
```cpp Snippet:SecretSample2GetSecret
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
## Creating a Backup for the secret properties
|
||||
|
||||
In order to get the backup of the secret we need to call BackupSecret, which will return a vector of bytes representing the backed up content.
|
||||
|
||||
|
||||
```cpp Snippet:SecretSample2BackupSecret
|
||||
std::cout << "\t-Backup Key" << std::endl;
|
||||
std::vector<uint8_t> backupKey(secretClient.BackupSecret(secret.Name).Value.Secret);
|
||||
backUpSize = backupKey.size();
|
||||
```
|
||||
|
||||
## Deleting the secret in order to later restore it
|
||||
|
||||
The secret is no longer needed so we need to delete it.
|
||||
|
||||
```cpp Snippet:SecretSample2DeleteSecret
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
```
|
||||
|
||||
## Purging a deleted key
|
||||
|
||||
If the Azure Key Vault is soft delete-enabled and you want to permanently delete the secret before its `ScheduledPurgeDate`, the secret needs to be purged.
|
||||
|
||||
```cpp Snippet:SecretSample2PurgeSecret
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// purge the deleted secret
|
||||
secretClient.PurgeDeletedSecret(secret.Name);
|
||||
```
|
||||
|
||||
## Restoring a secret
|
||||
|
||||
In order to restore a secret we need to call RestoreSecretBackup api passing in the byte vector obtained at the previous(backup) step.
|
||||
|
||||
```cpp Snippet:SecretSample2RestoreSecret
|
||||
std::cout << "\t-Restore Key" << std::endl;
|
||||
auto restoredSecret = secretClient.RestoreSecretBackup(inMemoryBackup).Value;
|
||||
```
|
||||
|
||||
## Source
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample3-delete-recover LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample3-delete-recover
|
||||
sample3-delete-recover.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample3-delete-recover PRIVATE azure-security-keyvault-secrets azure-identity)
|
||||
@ -0,0 +1,102 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault Secrets SDK client for
|
||||
* C++ to delete and restore a secret.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the Key Vault account URL.
|
||||
* - AZURE_TENANT_ID: Tenant ID for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The Client ID to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The client secret.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/keyvault_secrets.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace std::chrono_literals;
|
||||
void AssertSecretsEqual(Secret const& expected, Secret const& actual);
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
// create client
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// create secret
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// call recover secret
|
||||
RecoverDeletedSecretOperation recoverOperation
|
||||
= secretClient.StartRecoverDeletedSecret(secret.Name);
|
||||
|
||||
// poll until done
|
||||
Secret restoredSecret = recoverOperation.PollUntilDone(2s).Value;
|
||||
|
||||
AssertSecretsEqual(secret, restoredSecret);
|
||||
|
||||
// cleanup
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation cleanupOperation = secretClient.StartDeleteSecret(restoredSecret.Name);
|
||||
cleanupOperation.PollUntilDone(2s);
|
||||
secretClient.PurgeDeletedSecret(restoredSecret.Name);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException const& e)
|
||||
{
|
||||
std::cout << "Key Vault Secret Client Exception happened:" << std::endl
|
||||
<< e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AssertSecretsEqual(Secret const& expected, Secret const& actual)
|
||||
{
|
||||
#if defined(NDEBUG)
|
||||
// Use (void) to silence unused warnings.
|
||||
(void)expected;
|
||||
(void)actual;
|
||||
#endif
|
||||
assert(expected.Name == actual.Name);
|
||||
assert(expected.Properties.Version == actual.Properties.Version);
|
||||
assert(expected.Id == actual.Id);
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
# Delete and recover deleted secrets
|
||||
|
||||
This sample demonstrates how to delete and recover a deleted secret in Azure Key Vault.
|
||||
|
||||
## Creating a SecretClient
|
||||
|
||||
To create a new `SecretClient` to create, get, update, or delete secrets, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Secrets client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the Tenant ID, Client ID and Client Secret as environment variables.
|
||||
|
||||
```cpp Snippet:SecretSample3CreateCredential
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:SecretSample3SecretClient
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a Secret
|
||||
|
||||
To create a secret all you need to set id the name and secret value.
|
||||
|
||||
```cpp Snippet:SecretSample3SetSecret
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
secretClient.SetSecret(secretName, secretValue);
|
||||
```
|
||||
|
||||
## Getting a Secret
|
||||
|
||||
To get a secret from the keyvault you will need to call GetSecret.
|
||||
|
||||
```cpp Snippet:SecretSample3GetSecret
|
||||
// get secret
|
||||
Secret secret = secretClient.GetSecret(secretName).Value;
|
||||
std::cout << "Secret is returned with name " << secret.Name << " and value " << secret.Value
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
## Deleting a secret
|
||||
|
||||
The secret is no longer needed so we need to delete it.
|
||||
|
||||
```cpp Snippet:SecretSample3DeleteSecret
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name);
|
||||
```
|
||||
|
||||
## Recover a Deleted secret
|
||||
|
||||
To recover a deleted secret we need to call StartRecoverDeletedSecret and then poll untill the operation is done.
|
||||
|
||||
```cpp Snippet:SecretSample3RecoverSecret
|
||||
// call restore secret
|
||||
RecoverDeletedSecretOperation recoverOperation = secretClient.StartRecoverDeletedSecret(secret.Name);
|
||||
|
||||
// poll until done
|
||||
Secret restoredSecret = recoverOperation.PollUntilDone(2s).Value;
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample4-get-secrets-deleted LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample4-get-secrets-deleted
|
||||
sample4-get-secrets-deleted.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample4-get-secrets-deleted PRIVATE azure-security-keyvault-secrets azure-identity)
|
||||
@ -0,0 +1,115 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault Secrets SDK client for
|
||||
* C++ to get secrets, get secret versions, get deleted secrets, get deleted secret.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the Key Vault account URL.
|
||||
* - AZURE_TENANT_ID: Tenant ID for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The Client ID to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The client secret.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/keyvault_secrets.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
// create client
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretName2("MySampleSecret2");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
try
|
||||
{
|
||||
// create secret
|
||||
Secret secret1 = secretClient.SetSecret(secretName, secretValue).Value;
|
||||
Secret secret2 = secretClient.SetSecret(secretName2, secretValue).Value;
|
||||
|
||||
std::cout << "Secret1 Version : " << secret1.Properties.Version << std::endl;
|
||||
|
||||
// get properties of secrets
|
||||
for (auto secrets = secretClient.GetPropertiesOfSecrets(); secrets.HasPage();
|
||||
secrets.MoveToNextPage())
|
||||
{ // go through every secret of each page returned
|
||||
for (auto const& secret : secrets.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << secret.Name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// get all the versions of a secret
|
||||
for (auto secretsVersion = secretClient.GetPropertiesOfSecretsVersions(secret1.Name);
|
||||
secretsVersion.HasPage();
|
||||
secretsVersion.MoveToNextPage())
|
||||
{ // go through each version of the secret
|
||||
for (auto const& secret : secretsVersion.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << secret.Name
|
||||
<< " and with version: " << secret.Version << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret1.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// start deleting the secret
|
||||
operation = secretClient.StartDeleteSecret(secret2.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// get all the versions of a secret
|
||||
for (auto deletedSecrets = secretClient.GetDeletedSecrets(); deletedSecrets.HasPage();
|
||||
deletedSecrets.MoveToNextPage())
|
||||
{ // go through each version of the secret
|
||||
for (auto const& deletedSecret : deletedSecrets.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << deletedSecret.Name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// get one deleted secret
|
||||
auto deletedSecret = secretClient.GetDeletedSecret(secret1.Name);
|
||||
std::cout << "Deleted Secret with name: " << deletedSecret.Value.Name;
|
||||
|
||||
// cleanup
|
||||
secretClient.PurgeDeletedSecret(secret1.Name);
|
||||
secretClient.PurgeDeletedSecret(secret2.Name);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Core::RequestFailedException const& e)
|
||||
{
|
||||
std::cout << "Key Vault Secret Client Exception happened:" << std::endl
|
||||
<< e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
# Get Secrets, Get Secrets Versions, Get Deleted Secrets, Get Deleted Secret
|
||||
|
||||
This sample demonstrates how to list all the secrets , all the versions of a secret, list all deleted secrets, and get the properties of a deleted secret.
|
||||
|
||||
## Creating a SecretClient
|
||||
|
||||
To create a new `SecretClient` to create, get, update, or delete secrets, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Secrets client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the Tenant ID, Client ID and Client Secret as environment variables.
|
||||
|
||||
```cpp Snippet:SecretSample4CreateCredential
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential = std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:SecretSample4SecretClient
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a couple of Secrets
|
||||
|
||||
To create a secret all you need to set id the name and secret value.
|
||||
|
||||
```cpp Snippet:SecretSample4SetSecret
|
||||
std::string secretName("MySampleSecret");
|
||||
std::string secretName2("MySampleSecret2");
|
||||
std::string secretValue("my secret value");
|
||||
|
||||
Secret secret1 = secretClient.SetSecret(secretName, secretValue).Value;
|
||||
Secret secret2 = secretClient.SetSecret(secretName2, secretValue).Value;
|
||||
```
|
||||
|
||||
## Getting the properties of all the secrets in the keyvault
|
||||
|
||||
To get the properties of the secrets in the keyvault we will call GetPropertiesOfSecrets. The results of this call are paged to a maximum of 25 SecretProperties per page.
|
||||
|
||||
```cpp Snippet:SecretSample4ListAllSecrets
|
||||
// get properties of secrets
|
||||
for (auto secrets = secretClient.GetPropertiesOfSecrets(); secrets.HasPage(); secrets.MoveToNextPage())
|
||||
{ // go through every secret of each page returned
|
||||
for (auto const& secret : secrets.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << secret.Name << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Get the versions of a Secret
|
||||
|
||||
in order to list all the versions of a secret we need to call GetPropertiesOfSecretsVersions, which responds similarly with a paged response of up to 25 versions of the secret per page.
|
||||
|
||||
|
||||
```cpp Snippet:SecretSample4GetVersions
|
||||
// get all the versions of a secret
|
||||
for (auto secretsVersion = secretClient.GetPropertiesOfSecretsVersions(secret1.Name);
|
||||
secretsVersion.HasPage();
|
||||
secretsVersion.MoveToNextPage())
|
||||
{ // go through each version of the secret
|
||||
for (auto const& secret : secretsVersion.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << secret.Name
|
||||
<< " and with version: " << secret.Version << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Delete both secrets
|
||||
|
||||
The secrets is no longer needed so we need to delete them, in order to demonstrate the delete related operations. We shall not purge the secrets yet.
|
||||
|
||||
```cpp Snippet:SecretSample4DeleteSecrets
|
||||
// start deleting the secret
|
||||
DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret1.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
|
||||
// start deleting the secret
|
||||
operation = secretClient.StartDeleteSecret(secret2.Name);
|
||||
// You only need to wait for completion if you want to purge or recover the secret.
|
||||
operation.PollUntilDone(2s);
|
||||
```
|
||||
|
||||
## Get Deleted Secrets
|
||||
|
||||
To get a list of preprties of all deleted secrets we will call GetDeletedSecrets, similarly to the previous calls this is a paged response with the same limit of 25 items per response.
|
||||
|
||||
```cpp Snippet:SecretSample4GetDeletedSecrets
|
||||
// get all the versions of a secret
|
||||
for (auto deletedSecrets = secretClient.GetDeletedSecrets(); deletedSecrets.HasPage();
|
||||
deletedSecrets.MoveToNextPage())
|
||||
{ // go through each version of the secret
|
||||
for (auto const& deletedSecret : deletedSecrets.Items)
|
||||
{
|
||||
std::cout << "Found Secret with name: " << deletedSecret.Name << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Get Deleted Secret
|
||||
|
||||
To get information about a specific deleted secret we will call GetDeletedSecret passing the secret name as a parameter.
|
||||
|
||||
```cpp Snippet:SecretSample4GetDeletedSecret
|
||||
// get one deleted secret
|
||||
auto deletedSecret = secretClient.GetDeletedSecret(secret1.Name);
|
||||
std::cout << "Deleted Secret with name: " << deletedSecret.Value.Name;
|
||||
```
|
||||
|
||||
## Purge the secrets to cleanup
|
||||
|
||||
Since the secrets were deleted previously now we need to call purge to finish cleaning up.
|
||||
|
||||
```cpp Snippet:SecretSample4PurgeSecrets
|
||||
// cleanup
|
||||
secretClient.PurgeDeletedSecret(secret1.Name);
|
||||
secretClient.PurgeDeletedSecret(secret2.Name);
|
||||
```
|
||||
## Source
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md
|
||||
Loading…
Reference in New Issue
Block a user