Add CI pipeline step and script that validates all files in the repo contain ASCII-only bytes and no UTF-8 BOM (#4134)
* Add CI pipeline step and script that validates all files in the repo contain ASCII-only bytes and no UTF-8 BOM * Update platform-matrix.json to turn on CHECK_ASCII_CHARACTERS * Fix missing comma in json. * Update indentation in the ci.test.yml for the bash script * Exclude the .github folder and test recording json files. * Remove "recordings" exclusion since it doesn't exist anymore. * Fixed UTF-8 with BOM and other non-ASCII character issues within the files in the repo. * Exclude nlohmann json tests from ASCII validation check. * Log an intro to the CI console for the validation step. * Remove codecoverage.cmake exclusion. * Remove exclusion for docs and tools directories.
This commit is contained in:
Родитель
86aa9b4b0c
Коммит
876a7baaa5
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-DebugWithTests",
|
||||
|
|
|
@ -86,7 +86,7 @@ Most of the libcurl handle configuration becomes useless when the handle is chan
|
|||
|
||||
The most tedious task, while speaking raw HTTP, is reading and parsing responses. As mentioned before, the main purpose of using the poor man's substitute (custom protocol) to re-implement HTTP (even though libcurl provides HTTP support natively) is to enable an Azure SDK client to start a download operation and let customers to decide when to pull chunks of data from the response (directly from the network socket, without any intermediate buffers or using callback functions).
|
||||
|
||||
An HTTP request is nothing but a string with a specific format, it has special text delimiters to distinguish between the request line, headers and body. As soon as the server receives and parses the request, it would trigger an operation and eventually produce a response. The response needs to be HTTP formatted using text delimiters to indicate where the headers section starts and where it ends. Then the server will start sending small parts of it. On the client side, calling _curl_easy_recv()_ will get any bytes that have arrived. As soon as the function pulls the bytes from the socket, the socket will receive more data that will be written on top of the previous data. The function _curl_easy_recv()_ is a way to tell the OS, _“Hey, I got this data, you can write on top of it now"_.
|
||||
An HTTP request is nothing but a string with a specific format, it has special text delimiters to distinguish between the request line, headers and body. As soon as the server receives and parses the request, it would trigger an operation and eventually produce a response. The response needs to be HTTP formatted using text delimiters to indicate where the headers section starts and where it ends. Then the server will start sending small parts of it. On the client side, calling _curl_easy_recv()_ will get any bytes that have arrived. As soon as the function pulls the bytes from the socket, the socket will receive more data that will be written on top of the previous data. The function _curl_easy_recv()_ is a way to tell the OS, _"Hey, I got this data, you can write on top of it now"_.
|
||||
|
||||
Based on how _curl_easy_recv()_ behaves, and what the Azure SDK client is expecting, the libculTransportAdapter must keep calling _curl_easy_recv()_ until it finds the text delimiter that indicates the start of the HTTP body. When calling _curl_easy_recv()_, one of its input parameters is how many bytes to read from the socket. However, if there are not as many bytes in the socket at requested, the function will just get as much as it can. For example, if 1kb is requested to be pulled from the socket, the actual returned bytes might be 1kb (if that amount was ready in the socket) or less (if there were only 1023 bytes or less in the socket). This brings an interesting design question, how many bytes should the transport adapter request on every call to _curl_easy_recv()_?
|
||||
|
||||
|
@ -121,14 +121,14 @@ There are a few more variables to take into consideration. The HTTP protocol def
|
|||
|
||||
Calling _curl_easy_send()_ is a similar experience. It takes an input parameter which defines how much data to put into the network socket, and it returns how many bytes it was able to send. The LTA (libcurl transport adapter) implements an upload operation by calling _curl_easy_send()_ sequentially until all bytes are sent.
|
||||
The hardest thing to deal with, during an upload operation, is the speed that it takes the operating system to send bytes through the network. The OS sends bytes to the server and lets the socket in a state where it can take more data to be sent. The call to _curl_easy_send()_ returns as soon as the data is written to the socket, so, immediately calling the function again to send more data will most likely cause function to find the socket busy, because the OS is performing the I/O operation. This is another unfortunate side effect of using libcurl with custom protocol. By using the proper way, libcurl abstracts away all the operations between the application and the operating system sockets.
|
||||
When working on Unix systems (Linux and macOS), the LTA needs to import `sys/socket.h` . And when running for Windows, `winsock2h.h` is imported. These headers are used to check for socket updates, especially to poll for state change. That’s how the LTA knows when a socket is ready to be used.
|
||||
When working on Unix systems (Linux and macOS), the LTA needs to import `sys/socket.h` . And when running for Windows, `winsock2h.h` is imported. These headers are used to check for socket updates, especially to poll for state change. That's how the LTA knows when a socket is ready to be used.
|
||||
On the eyes of a customer, the LTA should provide the same level of experience, regardless of what libcurl mode it uses. If it is using custom protocol or proper way to consume libcurl, there should be no distinguish. This brings a complex challenge for the LTA. In terms of maintainability, libcurl will fix and maintain the code to support HTTP only for the proper mode. By using custom-protocol, LTA is manually implementing and supporting things that might have been already fixed in the past by the libcurl community. An example of a scenario like this can be found within the LTA Windows implementation, where _setsockopt()_ method must be called before writing to a socket to ensure the uploading chunk size of data is not reduced by Windows. The LTA goes as deep as the TCP implementation details to provide this patch. The side effect if this patch is not applied makes the LTA complete an upload operation __four times slower__ than using libcurl proper mode. And the adventure for discovering this patch requires running the proper mode, step by step (debugger), identifying the call stack deltas against the custom protocol mode. Or browsing the git commit history from libcurl, looking for tags like windows, performance, socket and/or uploading data. Trying to isolate related changes.
|
||||
|
||||
### Connection pool
|
||||
|
||||
There’s yet one more unfortunate detail for using libcurl with custom protocol, and that’s supporting the HTTP `keep alive` feature. Keep alive feature provides a huge performance improvement when using a secured connection (TLS). When a connection uses TLS to secure the data, there’s a time-consuming process where the server and the client both authenticate themselves and interchange valid certificates. This process starts with a handshake and completes when both server and client agree on how to encode and decode messages between them. Depending on the network speed, the entire process could take up to two seconds. If the request and response interchanged in the secured channel is just a few bytes, securing the connection could take more time than the actual data transferring. The keep alive feature is a mechanism to re-use a connection channel. In the case of a secured channel, an application can use the same connection to send requests, one after another, saving time and resources of securing a new connection for each request.
|
||||
There's yet one more unfortunate detail for using libcurl with custom protocol, and that's supporting the HTTP `keep alive` feature. Keep alive feature provides a huge performance improvement when using a secured connection (TLS). When a connection uses TLS to secure the data, there's a time-consuming process where the server and the client both authenticate themselves and interchange valid certificates. This process starts with a handshake and completes when both server and client agree on how to encode and decode messages between them. Depending on the network speed, the entire process could take up to two seconds. If the request and response interchanged in the secured channel is just a few bytes, securing the connection could take more time than the actual data transferring. The keep alive feature is a mechanism to re-use a connection channel. In the case of a secured channel, an application can use the same connection to send requests, one after another, saving time and resources of securing a new connection for each request.
|
||||
|
||||
Libcurl can automatically support the keep alive feature when using the proper mode. When _curl_easy_init(handle)_ is called, libcurl first check if there is already an open connection for the request described in the handle. Once the request is performed, libcurl will keep the connection open for some time in case there’s a new request for the same server. Nevertheless, if a libcurl handle is configured for custom protocol, libcurl does not provide a keep alive feature.
|
||||
Libcurl can automatically support the keep alive feature when using the proper mode. When _curl_easy_init(handle)_ is called, libcurl first check if there is already an open connection for the request described in the handle. Once the request is performed, libcurl will keep the connection open for some time in case there's a new request for the same server. Nevertheless, if a libcurl handle is configured for custom protocol, libcurl does not provide a keep alive feature.
|
||||
|
||||
The keep alive feature for libcurl is provided by the Azure SDK library directly. The library provides three main components to ensure keep alive connections for libcurl. The first one is the libcurl connection class, which is a wrapper for a libcurl handle. The second component is the pool of libcurl connections, which is a collection where connections can go in and out to be re-used. And the last component is a pool cleaner agent, which removes old connections from the pool. More details about each component are in the next paragraphs.
|
||||
|
||||
|
@ -141,11 +141,11 @@ The libcurl connection is typically wrapped within another container. In the cas
|
|||
|
||||
#### Connection Pool
|
||||
|
||||
The connection pool is a global and static singleton object. The pool provides an API to request a connection. Based on the set of options requested, the pool will search if there´s a connection which is not expired and was created with the same options. If one connection is found, it is moved out of the pool. When a libcurl connection owner (like the body stream from the LTA) goes out of scope, its destructor asks the pool to move the connection back to the pool. The connection needs to satisfy some requirements before it comes back to the pool, such as:
|
||||
The connection pool is a global and static singleton object. The pool provides an API to request a connection. Based on the set of options requested, the pool will search if there's a connection which is not expired and was created with the same options. If one connection is found, it is moved out of the pool. When a libcurl connection owner (like the body stream from the LTA) goes out of scope, its destructor asks the pool to move the connection back to the pool. The connection needs to satisfy some requirements before it comes back to the pool, such as:
|
||||
|
||||
- The last message from the server is not an error message. A server would typically close a connection when the HTTP status code returned to the client is not within the two hundred codes.
|
||||
- The connection is in a state where there are still bytes from the server response to be read from the socket. A connection should read an entire response before it can send a new request.
|
||||
- When the connection has been inactive and out of the pool for a long time, most likely it’s shut down and it won’t be moved back to the pool.
|
||||
- When the connection has been inactive and out of the pool for a long time, most likely it's shut down and it won't be moved back to the pool.
|
||||
|
||||
The connection pool contains a `mutex` for moving connections in and out of the pool. Multiple threads can request or return a libcurl connection at the same time. The pool uses a Last-in-First-out mechanism to move connections, making it certain to re-use the connections with less time seating in the pool.
|
||||
|
||||
|
@ -156,5 +156,5 @@ The connection pool is responsible for creating and initializing a libcurl handl
|
|||
|
||||
Whenever a libcurl connection is returned to the pool, the Pool Cleaner Agent (PCA) is started (if it is not already running). PCA is a thread which runs every 90 seconds while there are connections seating in the pool. Every time PCA runs, it checks connections, starting from the oldest connection returned to the pool. Since the connection pool works as one stack, the oldest connection is at the bottom. PCA will remove the connections which have expired. As soon as it finds a non-expired connection, PCA switch to inspect another index, until all indexes are reviewed.
|
||||
|
||||
PCA goes to sleep for 90 seconds only if a non-expired connection was found. If all connections were expired and removed, PCA is terminated and won’t be started again until a connection is moved to the pool.
|
||||
PCA goes to sleep for 90 seconds only if a non-expired connection was found. If all connections were expired and removed, PCA is terminated and won't be started again until a connection is moved to the pool.
|
||||
PCA prevents applications from keeping expired connections objects in memory. A common scenario where the importance of the PCA can be observed is if the application needs to create a hundred connections and use them all at the same time. Eventually, all the connections would return to the pool and if the Azure SDK client is not used anymore by the application, there would be a hundred expired connections in heap memory until the application ends.
|
||||
|
|
|
@ -108,7 +108,7 @@ jobs:
|
|||
- template: /eng/pipelines/templates/steps/vcpkg.yml
|
||||
|
||||
# Validate all the files are formatted correctly according to the
|
||||
# .clang-format file. This step runs on linux only only and assumes that
|
||||
# .clang-format file. This step runs on linux only and assumes that
|
||||
# clang-format-11 is installed.
|
||||
- bash: |
|
||||
# Run clang-format recursively on each source and header file within the repo sdk folder.
|
||||
|
@ -132,6 +132,31 @@ jobs:
|
|||
displayName: Validate Clang Format
|
||||
condition: and(succeededOrFailed(), eq(variables['CHECK_CLANG_FORMAT'], 1))
|
||||
|
||||
# Validate all the files are saved as ASCII only without a UTF-8 BOM.
|
||||
- bash: |
|
||||
echo Validate that the files in the repo contain only ASCII characters, saved as UTF-8, without a BOM at the start.
|
||||
|
||||
# Run grep recursive excluding git folder and known expected files and save a file with results.
|
||||
grep -I -P -n "[^\x00-\x7F]" -r --exclude-dir ".git" --exclude-dir ".github" --exclude-dir "vcpkg_installed" --exclude-dir "_deps" --exclude-dir "nlohmann-json-test" --exclude "grepResults" . > grepResults
|
||||
|
||||
# Display results to console.
|
||||
cat grepResults
|
||||
|
||||
# Each result will produce one line, count how many lines were found.
|
||||
files_with_non_ascii=($(wc -l < grepResults))
|
||||
|
||||
# Show info about the total files that needs attention.
|
||||
echo Files found with non-ASCII characters: $files_with_non_ascii
|
||||
|
||||
# Remove the grepResults file.
|
||||
rm grepResults
|
||||
|
||||
# Return the count. When greater than 0, the step will fail.
|
||||
exit $files_with_non_ascii
|
||||
|
||||
displayName: Validate Characters are ASCII
|
||||
condition: and(succeededOrFailed(), eq(variables['CHECK_ASCII_CHARACTERS'], 1))
|
||||
|
||||
- ${{ each artifact in parameters.Artifacts }}:
|
||||
- template: /eng/common/pipelines/templates/steps/set-test-pipeline-version.yml
|
||||
parameters:
|
||||
|
|
|
@ -193,7 +193,8 @@
|
|||
},
|
||||
"BuildSettings": {
|
||||
"clang-11": {
|
||||
"CHECK_CLANG_FORMAT": "1"
|
||||
"CHECK_CLANG_FORMAT": "1",
|
||||
"CHECK_ASCII_CHARACTERS": "1"
|
||||
},
|
||||
"included_release": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
|
|
|
@ -203,7 +203,7 @@ RawContent : HTTP/1.1 200 OK
|
|||
Access-Control-Allow-Credentials: true
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Length: 964
|
||||
Content-Type: application/js…
|
||||
Content-Type: application/json
|
||||
Headers : {[Date, System.String[]], [Server, System.String[]], [Access-Control-Allow-Credentials,
|
||||
System.String[]], [Access-Control-Allow-Origin, System.String[]]...}
|
||||
Images : {}
|
||||
|
@ -530,7 +530,7 @@ RawContent : HTTP/1.1 200 OK
|
|||
Access-Control-Allow-Credentials: true
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Length: 967
|
||||
Content-Type: application/js<EFBFBD>
|
||||
Content-Type: application/json
|
||||
Headers : {[Date, System.String[]], [Server, System.String[]], [Access-Control-Allow-Credentials,
|
||||
System.String[]], [Access-Control-Allow-Origin, System.String[]]...}
|
||||
Images : {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "private/keyvault_settings_common_request.hpp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/identity/client_secret_credential.hpp>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-DebugWithTests",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,495 +1,495 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/certificates/certificate_client.hpp"
|
||||
|
||||
#include "azure/keyvault/shared/keyvault_shared.hpp"
|
||||
#include "private/certificate_constants.hpp"
|
||||
#include "private/certificate_serializers.hpp"
|
||||
#include "private/keyvault_certificates_common_request.hpp"
|
||||
#include "private/package_version.hpp"
|
||||
#include <azure/core/base64.hpp>
|
||||
|
||||
#include <azure/core/credentials/credentials.hpp>
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
#include <azure/core/internal/http/pipeline.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Certificates;
|
||||
using namespace Azure::Security::KeyVault::Certificates::_detail;
|
||||
using namespace Azure;
|
||||
using namespace Azure::Core;
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace Azure::Core::Http::Policies;
|
||||
using namespace Azure::Core::Http::Policies::_internal;
|
||||
using namespace Azure::Core::Http::_internal;
|
||||
using namespace Azure::Security::KeyVault::_detail;
|
||||
|
||||
namespace {
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<RawResponse> CertificateClient::SendRequest(
|
||||
Azure::Core::Http::Request& request,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return KeyVaultCertificatesCommonRequest::SendRequest(*m_pipeline, request, context);
|
||||
}
|
||||
|
||||
Request CertificateClient::CreateRequest(
|
||||
HttpMethod method,
|
||||
std::vector<std::string> const& path,
|
||||
Azure::Core::IO::BodyStream* content) const
|
||||
{
|
||||
return KeyVaultCertificatesCommonRequest::CreateRequest(
|
||||
m_vaultUrl, m_apiVersion, method, path, content);
|
||||
}
|
||||
|
||||
Request CertificateClient::ContinuationTokenRequest(
|
||||
std::vector<std::string> const& path,
|
||||
const Azure::Nullable<std::string>& NextPageToken) const
|
||||
{
|
||||
if (NextPageToken)
|
||||
{
|
||||
// Using a continuation token requires to send the request to the continuation token URL instead
|
||||
// of the default URL which is used only for the first page.
|
||||
Azure::Core::Url nextPageUrl(NextPageToken.Value());
|
||||
return Request(HttpMethod::Get, nextPageUrl);
|
||||
}
|
||||
return CreateRequest(HttpMethod::Get, path);
|
||||
}
|
||||
|
||||
CertificateClient::CertificateClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
CertificateClientOptions options)
|
||||
: m_vaultUrl(vaultUrl), m_apiVersion(options.ApiVersion)
|
||||
{
|
||||
auto apiVersion = options.ApiVersion;
|
||||
|
||||
std::vector<std::unique_ptr<HttpPolicy>> perRetrypolicies;
|
||||
{
|
||||
Azure::Core::Credentials::TokenRequestContext tokenContext;
|
||||
tokenContext.Scopes = {_internal::UrlScope::GetScopeFromUrl(m_vaultUrl)};
|
||||
|
||||
perRetrypolicies.emplace_back(
|
||||
std::make_unique<BearerTokenAuthenticationPolicy>(credential, std::move(tokenContext)));
|
||||
}
|
||||
std::vector<std::unique_ptr<HttpPolicy>> perCallpolicies;
|
||||
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
KeyVaultServicePackageName,
|
||||
PackageVersion::ToString(),
|
||||
std::move(perRetrypolicies),
|
||||
std::move(perCallpolicies));
|
||||
}
|
||||
|
||||
Response<KeyVaultCertificateWithPolicy> CertificateClient::GetCertificate(
|
||||
std::string const& certificateName,
|
||||
Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<KeyVaultCertificate> CertificateClient::GetCertificateVersion(
|
||||
std::string const& certificateName,
|
||||
std::string const& certificateVersion,
|
||||
Context const& context) const
|
||||
{
|
||||
// Request with no payload
|
||||
std::vector<std::string> path{{CertificatesPath, certificateName, certificateVersion}};
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Get, std::move(path));
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
CreateCertificateOperation CertificateClient::StartCreateCertificate(
|
||||
std::string const& certificateName,
|
||||
CertificateCreateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateCreateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post,
|
||||
{CertificatesPath, certificateName, CertificatesCreatePath},
|
||||
&payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
|
||||
return CreateCertificateOperation(value.Name, std::make_shared<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
Response<DeletedCertificate> CertificateClient::GetDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {DeletedCertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<DeletedCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::GetIssuer(
|
||||
std::string const& issuerName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, IssuersPath, issuerName});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::DeleteIssuer(
|
||||
std::string const& issuerName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, IssuersPath, issuerName});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::CreateIssuer(
|
||||
std::string const& issuerName,
|
||||
CertificateIssuer const& certificateIssuer,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateIssuerSerializer::Serialize(certificateIssuer);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Put, {CertificatesPath, IssuersPath, issuerName}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::UpdateIssuer(
|
||||
std::string const& issuerName,
|
||||
CertificateIssuer const& certificateIssuer,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateIssuerSerializer::Serialize(certificateIssuer);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, IssuersPath, issuerName}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::GetContacts(
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, ContactsPath});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::DeleteContacts(
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, ContactsPath});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::SetContacts(
|
||||
std::vector<CertificateContact> const& contacts,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateContactsSerializer::Serialize(contacts);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Put, {CertificatesPath, ContactsPath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties> CertificateClient::GetPendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName, PendingPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties>
|
||||
CertificateClient::CancelPendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
CertificateOperationUpdateOptions option;
|
||||
option.CancelationRequested = true;
|
||||
auto payload = CertificateOperationUpdateOptionSerializer::Serialize(option);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, PendingPath}, &payloadStream);
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties>
|
||||
CertificateClient::DeletePendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Delete, {CertificatesPath, certificateName, PendingPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<PurgedCertificate> CertificateClient::PurgeDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {DeletedCertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
PurgedCertificate value;
|
||||
return Azure::Response<PurgedCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
DeleteCertificateOperation CertificateClient::StartDeleteCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, certificateName});
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificate();
|
||||
value.Properties.Name = certificateName;
|
||||
auto responseT = Azure::Response<DeletedCertificate>(std::move(value), std::move(rawResponse));
|
||||
return DeleteCertificateOperation(
|
||||
std::make_shared<CertificateClient>(*this), std::move(responseT));
|
||||
}
|
||||
|
||||
RecoverDeletedCertificateOperation CertificateClient::StartRecoverDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Post, {DeletedCertificatesPath, certificateName, RecoverPath});
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateWithPolicy();
|
||||
value.Properties.Name = certificateName;
|
||||
auto responseT
|
||||
= Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
return RecoverDeletedCertificateOperation(
|
||||
std::make_shared<CertificateClient>(*this), std::move(responseT));
|
||||
}
|
||||
Azure::Response<CertificatePolicy> CertificateClient::GetCertificatePolicy(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName, PolicyPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificatePolicySerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificatePolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificatePolicy> CertificateClient::UpdateCertificatePolicy(
|
||||
std::string const& certificateName,
|
||||
CertificatePolicy const& certificatePolicy,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificatePolicySerializer::Serialize(certificatePolicy);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, PolicyPath}, &payloadStream);
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificatePolicySerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificatePolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<BackupCertificateResult> CertificateClient::BackupCertificate(
|
||||
std::string certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Post, {CertificatesPath, certificateName, BackupPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = BackupCertificateSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<BackupCertificateResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::RestoreCertificateBackup(
|
||||
std::vector<uint8_t> const& certificateBackup,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = BackupCertificateSerializer::Serialize(certificateBackup);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Post, {CertificatesPath, RestorePath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize("", *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
CertificatePropertiesPagedResponse CertificateClient::GetPropertiesOfCertificates(
|
||||
GetPropertiesOfCertificatesOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
(void)options;
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({CertificatesPath}, options.NextPageToken);
|
||||
if (options.IncludePending)
|
||||
{
|
||||
request.GetUrl().AppendQueryParameter(
|
||||
IncludePendingQuery, options.IncludePending.Value() ? TrueQueryValue : FalseQueryValue);
|
||||
}
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificatePropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return CertificatePropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
CertificatePropertiesPagedResponse CertificateClient::GetPropertiesOfCertificateVersions(
|
||||
std::string const& certificateName,
|
||||
GetPropertiesOfCertificateVersionsOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest(
|
||||
{CertificatesPath, certificateName, VersionsPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificatePropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return CertificatePropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
IssuerPropertiesPagedResponse CertificateClient::GetPropertiesOfIssuers(
|
||||
GetPropertiesOfIssuersOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({CertificatesPath, IssuersPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = IssuerPropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return IssuerPropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
DeletedCertificatesPagedResponse CertificateClient::GetDeletedCertificates(
|
||||
GetDeletedCertificatesOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({DeletedCertificatesPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificatesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return DeletedCertificatesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::ImportCertificate(
|
||||
std::string const& certificateName,
|
||||
ImportCertificateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = ImportCertificateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post, {CertificatesPath, certificateName, ImportPath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::MergeCertificate(
|
||||
std::string const& certificateName,
|
||||
MergeCertificateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = MergeCertificateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post,
|
||||
{CertificatesPath, certificateName, PendingPath, MergePath},
|
||||
&payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificate> CertificateClient::UpdateCertificateProperties(
|
||||
std::string const& certificateName,
|
||||
std::string const& certificateVersion,
|
||||
CertificateProperties const& certificateProperties,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateUpdateOptionsSerializer::Serialize(certificateProperties);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, certificateVersion}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/certificates/certificate_client.hpp"
|
||||
|
||||
#include "azure/keyvault/shared/keyvault_shared.hpp"
|
||||
#include "private/certificate_constants.hpp"
|
||||
#include "private/certificate_serializers.hpp"
|
||||
#include "private/keyvault_certificates_common_request.hpp"
|
||||
#include "private/package_version.hpp"
|
||||
#include <azure/core/base64.hpp>
|
||||
|
||||
#include <azure/core/credentials/credentials.hpp>
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
#include <azure/core/internal/http/pipeline.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Certificates;
|
||||
using namespace Azure::Security::KeyVault::Certificates::_detail;
|
||||
using namespace Azure;
|
||||
using namespace Azure::Core;
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace Azure::Core::Http::Policies;
|
||||
using namespace Azure::Core::Http::Policies::_internal;
|
||||
using namespace Azure::Core::Http::_internal;
|
||||
using namespace Azure::Security::KeyVault::_detail;
|
||||
|
||||
namespace {
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<RawResponse> CertificateClient::SendRequest(
|
||||
Azure::Core::Http::Request& request,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return KeyVaultCertificatesCommonRequest::SendRequest(*m_pipeline, request, context);
|
||||
}
|
||||
|
||||
Request CertificateClient::CreateRequest(
|
||||
HttpMethod method,
|
||||
std::vector<std::string> const& path,
|
||||
Azure::Core::IO::BodyStream* content) const
|
||||
{
|
||||
return KeyVaultCertificatesCommonRequest::CreateRequest(
|
||||
m_vaultUrl, m_apiVersion, method, path, content);
|
||||
}
|
||||
|
||||
Request CertificateClient::ContinuationTokenRequest(
|
||||
std::vector<std::string> const& path,
|
||||
const Azure::Nullable<std::string>& NextPageToken) const
|
||||
{
|
||||
if (NextPageToken)
|
||||
{
|
||||
// Using a continuation token requires to send the request to the continuation token URL instead
|
||||
// of the default URL which is used only for the first page.
|
||||
Azure::Core::Url nextPageUrl(NextPageToken.Value());
|
||||
return Request(HttpMethod::Get, nextPageUrl);
|
||||
}
|
||||
return CreateRequest(HttpMethod::Get, path);
|
||||
}
|
||||
|
||||
CertificateClient::CertificateClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
CertificateClientOptions options)
|
||||
: m_vaultUrl(vaultUrl), m_apiVersion(options.ApiVersion)
|
||||
{
|
||||
auto apiVersion = options.ApiVersion;
|
||||
|
||||
std::vector<std::unique_ptr<HttpPolicy>> perRetrypolicies;
|
||||
{
|
||||
Azure::Core::Credentials::TokenRequestContext tokenContext;
|
||||
tokenContext.Scopes = {_internal::UrlScope::GetScopeFromUrl(m_vaultUrl)};
|
||||
|
||||
perRetrypolicies.emplace_back(
|
||||
std::make_unique<BearerTokenAuthenticationPolicy>(credential, std::move(tokenContext)));
|
||||
}
|
||||
std::vector<std::unique_ptr<HttpPolicy>> perCallpolicies;
|
||||
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
KeyVaultServicePackageName,
|
||||
PackageVersion::ToString(),
|
||||
std::move(perRetrypolicies),
|
||||
std::move(perCallpolicies));
|
||||
}
|
||||
|
||||
Response<KeyVaultCertificateWithPolicy> CertificateClient::GetCertificate(
|
||||
std::string const& certificateName,
|
||||
Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<KeyVaultCertificate> CertificateClient::GetCertificateVersion(
|
||||
std::string const& certificateName,
|
||||
std::string const& certificateVersion,
|
||||
Context const& context) const
|
||||
{
|
||||
// Request with no payload
|
||||
std::vector<std::string> path{{CertificatesPath, certificateName, certificateVersion}};
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Get, std::move(path));
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
CreateCertificateOperation CertificateClient::StartCreateCertificate(
|
||||
std::string const& certificateName,
|
||||
CertificateCreateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateCreateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post,
|
||||
{CertificatesPath, certificateName, CertificatesCreatePath},
|
||||
&payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = _detail::CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
|
||||
return CreateCertificateOperation(value.Name, std::make_shared<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
Response<DeletedCertificate> CertificateClient::GetDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {DeletedCertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<DeletedCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::GetIssuer(
|
||||
std::string const& issuerName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, IssuersPath, issuerName});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::DeleteIssuer(
|
||||
std::string const& issuerName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, IssuersPath, issuerName});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::CreateIssuer(
|
||||
std::string const& issuerName,
|
||||
CertificateIssuer const& certificateIssuer,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateIssuerSerializer::Serialize(certificateIssuer);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Put, {CertificatesPath, IssuersPath, issuerName}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateIssuer> CertificateClient::UpdateIssuer(
|
||||
std::string const& issuerName,
|
||||
CertificateIssuer const& certificateIssuer,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateIssuerSerializer::Serialize(certificateIssuer);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, IssuersPath, issuerName}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateIssuerSerializer::Deserialize(issuerName, *rawResponse);
|
||||
return Azure::Response<CertificateIssuer>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::GetContacts(
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, ContactsPath});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::DeleteContacts(
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, ContactsPath});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<CertificateContactsResult> CertificateClient::SetContacts(
|
||||
std::vector<CertificateContact> const& contacts,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateContactsSerializer::Serialize(contacts);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Put, {CertificatesPath, ContactsPath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificateContactsSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateContactsResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties> CertificateClient::GetPendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName, PendingPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties>
|
||||
CertificateClient::CancelPendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
CertificateOperationUpdateOptions option;
|
||||
option.CancelationRequested = true;
|
||||
auto payload = CertificateOperationUpdateOptionSerializer::Serialize(option);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, PendingPath}, &payloadStream);
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificateOperationProperties>
|
||||
CertificateClient::DeletePendingCertificateOperation(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Delete, {CertificatesPath, certificateName, PendingPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificateOperationSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificateOperationProperties>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Response<PurgedCertificate> CertificateClient::PurgeDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {DeletedCertificatesPath, certificateName});
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
PurgedCertificate value;
|
||||
return Azure::Response<PurgedCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
DeleteCertificateOperation CertificateClient::StartDeleteCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Delete, {CertificatesPath, certificateName});
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificate();
|
||||
value.Properties.Name = certificateName;
|
||||
auto responseT = Azure::Response<DeletedCertificate>(std::move(value), std::move(rawResponse));
|
||||
return DeleteCertificateOperation(
|
||||
std::make_shared<CertificateClient>(*this), std::move(responseT));
|
||||
}
|
||||
|
||||
RecoverDeletedCertificateOperation CertificateClient::StartRecoverDeletedCertificate(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request
|
||||
= CreateRequest(HttpMethod::Post, {DeletedCertificatesPath, certificateName, RecoverPath});
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateWithPolicy();
|
||||
value.Properties.Name = certificateName;
|
||||
auto responseT
|
||||
= Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
return RecoverDeletedCertificateOperation(
|
||||
std::make_shared<CertificateClient>(*this), std::move(responseT));
|
||||
}
|
||||
Azure::Response<CertificatePolicy> CertificateClient::GetCertificatePolicy(
|
||||
std::string const& certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Get, {CertificatesPath, certificateName, PolicyPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificatePolicySerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificatePolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<CertificatePolicy> CertificateClient::UpdateCertificatePolicy(
|
||||
std::string const& certificateName,
|
||||
CertificatePolicy const& certificatePolicy,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificatePolicySerializer::Serialize(certificatePolicy);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, PolicyPath}, &payloadStream);
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = CertificatePolicySerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<CertificatePolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<BackupCertificateResult> CertificateClient::BackupCertificate(
|
||||
std::string certificateName,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto request = CreateRequest(HttpMethod::Post, {CertificatesPath, certificateName, BackupPath});
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
|
||||
auto value = BackupCertificateSerializer::Deserialize(*rawResponse);
|
||||
return Azure::Response<BackupCertificateResult>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::RestoreCertificateBackup(
|
||||
std::vector<uint8_t> const& certificateBackup,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = BackupCertificateSerializer::Serialize(certificateBackup);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(HttpMethod::Post, {CertificatesPath, RestorePath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize("", *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
CertificatePropertiesPagedResponse CertificateClient::GetPropertiesOfCertificates(
|
||||
GetPropertiesOfCertificatesOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
(void)options;
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({CertificatesPath}, options.NextPageToken);
|
||||
if (options.IncludePending)
|
||||
{
|
||||
request.GetUrl().AppendQueryParameter(
|
||||
IncludePendingQuery, options.IncludePending.Value() ? TrueQueryValue : FalseQueryValue);
|
||||
}
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificatePropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return CertificatePropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
CertificatePropertiesPagedResponse CertificateClient::GetPropertiesOfCertificateVersions(
|
||||
std::string const& certificateName,
|
||||
GetPropertiesOfCertificateVersionsOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest(
|
||||
{CertificatesPath, certificateName, VersionsPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = CertificatePropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return CertificatePropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
IssuerPropertiesPagedResponse CertificateClient::GetPropertiesOfIssuers(
|
||||
GetPropertiesOfIssuersOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({CertificatesPath, IssuersPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = IssuerPropertiesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return IssuerPropertiesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
DeletedCertificatesPagedResponse CertificateClient::GetDeletedCertificates(
|
||||
GetDeletedCertificatesOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Request and settings
|
||||
auto request = ContinuationTokenRequest({DeletedCertificatesPath}, options.NextPageToken);
|
||||
|
||||
// Send and parse respone
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = DeletedCertificatesPagedResponseSerializer::Deserialize(*rawResponse);
|
||||
return DeletedCertificatesPagedResponse(
|
||||
std::move(value), std::move(rawResponse), std::make_unique<CertificateClient>(*this));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::ImportCertificate(
|
||||
std::string const& certificateName,
|
||||
ImportCertificateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = ImportCertificateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post, {CertificatesPath, certificateName, ImportPath}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificateWithPolicy> CertificateClient::MergeCertificate(
|
||||
std::string const& certificateName,
|
||||
MergeCertificateOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = MergeCertificateOptionsSerializer::Serialize(options);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Post,
|
||||
{CertificatesPath, certificateName, PendingPath, MergePath},
|
||||
&payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificateWithPolicy>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultCertificate> CertificateClient::UpdateCertificateProperties(
|
||||
std::string const& certificateName,
|
||||
std::string const& certificateVersion,
|
||||
CertificateProperties const& certificateProperties,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto payload = CertificateUpdateOptionsSerializer::Serialize(certificateProperties);
|
||||
Azure::Core::IO::MemoryBodyStream payloadStream(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
|
||||
|
||||
auto request = CreateRequest(
|
||||
HttpMethod::Patch, {CertificatesPath, certificateName, certificateVersion}, &payloadStream);
|
||||
|
||||
auto rawResponse = SendRequest(request, context);
|
||||
auto value = KeyVaultCertificateSerializer::Deserialize(certificateName, *rawResponse);
|
||||
return Azure::Response<KeyVaultCertificate>(std::move(value), std::move(rawResponse));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "azure/keyvault/certificates/certificate_client_operations.hpp"
|
||||
#include "azure/keyvault/certificates/certificate_client.hpp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/core/base64.hpp>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "private/keyvault_certificates_common_request.hpp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/identity/client_secret_credential.hpp>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "private/keyvault_secrets_common_request.hpp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "datalake_path_client_test.hpp"
|
||||
|
|
Загрузка…
Ссылка в новой задаче