diff --git a/.gitignore b/.gitignore index 6fd64ac1a..951444f07 100644 --- a/.gitignore +++ b/.gitignore @@ -348,8 +348,11 @@ build/ [Dd]ocs/ # vscode -.vscode/ +.vscode/* +!.vscode/cspell.json .factorypath # Default Assets restore directory .assets + +CMakeUserPresets.json diff --git a/.vscode/cspell.json b/.vscode/cspell.json index b70213902..fdb027c1f 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -82,6 +82,7 @@ "gtest", "Gzrs", "HKEY", + "HLOCAL", "HRESULT", "IMDS", "immutability", @@ -244,6 +245,12 @@ "Sylvain" ] }, + { + "filename": "**/sdk/identity/azure-identity/**", + "words": [ + "PCCERT" + ] + }, { "filename": "**/sdk/storage/azure-storage-common/CHANGELOG.md", "words": [ diff --git a/sdk/identity/azure-identity/CHANGELOG.md b/sdk/identity/azure-identity/CHANGELOG.md index d8b458566..2cae37104 100644 --- a/sdk/identity/azure-identity/CHANGELOG.md +++ b/sdk/identity/azure-identity/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- [[#4084]](https://github.com/Azure/azure-sdk-for-cpp/issues/4084) Remove OpenSSL dependency on Windows. + ### Other Changes ## 1.6.0-beta.1 (2023-08-11) diff --git a/sdk/identity/azure-identity/CMakeLists.txt b/sdk/identity/azure-identity/CMakeLists.txt index 755320f42..bbf9ee69d 100644 --- a/sdk/identity/azure-identity/CMakeLists.txt +++ b/sdk/identity/azure-identity/CMakeLists.txt @@ -101,8 +101,13 @@ target_include_directories( target_link_libraries(azure-identity PUBLIC Azure::azure-core) -find_package(OpenSSL REQUIRED) -target_link_libraries(azure-identity PRIVATE OpenSSL::Crypto) +if(WIN32) + find_package(wil CONFIG REQUIRED) + target_link_libraries(azure-identity PRIVATE WIL::WIL bcrypt crypt32) +else() + find_package(OpenSSL REQUIRED) + target_link_libraries(azure-identity PRIVATE OpenSSL::Crypto) +endif() get_az_version("${CMAKE_CURRENT_SOURCE_DIR}/src/private/package_version.hpp") generate_documentation(azure-identity ${AZ_LIBRARY_VERSION}) diff --git a/sdk/identity/azure-identity/inc/azure/identity/client_certificate_credential.hpp b/sdk/identity/azure-identity/inc/azure/identity/client_certificate_credential.hpp index dea42e98a..320434a9d 100644 --- a/sdk/identity/azure-identity/inc/azure/identity/client_certificate_credential.hpp +++ b/sdk/identity/azure-identity/inc/azure/identity/client_certificate_credential.hpp @@ -24,16 +24,16 @@ namespace Azure { namespace Identity { namespace _detail { class TokenCredentialImpl; - void FreePkeyImpl(void* pkey); + void FreePrivateKeyImpl(void* pkey); - template struct UniquePkeyHelper; - template <> struct UniquePkeyHelper + template struct UniquePrivateKeyHelper; + template <> struct UniquePrivateKeyHelper { - static void FreePkey(void* pkey) { FreePkeyImpl(pkey); } - using type = Azure::Core::_internal::BasicUniqueHandle; + static void FreePrivateKey(void* pkey) { FreePrivateKeyImpl(pkey); } + using type = Azure::Core::_internal::BasicUniqueHandle; }; - using UniquePkeyHandle = Azure::Core::_internal::UniqueHandle; + using UniquePrivateKey = Azure::Core::_internal::UniqueHandle; } // namespace _detail /** @@ -73,7 +73,7 @@ namespace Azure { namespace Identity { std::string m_requestBody; std::string m_tokenPayloadStaticPart; std::string m_tokenHeaderEncoded; - _detail::UniquePkeyHandle m_pkey; + _detail::UniquePrivateKey m_pkey; explicit ClientCertificateCredential( std::string tenantId, diff --git a/sdk/identity/azure-identity/src/client_certificate_credential.cpp b/sdk/identity/azure-identity/src/client_certificate_credential.cpp index ea5cb5303..ef5eee716 100644 --- a/sdk/identity/azure-identity/src/client_certificate_credential.cpp +++ b/sdk/identity/azure-identity/src/client_certificate_credential.cpp @@ -8,6 +8,9 @@ #include #include +#include +#include +#include #include #include @@ -15,12 +18,19 @@ #include #include +#if defined(AZ_PLATFORM_WINDOWS) +#include + +#include +#include +#else #include #include #include #include #include #include +#endif using Azure::Identity::ClientCertificateCredential; @@ -34,6 +44,7 @@ using Azure::Core::Credentials::AuthenticationException; using Azure::Core::Credentials::TokenCredentialOptions; using Azure::Core::Credentials::TokenRequestContext; using Azure::Core::Http::HttpMethod; +using Azure::Core::IO::FileBodyStream; using Azure::Identity::_detail::TenantIdResolver; using Azure::Identity::_detail::TokenCredentialImpl; @@ -50,6 +61,204 @@ template std::vector ToUInt8Vector(T const& in) return outVec; } +using CertificateThumbprint = std::vector; +using UniquePrivateKey = Azure::Identity::_detail::UniquePrivateKey; +using PrivateKey = decltype(std::declval().get()); + +#if defined(AZ_PLATFORM_WINDOWS) +enum PrivateKeyType +{ + Rsa, + Ecdsa, + Pkcs +}; + +std::vector PemToBinary(LPCSTR str, DWORD count) +{ + DWORD size = 0; + THROW_IF_WIN32_BOOL_FALSE(CryptStringToBinaryA( + str, count, CRYPT_STRING_BASE64HEADER, nullptr, &size, nullptr, nullptr)); + std::vector buffer(size); + THROW_IF_WIN32_BOOL_FALSE(CryptStringToBinaryA( + str, count, CRYPT_STRING_BASE64HEADER, buffer.data(), &size, nullptr, nullptr)); + return buffer; +} + +CertificateThumbprint GetThumbprint(PCCERT_CONTEXT cert) +{ + DWORD size = 0; + THROW_IF_WIN32_BOOL_FALSE( + CertGetCertificateContextProperty(cert, CERT_SHA1_HASH_PROP_ID, nullptr, &size)); + std::vector thumbprint(size); + THROW_IF_WIN32_BOOL_FALSE( + CertGetCertificateContextProperty(cert, CERT_SHA1_HASH_PROP_ID, thumbprint.data(), &size)); + return thumbprint; +} + +wil::unique_cert_context ImportPemCertificate(std::string const& pem) +{ + auto headerStart = pem.find("-----BEGIN CERTIFICATE-----"); + if (headerStart == std::string::npos) + { + throw AuthenticationException("PEM file does not contain certificate."); + } + auto certBuffer + = PemToBinary(pem.c_str() + headerStart, static_cast(pem.size() - headerStart)); + auto cert = CertCreateCertificateContext( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + certBuffer.data(), + static_cast(certBuffer.size())); + THROW_LAST_ERROR_IF_NULL(cert); + return wil::unique_cert_context{cert}; +} + +size_t FindPemPrivateKeyHeader(std::string const& pem, PrivateKeyType& keyType) +{ + auto headerStart = pem.find("-----BEGIN RSA PRIVATE KEY-----"); + if (headerStart != std::string::npos) + { + keyType = PrivateKeyType::Rsa; + return headerStart; + } + headerStart = pem.find("-----BEGIN EC PRIVATE KEY-----"); + if (headerStart != std::string::npos) + { + keyType = PrivateKeyType::Ecdsa; + return headerStart; + } + keyType = PrivateKeyType::Pkcs; + return pem.find("-----BEGIN PRIVATE KEY-----"); +} + +wil::unique_bcrypt_algorithm OpenAlgorithm(LPCWSTR algId) +{ + wil::unique_bcrypt_algorithm alg; + THROW_IF_NTSTATUS_FAILED(BCryptOpenAlgorithmProvider(wil::out_param(alg), algId, nullptr, 0)); + return alg; +} + +UniquePrivateKey ImportRsaPrivateKey(const BYTE* data, DWORD size) +{ + DWORD keySize = 0; + wil::unique_hlocal_ptr rsaKeyBlob; + THROW_IF_WIN32_BOOL_FALSE(CryptDecodeObjectEx( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + CNG_RSA_PRIVATE_KEY_BLOB, + data, + size, + CRYPT_DECODE_ALLOC_FLAG, + nullptr, + wil::out_param(rsaKeyBlob), + &keySize)); + BCRYPT_KEY_HANDLE key; + auto alg = OpenAlgorithm(BCRYPT_RSA_ALGORITHM); + THROW_IF_NTSTATUS_FAILED(BCryptImportKeyPair( + alg.get(), + nullptr, + BCRYPT_RSAPRIVATE_BLOB, + &key, + reinterpret_cast(rsaKeyBlob.get()), + keySize, + 0)); + return UniquePrivateKey{key}; +} + +UniquePrivateKey ImportEccPrivateKey(const BYTE*, DWORD) +{ + throw AuthenticationException("ECDSA private keys are not supported."); +} + +UniquePrivateKey ImportPemPrivateKey(std::string const& pem) +{ + PrivateKeyType keyType{}; + auto headerStart = FindPemPrivateKeyHeader(pem, keyType); + if (headerStart == std::string::npos) + { + throw AuthenticationException("PEM file does not contain private key."); + } + auto keyBuffer{ + PemToBinary(pem.c_str() + headerStart, static_cast(pem.size() - headerStart))}; + + if (keyType == PrivateKeyType::Rsa) + { + return ImportRsaPrivateKey(keyBuffer.data(), static_cast(keyBuffer.size())); + } + + if (keyType == PrivateKeyType::Ecdsa) + { + return ImportEccPrivateKey(keyBuffer.data(), static_cast(keyBuffer.size())); + } + + wil::unique_hlocal_ptr privateKeyInfo; + DWORD keySize = 0; + THROW_IF_WIN32_BOOL_FALSE(CryptDecodeObjectEx( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + PKCS_PRIVATE_KEY_INFO, + keyBuffer.data(), + static_cast(keyBuffer.size()), + CRYPT_DECODE_ALLOC_FLAG, + nullptr, + wil::out_param(privateKeyInfo), + &keySize)); + if (strcmp(privateKeyInfo->Algorithm.pszObjId, szOID_RSA_RSA) == 0) + { + return ImportRsaPrivateKey( + privateKeyInfo->PrivateKey.pbData, privateKeyInfo->PrivateKey.cbData); + } + if (strcmp(privateKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY) == 0) + { + return ImportEccPrivateKey( + privateKeyInfo->PrivateKey.pbData, privateKeyInfo->PrivateKey.cbData); + } + throw AuthenticationException("Invalid private key."); +} + +std::tuple ReadPemCertificate(std::string const& path) +{ + auto pemContent{FileBodyStream(path).ReadToEnd()}; + std::string pem{pemContent.begin(), pemContent.end()}; + pemContent = {}; + + auto certContext = ImportPemCertificate(pem); + return std::make_tuple(GetThumbprint(certContext.get()), ImportPemPrivateKey(pem)); +} + +std::vector SignPkcs1Sha256(PrivateKey key, const uint8_t* data, size_t size) +{ + auto hash = Azure::Core::Cryptography::_internal::Sha256Hash().Final(data, size); + BCRYPT_PKCS1_PADDING_INFO paddingInfo; + paddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; + DWORD signatureSize = 0; + auto status = BCryptSignHash( + key, + &paddingInfo, + hash.data(), + static_cast(hash.size()), + nullptr, + 0, + &signatureSize, + BCRYPT_PAD_PKCS1); + if (status != ERROR_SUCCESS) + { + return {}; + } + std::vector signature(signatureSize); + status = BCryptSignHash( + key, + &paddingInfo, + hash.data(), + static_cast(hash.size()), + signature.data(), + static_cast(signature.size()), + &signatureSize, + BCRYPT_PAD_PKCS1); + if (status != ERROR_SUCCESS) + { + return {}; + } + return signature; +} +#else template struct UniqueHandleHelper; template <> struct UniqueHandleHelper @@ -69,11 +278,87 @@ template <> struct UniqueHandleHelper template using UniqueHandle = Azure::Core::_internal::UniqueHandle; + +std::tuple ReadPemCertificate(const std::string& path) +{ + // Open certificate file, then get private key and X509: + UniqueHandle bio(BIO_new_file(path.c_str(), "r")); + if (!bio) + { + throw AuthenticationException("Failed to open certificate file."); + } + + UniquePrivateKey pkey{PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)}; + if (!pkey) + { + throw AuthenticationException("Failed to read certificate private key."); + } + + UniqueHandle x509{PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)}; + if (!x509) + { + std::ignore = BIO_seek(bio.get(), 0); + x509.reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); + if (!x509) + { + throw AuthenticationException("Failed to read X509 section."); + } + } + + CertificateThumbprint thumbprint(EVP_MAX_MD_SIZE); + // Get certificate thumbprint: + unsigned int mdLen = 0; + const auto digestResult = X509_digest(x509.get(), EVP_sha1(), thumbprint.data(), &mdLen); + + if (!digestResult) + { + throw AuthenticationException("Failed to get certificate thumbprint."); + } + + // Drop unused buffer space: + const auto mdLenSz = static_cast(mdLen); + if (thumbprint.size() > mdLenSz) + { + thumbprint.resize(mdLenSz); + } + + return std::make_tuple(thumbprint, std::move(pkey)); +} + +std::vector SignPkcs1Sha256(PrivateKey key, const uint8_t* data, size_t size) +{ + UniqueHandle mdCtx(EVP_MD_CTX_new()); + if (!mdCtx) + { + return {}; + } + EVP_PKEY_CTX* signCtx = nullptr; + if ((EVP_DigestSignInit(mdCtx.get(), &signCtx, EVP_sha256(), nullptr, static_cast(key)) + == 1) + && (EVP_PKEY_CTX_set_rsa_padding(signCtx, RSA_PKCS1_PADDING) == 1)) + { + size_t sigLen = 0; + if (EVP_DigestSign(mdCtx.get(), nullptr, &sigLen, nullptr, 0) == 1) + { + std::vector sigVec(sigLen); + if (EVP_DigestSign(mdCtx.get(), sigVec.data(), &sigLen, data, size) == 1) + { + return sigVec; + } + } + } + return {}; +} +#endif } // namespace -void Azure::Identity::_detail::FreePkeyImpl(void* pkey) +void Azure::Identity::_detail::FreePrivateKeyImpl(void* pkey) { +#if defined(AZ_PLATFORM_WINDOWS) + BCryptDestroyKey(static_cast(pkey)); +#else EVP_PKEY_free(static_cast(pkey)); +#endif } ClientCertificateCredential::ClientCertificateCredential( @@ -100,50 +385,19 @@ ClientCertificateCredential::ClientCertificateCredential( std::string thumbprintBase64Str; { - std::vector mdVec(EVP_MAX_MD_SIZE); + CertificateThumbprint mdVec; + try { - UniqueHandle x509; - { - // Open certificate file, then get private key and X509: - UniqueHandle bio(BIO_new_file(clientCertificatePath.c_str(), "r")); - if (!bio) - { - throw AuthenticationException("Failed to open certificate file."); - } - - m_pkey.reset(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); - if (!m_pkey) - { - throw AuthenticationException("Failed to read certificate private key."); - } - - x509.reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); - if (!x509) - { - static_cast(BIO_seek(bio.get(), 0)); - x509.reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); - if (!x509) - { - throw AuthenticationException("Failed to read X509 section."); - } - } - } - - // Get certificate thumbprint: - unsigned int mdLen = 0; - const auto digestResult = X509_digest(x509.get(), EVP_sha1(), mdVec.data(), &mdLen); - - if (!digestResult) - { - throw AuthenticationException("Failed to get certificate thumbprint."); - } - - // Drop unused buffer space: - const auto mdLenSz = static_cast(mdLen); - if (mdVec.size() > mdLenSz) - { - mdVec.resize(mdLenSz); - } + std::tie(mdVec, m_pkey) = ReadPemCertificate(clientCertificatePath); + } + catch (AuthenticationException&) + { + throw; + } + catch (std::exception& e) + { + // WIL does not throw AuthenticationException. + throw AuthenticationException(e.what()); } // Get thumbprint as hex string: @@ -256,41 +510,14 @@ AccessToken ClientCertificateCredential::GetToken( } // Get assertion signature. - std::string signature; - { - UniqueHandle mdCtx(EVP_MD_CTX_new()); - if (mdCtx) - { - EVP_PKEY_CTX* signCtx = nullptr; - if ((EVP_DigestSignInit( - mdCtx.get(), - &signCtx, - EVP_sha256(), - nullptr, - static_cast(m_pkey.get())) - == 1) - && (EVP_PKEY_CTX_set_rsa_padding(signCtx, RSA_PKCS1_PADDING) == 1)) - { - size_t sigLen = 0; - if (EVP_DigestSign(mdCtx.get(), nullptr, &sigLen, nullptr, 0) == 1) - { - const auto bufToSign = reinterpret_cast(assertion.data()); - const auto bufToSignLen = static_cast(assertion.size()); - - std::vector sigVec(sigLen); - if (EVP_DigestSign(mdCtx.get(), sigVec.data(), &sigLen, bufToSign, bufToSignLen) - == 1) - { - signature = Base64Url::Base64UrlEncode(ToUInt8Vector(sigVec)); - } - } - } - } - } + std::string signature = Base64Url::Base64UrlEncode(SignPkcs1Sha256( + m_pkey.get(), + reinterpret_cast(assertion.data()), + static_cast(assertion.size()))); if (signature.empty()) { - throw Azure::Core::Credentials::AuthenticationException("Failed to sign token request."); + throw AuthenticationException("Failed to sign token request."); } // Add signature to the end of assertion diff --git a/sdk/identity/azure-identity/test/ut/client_certificate_credential_test.cpp b/sdk/identity/azure-identity/test/ut/client_certificate_credential_test.cpp index dffc1c1dc..9a2d1b942 100644 --- a/sdk/identity/azure-identity/test/ut/client_certificate_credential_test.cpp +++ b/sdk/identity/azure-identity/test/ut/client_certificate_credential_test.cpp @@ -17,11 +17,24 @@ using Azure::Identity::ClientCertificateCredentialOptions; using Azure::Identity::Test::_detail::CredentialTestHelper; namespace { +enum CertFormat +{ + RsaPkcs, + RsaRaw +}; + +enum TestType +{ + Regular, + AzureStack, + Authority +}; + struct TempCertFile final { static const char* const Path; ~TempCertFile(); - TempCertFile(); + TempCertFile(CertFormat algorithm = RsaPkcs); }; std::vector SplitString(const std::string& s, char separator); @@ -29,9 +42,104 @@ std::vector SplitString(const std::string& s, char separator); std::string ToString(std::vector const& vec); } // namespace -TEST(ClientCertificateCredential, GetCredentialName) +class GetCredentialName : public ::testing::TestWithParam { + TempCertFile m_certFile{GetParam()}; +}; + +class GetToken : public ::testing::TestWithParam> { +public: + TestType GetTestType() { return std::get<0>(GetParam()); } + + CertFormat GetCertFormat() { return std::get<1>(GetParam()); } + + std::string GetTenantId() + { + return GetTestType() == TestType::AzureStack ? "adfs" : "01234567-89ab-cdef-fedc-ba8976543210"; + } + + std::string GetRequestUri() + { + switch (GetTestType()) + { + case TestType::Regular: + return "https://login.microsoftonline.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/" + "token"; + case TestType::AzureStack: + return "https://login.microsoftonline.com/adfs/oauth2/token"; + case TestType::Authority: + return "https://microsoft.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/token"; + } + AZURE_UNREACHABLE_CODE(); + } + + std::string GetBodyStart0() + { + switch (GetTestType()) + { + case TestType::Regular: + case TestType::Authority: // cspell:disable + return "grant_type=client_credentials" + "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-" + "bearer" + "&client_id=fedcba98-7654-3210-0123-456789abcdef" + "&scope=https%3A%2F%2Fazure.com%2F.default" + "&client_assertion="; // cspell:enable + case TestType::AzureStack: // cspell:disable + return "grant_type=client_credentials" + "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-" + "bearer" + "&client_id=fedcba98-7654-3210-0123-456789abcdef" + "&scope=https%3A%2F%2Fazure.com" + "&client_assertion="; // cspell:enable + } + AZURE_UNREACHABLE_CODE(); + } + + std::string GetBodyStart1() + { + // cspell:disable + return "grant_type=client_credentials" + "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" + "&client_id=fedcba98-7654-3210-0123-456789abcdef" + "&client_assertion="; // cspell:enable + } + + std::string GetHeader() + { // cspell:disable + return "{\"x5t\":\"V0pIIQwSzNn6vfSTPv-1f7Vt_Pw\",\"kid\":" + "\"574A48210C12CCD9FABDF4933EFFB57FB56DFCFC\",\"alg\":\"RS256\",\"typ\":\"JWT\"}"; + } + + std::string GetPayloadStart() + { + switch (GetTestType()) + { + case TestType::Regular: + return "{\"aud\":\"https://login.microsoftonline.com/01234567-89ab-cdef-fedc-ba8976543210/" + "oauth2/v2.0/token\"," + "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," + "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; + case TestType::AzureStack: + return "{\"aud\":\"https://login.microsoftonline.com/adfs/oauth2/token\"," + "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," + "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; + case TestType::Authority: + return "{\"aud\":\"https://microsoft.com/01234567-89ab-cdef-fedc-ba8976543210/" + "oauth2/v2.0/token\"," + "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," + "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; + } + AZURE_UNREACHABLE_CODE(); + } + + size_t GetSignatureSize() { return 256; } + +private: + TempCertFile m_certFile{GetCertFormat()}; +}; + +TEST_P(GetCredentialName, ) { - TempCertFile const tempCertFile; ClientCertificateCredential const cred( "01234567-89ab-cdef-fedc-ba8976543210", "fedcba98-7654-3210-0123-456789abcdef", @@ -40,20 +148,19 @@ TEST(ClientCertificateCredential, GetCredentialName) EXPECT_EQ(cred.GetCredentialName(), "ClientCertificateCredential"); } -TEST(ClientCertificateCredential, Regular) +TEST_P(GetToken, ) { - TempCertFile const tempCertFile; - auto const actual = CredentialTestHelper::SimulateTokenRequest( - [](auto transport) { + [this](auto transport) { ClientCertificateCredentialOptions options; + if (GetTestType() == TestType::Authority) + { + options.AuthorityHost = "https://microsoft.com/"; + } options.Transport.Transport = transport; return std::make_unique( - "01234567-89ab-cdef-fedc-ba8976543210", - "fedcba98-7654-3210-0123-456789abcdef", - TempCertFile::Path, - options); + GetTenantId(), "fedcba98-7654-3210-0123-456789abcdef", TempCertFile::Path, options); }, {{{"https://azure.com/.default"}}, {{}}}, std::vector{ @@ -72,49 +179,35 @@ TEST(ClientCertificateCredential, Regular) EXPECT_EQ(request0.HttpMethod, HttpMethod::Post); EXPECT_EQ(request1.HttpMethod, HttpMethod::Post); - EXPECT_EQ( - request0.AbsoluteUrl, - "https://login.microsoftonline.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/token"); + EXPECT_EQ(request0.AbsoluteUrl, GetRequestUri()); - EXPECT_EQ( - request1.AbsoluteUrl, - "https://login.microsoftonline.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/token"); + EXPECT_EQ(request1.AbsoluteUrl, GetRequestUri()); { - constexpr char expectedBodyStart0[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&scope=https%3A%2F%2Fazure.com%2F.default" - "&client_assertion="; // cspell:enable + auto expectedBodyStart0 = GetBodyStart0(); + auto expectedBodyStart1 = GetBodyStart1(); - constexpr char expectedBodyStart1[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&client_assertion="; // cspell:enable + EXPECT_GT(request0.Body.size(), expectedBodyStart0.size()); + EXPECT_GT(request1.Body.size(), expectedBodyStart1.size()); - EXPECT_GT(request0.Body.size(), (sizeof(expectedBodyStart0) - 1)); - EXPECT_GT(request1.Body.size(), (sizeof(expectedBodyStart1) - 1)); - - EXPECT_EQ(request0.Body.substr(0, (sizeof(expectedBodyStart0) - 1)), expectedBodyStart0); - EXPECT_EQ(request1.Body.substr(0, (sizeof(expectedBodyStart1) - 1)), expectedBodyStart1); + EXPECT_EQ(request0.Body.substr(0, expectedBodyStart0.size()), expectedBodyStart0); + EXPECT_EQ(request1.Body.substr(0, expectedBodyStart1.size()), expectedBodyStart1); EXPECT_NE(request0.Headers.find("Content-Length"), request0.Headers.end()); EXPECT_GT( std::stoi(request0.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart0) - 1)); + static_cast(expectedBodyStart0.size())); EXPECT_NE(request1.Headers.find("Content-Length"), request1.Headers.end()); EXPECT_GT( std::stoi(request1.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart1) - 1)); + static_cast(expectedBodyStart1.size())); { using Azure::Core::_internal::Base64Url; - const auto assertion0 = request0.Body.substr((sizeof(expectedBodyStart0) - 1)); - const auto assertion1 = request1.Body.substr((sizeof(expectedBodyStart1) - 1)); + const auto assertion0 = request0.Body.substr(expectedBodyStart0.size()); + const auto assertion1 = request1.Body.substr(expectedBodyStart1.size()); const auto assertion0Parts = SplitString(assertion0, '.'); const auto assertion1Parts = SplitString(assertion1, '.'); @@ -137,24 +230,18 @@ TEST(ClientCertificateCredential, Regular) const auto payload0 = ToString(payload0Vec); const auto payload1 = ToString(payload1Vec); - constexpr auto ExpectedHeader - = "{\"x5t\":\"V0pIIQwSzNn6vfSTPv-1f7Vt_Pw\",\"kid\":" - "\"574A48210C12CCD9FABDF4933EFFB57FB56DFCFC\",\"alg\":\"RS256\",\"typ\":\"JWT\"}"; + auto ExpectedHeader = GetHeader(); EXPECT_EQ(header0, ExpectedHeader); EXPECT_EQ(header1, ExpectedHeader); - constexpr char ExpectedPayloadStart[] - = "{\"aud\":\"https://login.microsoftonline.com/01234567-89ab-cdef-fedc-ba8976543210/" - "oauth2/v2.0/token\"," - "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," - "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; + auto ExpectedPayloadStart = GetPayloadStart(); - EXPECT_EQ(payload0.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); - EXPECT_EQ(payload1.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); + EXPECT_EQ(payload0.substr(0, ExpectedPayloadStart.size()), ExpectedPayloadStart); + EXPECT_EQ(payload1.substr(0, ExpectedPayloadStart.size()), ExpectedPayloadStart); - EXPECT_EQ(Base64Url::Base64UrlDecode(signature0).size(), 256U); - EXPECT_EQ(Base64Url::Base64UrlDecode(signature1).size(), 256U); + EXPECT_EQ(Base64Url::Base64UrlDecode(signature0).size(), GetSignatureSize()); + EXPECT_EQ(Base64Url::Base64UrlDecode(signature1).size(), GetSignatureSize()); } } @@ -175,357 +262,142 @@ TEST(ClientCertificateCredential, Regular) EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 7200s); } -TEST(ClientCertificateCredential, AzureStack) -{ - TempCertFile const tempCertFile; - - auto const actual = CredentialTestHelper::SimulateTokenRequest( - [](auto transport) { - ClientCertificateCredentialOptions options; - options.Transport.Transport = transport; - - return std::make_unique( - "adfs", "fedcba98-7654-3210-0123-456789abcdef", TempCertFile::Path, options); - }, - {{{"https://azure.com/.default"}}, {{}}}, - std::vector{ - "{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}", - "{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}"}); - - EXPECT_EQ(actual.Requests.size(), 2U); - EXPECT_EQ(actual.Responses.size(), 2U); - - auto const& request0 = actual.Requests.at(0); - auto const& request1 = actual.Requests.at(1); - - auto const& response0 = actual.Responses.at(0); - auto const& response1 = actual.Responses.at(1); - - EXPECT_EQ(request0.HttpMethod, HttpMethod::Post); - EXPECT_EQ(request1.HttpMethod, HttpMethod::Post); - - EXPECT_EQ(request0.AbsoluteUrl, "https://login.microsoftonline.com/adfs/oauth2/token"); - - EXPECT_EQ(request1.AbsoluteUrl, "https://login.microsoftonline.com/adfs/oauth2/token"); - - { - constexpr char expectedBodyStart0[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&scope=https%3A%2F%2Fazure.com" - "&client_assertion="; // cspell:enable - - constexpr char expectedBodyStart1[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&client_assertion="; // cspell:enable - - EXPECT_GT(request0.Body.size(), (sizeof(expectedBodyStart0) - 1)); - EXPECT_GT(request1.Body.size(), (sizeof(expectedBodyStart1) - 1)); - - EXPECT_EQ(request0.Body.substr(0, (sizeof(expectedBodyStart0) - 1)), expectedBodyStart0); - EXPECT_EQ(request1.Body.substr(0, (sizeof(expectedBodyStart1) - 1)), expectedBodyStart1); - - EXPECT_NE(request0.Headers.find("Content-Length"), request0.Headers.end()); - EXPECT_GT( - std::stoi(request0.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart0) - 1)); - - EXPECT_NE(request1.Headers.find("Content-Length"), request1.Headers.end()); - EXPECT_GT( - std::stoi(request1.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart1) - 1)); - - { - using Azure::Core::_internal::Base64Url; - - const auto assertion0 = request0.Body.substr((sizeof(expectedBodyStart0) - 1)); - const auto assertion1 = request1.Body.substr((sizeof(expectedBodyStart1) - 1)); - - const auto assertion0Parts = SplitString(assertion0, '.'); - const auto assertion1Parts = SplitString(assertion1, '.'); - - EXPECT_EQ(assertion0Parts.size(), 3U); - EXPECT_EQ(assertion1Parts.size(), 3U); - - const auto header0Vec = Base64Url::Base64UrlDecode(assertion0Parts[0]); - const auto header1Vec = Base64Url::Base64UrlDecode(assertion1Parts[0]); - - const auto payload0Vec = Base64Url::Base64UrlDecode(assertion0Parts[1]); - const auto payload1Vec = Base64Url::Base64UrlDecode(assertion1Parts[1]); - - const auto signature0 = assertion0Parts[2]; - const auto signature1 = assertion1Parts[2]; - - const auto header0 = ToString(header0Vec); - const auto header1 = ToString(header1Vec); - - const auto payload0 = ToString(payload0Vec); - const auto payload1 = ToString(payload1Vec); - - constexpr auto ExpectedHeader - = "{\"x5t\":\"V0pIIQwSzNn6vfSTPv-1f7Vt_Pw\",\"kid\":" - "\"574A48210C12CCD9FABDF4933EFFB57FB56DFCFC\",\"alg\":\"RS256\",\"typ\":\"JWT\"}"; - - EXPECT_EQ(header0, ExpectedHeader); - EXPECT_EQ(header1, ExpectedHeader); - - constexpr char ExpectedPayloadStart[] - = "{\"aud\":\"https://login.microsoftonline.com/adfs/oauth2/token\"," - "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," - "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; - - EXPECT_EQ(payload0.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); - EXPECT_EQ(payload1.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); - - EXPECT_EQ(Base64Url::Base64UrlDecode(signature0).size(), 256U); - EXPECT_EQ(Base64Url::Base64UrlDecode(signature1).size(), 256U); - } - } - - EXPECT_NE(request0.Headers.find("Content-Type"), request0.Headers.end()); - EXPECT_EQ(request0.Headers.at("Content-Type"), "application/x-www-form-urlencoded"); - - EXPECT_NE(request1.Headers.find("Content-Type"), request1.Headers.end()); - EXPECT_EQ(request1.Headers.at("Content-Type"), "application/x-www-form-urlencoded"); - - EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1"); - EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2"); - - using namespace std::chrono_literals; - EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s); - EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s); - - EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 7200s); - EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 7200s); -} - -TEST(ClientCertificateCredential, Authority) -{ - TempCertFile const tempCertFile; - - auto const actual = CredentialTestHelper::SimulateTokenRequest( - [](auto transport) { - ClientCertificateCredentialOptions options; - options.AuthorityHost = "https://microsoft.com/"; - options.Transport.Transport = transport; - - return std::make_unique( - "01234567-89ab-cdef-fedc-ba8976543210", - "fedcba98-7654-3210-0123-456789abcdef", - TempCertFile::Path, - options); - }, - {{{"https://azure.com/.default"}}, {{}}}, - std::vector{ - "{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}", - "{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}"}); - - EXPECT_EQ(actual.Requests.size(), 2U); - EXPECT_EQ(actual.Responses.size(), 2U); - - auto const& request0 = actual.Requests.at(0); - auto const& request1 = actual.Requests.at(1); - - auto const& response0 = actual.Responses.at(0); - auto const& response1 = actual.Responses.at(1); - - EXPECT_EQ(request0.HttpMethod, HttpMethod::Post); - EXPECT_EQ(request1.HttpMethod, HttpMethod::Post); - - EXPECT_EQ( - request0.AbsoluteUrl, - "https://microsoft.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/token"); - - EXPECT_EQ( - request1.AbsoluteUrl, - "https://microsoft.com/01234567-89ab-cdef-fedc-ba8976543210/oauth2/v2.0/token"); - - { - constexpr char expectedBodyStart0[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&scope=https%3A%2F%2Fazure.com%2F.default" - "&client_assertion="; // cspell:enable - - constexpr char expectedBodyStart1[] // cspell:disable - = "grant_type=client_credentials" - "&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" - "&client_id=fedcba98-7654-3210-0123-456789abcdef" - "&client_assertion="; // cspell:enable - - EXPECT_GT(request0.Body.size(), (sizeof(expectedBodyStart0) - 1)); - EXPECT_GT(request1.Body.size(), (sizeof(expectedBodyStart1) - 1)); - - EXPECT_EQ(request0.Body.substr(0, (sizeof(expectedBodyStart0) - 1)), expectedBodyStart0); - EXPECT_EQ(request1.Body.substr(0, (sizeof(expectedBodyStart1) - 1)), expectedBodyStart1); - - EXPECT_NE(request0.Headers.find("Content-Length"), request0.Headers.end()); - EXPECT_GT( - std::stoi(request0.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart0) - 1)); - - EXPECT_NE(request1.Headers.find("Content-Length"), request1.Headers.end()); - EXPECT_GT( - std::stoi(request1.Headers.at("Content-Length")), - static_cast(sizeof(expectedBodyStart1) - 1)); - - { - using Azure::Core::_internal::Base64Url; - - const auto assertion0 = request0.Body.substr((sizeof(expectedBodyStart0) - 1)); - const auto assertion1 = request1.Body.substr((sizeof(expectedBodyStart1) - 1)); - - const auto assertion0Parts = SplitString(assertion0, '.'); - const auto assertion1Parts = SplitString(assertion1, '.'); - - EXPECT_EQ(assertion0Parts.size(), 3U); - EXPECT_EQ(assertion1Parts.size(), 3U); - - const auto header0Vec = Base64Url::Base64UrlDecode(assertion0Parts[0]); - const auto header1Vec = Base64Url::Base64UrlDecode(assertion1Parts[0]); - - const auto payload0Vec = Base64Url::Base64UrlDecode(assertion0Parts[1]); - const auto payload1Vec = Base64Url::Base64UrlDecode(assertion1Parts[1]); - - const auto signature0 = assertion0Parts[2]; - const auto signature1 = assertion1Parts[2]; - - const auto header0 = ToString(header0Vec); - const auto header1 = ToString(header1Vec); - - const auto payload0 = ToString(payload0Vec); - const auto payload1 = ToString(payload1Vec); - - constexpr auto ExpectedHeader - = "{\"x5t\":\"V0pIIQwSzNn6vfSTPv-1f7Vt_Pw\",\"kid\":" - "\"574A48210C12CCD9FABDF4933EFFB57FB56DFCFC\",\"alg\":\"RS256\",\"typ\":\"JWT\"}"; - - EXPECT_EQ(header0, ExpectedHeader); - EXPECT_EQ(header1, ExpectedHeader); - - constexpr char ExpectedPayloadStart[] - = "{\"aud\":\"https://microsoft.com/01234567-89ab-cdef-fedc-ba8976543210/" - "oauth2/v2.0/token\"," - "\"iss\":\"fedcba98-7654-3210-0123-456789abcdef\"," - "\"sub\":\"fedcba98-7654-3210-0123-456789abcdef\",\"jti\":\""; - - EXPECT_EQ(payload0.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); - EXPECT_EQ(payload1.substr(0, (sizeof(ExpectedPayloadStart) - 1)), ExpectedPayloadStart); - - EXPECT_EQ(Base64Url::Base64UrlDecode(signature0).size(), 256U); - EXPECT_EQ(Base64Url::Base64UrlDecode(signature1).size(), 256U); - } - } - - EXPECT_NE(request0.Headers.find("Content-Type"), request0.Headers.end()); - EXPECT_EQ(request0.Headers.at("Content-Type"), "application/x-www-form-urlencoded"); - - EXPECT_NE(request1.Headers.find("Content-Type"), request1.Headers.end()); - EXPECT_EQ(request1.Headers.at("Content-Type"), "application/x-www-form-urlencoded"); - - EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1"); - EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2"); - - using namespace std::chrono_literals; - EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s); - EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s); - - EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 7200s); - EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 7200s); -} +INSTANTIATE_TEST_SUITE_P( + ClientCertificateCredential, + GetCredentialName, + testing::Values(RsaPkcs, RsaRaw)); + +INSTANTIATE_TEST_SUITE_P( + ClientCertificateCredential, + GetToken, + testing::Combine( + testing::Values(Regular, AzureStack, Authority), + testing::Values(RsaPkcs, RsaRaw))); namespace { const char* const TempCertFile::Path = "azure-identity-test.pem"; TempCertFile::~TempCertFile() { std::remove(Path); } -TempCertFile::TempCertFile() +TempCertFile::TempCertFile(CertFormat format) { std::ofstream cert(Path, std::ios_base::out | std::ios_base::trunc); - cert << // cspell:disable - "Bag Attributes\n" - " Microsoft Local Key set: \n" - " localKeyID: 01 00 00 00 \n" - " friendlyName: te-66f5c973-4fc8-4cd3-8acc-64964d79b693\n" - " Microsoft CSP Name: Microsoft Software Key Storage Provider\n" - "Key Attributes\n" - " X509v3 Key Usage: 90 \n" - "-----BEGIN PRIVATE KEY-----\n"; + if (format == RsaPkcs) + cert << // cspell:disable + "Bag Attributes\n" + " Microsoft Local Key set: \n" + " localKeyID: 01 00 00 00 \n" + " friendlyName: te-66f5c973-4fc8-4cd3-8acc-64964d79b693\n" + " Microsoft CSP Name: Microsoft Software Key Storage Provider\n" + "Key Attributes\n" + " X509v3 Key Usage: 90 \n" + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPdm4pukO7ugEx\n" + "8wXrmo4VIEoicp7w3QsEJGA2bMx9nHMvwugG54t14QpfqBQYQWLeL1HmpcDeivVD\n" + "+15ZXeGLCPVZBHhoY8ZWGibfhAAzqQ0P9Ca1kydjvB4uJcEnF/RYtQv6n6OwmdO1\n" + "wJ22JNcRlMtZqmnb/Q0In2fjXEbdl85/GZlYzMQRdyfI0yriSRBcYV2kg0zeXCxf\n" + "mCvB3rb6I1KpoUFHlkeHtkeDwm0VHUEt4Hz8ghcB00tI5eS2fH2rPkINQKc6+0QU\n" + "C2KICQC+GzJsYDbwQOao5Vhk80H5LRuM9Ndzv+fU3lLnktYCgXgL9AX4L/R9Z4Pz\n" + "tuao/qbRAgMBAAECggEBAMQZIrooiTuZ7uVC3Ja96Y1IjyqOg3QSzAXnSFZJcuVM\n" + "i4hayC02khkjVUXjvtLKg2SW/+hvRqZUXM8cfCsm1Tkxh4/T7OhnXyMl5xahU/uA\n" + "0IsC8c/xv2rDdxeRskh8mQd8Yk1MtlIIpRgIcEqp+exxY+FmdldtkvNSkcVUBNwQ\n" + "nXi+oWPhE2guo2g1BPk2gbF0+3FvSrQ8QwGHg+uQJwrQpJ+SB9TyuQFauGR5/wSq\n" + "H93cFH5YC/+v5I7qW6ZQe0f7rEKQDybGVzkBlKJyGCVYmPn7Xa/wJriws+FZIfHz\n" + "f3m0kJigxJd/HwTrnKSg+H8oBgng7lZLdBYWHMGJhA0CgYEA48moW7szegvfLuUF\n" + "a0sHfyKuNyvOv7Wud4sa0lwdKPHS+atwL6TNUWCAGkomYADEe3qiYgMXDX9U3hlW\n" + "6zktYFj03tnRg4iBjp8nchLBVLf3Wd5TPRw1VKu4ZW43y8BRhYWV+3Z4s1nyMEDA\n" + "NFbKRmL7LDB05oWHdJMjFK/L6YcCgYEA6ShV4v2RQiXzkW6GHSBZDIVHCeWwvIld\n" + "OlEfG7wzZW4e8wNDhfSMtXyJrzfbEyXBtVKoESdP6Nnm9W7ftcynW965S94THuy7\n" + "+ofvHo6JAm8g/0uX70wZ26LU8qhkJMTWmsONBNKLwUzkFT7VGsdaBliam1RLvjeT\n" + "URdQgnftIucCgYEA4FYamT0k1W4bv/OOAr1CBNQDABME64ni6Zj2MXbGwSxou7s8\n" + "IbANBbgkcb/VS3d2CqYchqrEaWaeDp6mG8OUDO+POmsLDJ/D+NKF5rLR9L25vahY\n" + "EjdVzq3QTRTfnqspnnaR37Yt6XUMMLmUkfdn/yo8dKjEeMPJQ+YlBpqcGMECgYBZ\n" + "rmIaxV2yC9b8AX8khOS7pCgG7opkepGZdMp6aJF8WjcdUgwO4lmdFSIAe4OQgd1Y\n" + "WUq8Dlr2PZpQnSz/SJC3DZxISksggf5sBw06u6iHfyc6C2GNccAgcylljM+4NN42\n" + "+TCswi9vUpwIb/qYKkW+WyZcyLe5mrbXYhhdlrNn0QKBgDe8aRG+MOSUTTXjAVss\n" + "bDY0Us943FN91qBmagNqDyozKAAqDoKvdRxM0IlIDnOptj4AfbpJ1JThNOJDYBpU\n" + "+Azo8UoedANgndtZ2n11RSjmlQ6TE/WGlsirHExqr6y/l71znoQm1y3E2cArbsmy\n" + "hp0P5v42PKxmAx4pR0EjNKsd\n" + "-----END PRIVATE KEY-----\n" + "Bag Attributes\n" + " localKeyID: 01 00 00 00 \n" + " 1.3.6.1.4.1.311.17.3.71: 61 00 6E 00 74 00 6B 00 2D 00 6C 00 61 00 70 00 " + "74 00 6F 00 70 00 00 00 \n" + "subject=CN = azure-identity-test\n" + "\n" + "issuer=CN = azure-identity-test\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDODCCAiCgAwIBAgIQNqa9U3MBxqBF7ksWk+XRkzANBgkqhkiG9w0BAQsFADAe\n" + "MRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0MCAXDTIyMDQyMjE1MDYwNloY\n" + "DzIyMjIwMTAxMDcwMDAwWjAeMRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0\n" + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz3ZuKbpDu7oBMfMF65qO\n" + "FSBKInKe8N0LBCRgNmzMfZxzL8LoBueLdeEKX6gUGEFi3i9R5qXA3or1Q/teWV3h\n" + "iwj1WQR4aGPGVhom34QAM6kND/QmtZMnY7weLiXBJxf0WLUL+p+jsJnTtcCdtiTX\n" + "EZTLWapp2/0NCJ9n41xG3ZfOfxmZWMzEEXcnyNMq4kkQXGFdpINM3lwsX5grwd62\n" + "+iNSqaFBR5ZHh7ZHg8JtFR1BLeB8/IIXAdNLSOXktnx9qz5CDUCnOvtEFAtiiAkA\n" + "vhsybGA28EDmqOVYZPNB+S0bjPTXc7/n1N5S55LWAoF4C/QF+C/0fWeD87bmqP6m\n" + "0QIDAQABo3AwbjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIG\n" + "CCsGAQUFBwMBMB4GA1UdEQQXMBWCE2F6dXJlLWlkZW50aXR5LXRlc3QwHQYDVR0O\n" + "BBYEFCoJ5tInmafyNuR0tGxZOz522jlWMA0GCSqGSIb3DQEBCwUAA4IBAQBzLXpw\n" + "Xmrg1sQTmzMnS24mREKxj9B3YILmgsdBMrHkH07QUROee7IbQ8gfBKeln0dEcfYi\n" + "Jyh42jn+fmg9AR17RP80wPthD2eKOt4WYNkNM3H8U4JEo+0ML0jZyswynpR48h/E\n" + "m96sm/NUeKUViD5iVTb1uHL4j8mQAN1IbXcunXvrrek1CzFVn5Rpah0Tn+6cYVKd\n" + "Jg531i53udzusgZtV1NPZ82tzYkPQG1vxB//D9vd0LzmcfCvT50MKhz0r/c5yJYk\n" + "i9q94DBuzMhe+O9j+Ob2pVQt5akVFJVtIVSfBZzRBAd66u9JeADlT4sxwS4QAUHi\n" + "RrCsEpJsnJXkx/6O\n" + "-----END CERTIFICATE-----\n"; // cspell:enable - - cert << // cspell:disable - "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPdm4pukO7ugEx\n" - "8wXrmo4VIEoicp7w3QsEJGA2bMx9nHMvwugG54t14QpfqBQYQWLeL1HmpcDeivVD\n" - "+15ZXeGLCPVZBHhoY8ZWGibfhAAzqQ0P9Ca1kydjvB4uJcEnF/RYtQv6n6OwmdO1\n" - "wJ22JNcRlMtZqmnb/Q0In2fjXEbdl85/GZlYzMQRdyfI0yriSRBcYV2kg0zeXCxf\n" - "mCvB3rb6I1KpoUFHlkeHtkeDwm0VHUEt4Hz8ghcB00tI5eS2fH2rPkINQKc6+0QU\n" - "C2KICQC+GzJsYDbwQOao5Vhk80H5LRuM9Ndzv+fU3lLnktYCgXgL9AX4L/R9Z4Pz\n" - "tuao/qbRAgMBAAECggEBAMQZIrooiTuZ7uVC3Ja96Y1IjyqOg3QSzAXnSFZJcuVM\n" - "i4hayC02khkjVUXjvtLKg2SW/+hvRqZUXM8cfCsm1Tkxh4/T7OhnXyMl5xahU/uA\n" - "0IsC8c/xv2rDdxeRskh8mQd8Yk1MtlIIpRgIcEqp+exxY+FmdldtkvNSkcVUBNwQ\n" - "nXi+oWPhE2guo2g1BPk2gbF0+3FvSrQ8QwGHg+uQJwrQpJ+SB9TyuQFauGR5/wSq\n" - "H93cFH5YC/+v5I7qW6ZQe0f7rEKQDybGVzkBlKJyGCVYmPn7Xa/wJriws+FZIfHz\n" - "f3m0kJigxJd/HwTrnKSg+H8oBgng7lZLdBYWHMGJhA0CgYEA48moW7szegvfLuUF\n" - "a0sHfyKuNyvOv7Wud4sa0lwdKPHS+atwL6TNUWCAGkomYADEe3qiYgMXDX9U3hlW\n"; - // cspell:enable - - cert << // cspell:disable - "6zktYFj03tnRg4iBjp8nchLBVLf3Wd5TPRw1VKu4ZW43y8BRhYWV+3Z4s1nyMEDA\n" - "NFbKRmL7LDB05oWHdJMjFK/L6YcCgYEA6ShV4v2RQiXzkW6GHSBZDIVHCeWwvIld\n" - "OlEfG7wzZW4e8wNDhfSMtXyJrzfbEyXBtVKoESdP6Nnm9W7ftcynW965S94THuy7\n" - "+ofvHo6JAm8g/0uX70wZ26LU8qhkJMTWmsONBNKLwUzkFT7VGsdaBliam1RLvjeT\n" - "URdQgnftIucCgYEA4FYamT0k1W4bv/OOAr1CBNQDABME64ni6Zj2MXbGwSxou7s8\n" - "IbANBbgkcb/VS3d2CqYchqrEaWaeDp6mG8OUDO+POmsLDJ/D+NKF5rLR9L25vahY\n" - "EjdVzq3QTRTfnqspnnaR37Yt6XUMMLmUkfdn/yo8dKjEeMPJQ+YlBpqcGMECgYBZ\n" - "rmIaxV2yC9b8AX8khOS7pCgG7opkepGZdMp6aJF8WjcdUgwO4lmdFSIAe4OQgd1Y\n" - "WUq8Dlr2PZpQnSz/SJC3DZxISksggf5sBw06u6iHfyc6C2GNccAgcylljM+4NN42\n" - "+TCswi9vUpwIb/qYKkW+WyZcyLe5mrbXYhhdlrNn0QKBgDe8aRG+MOSUTTXjAVss\n" - "bDY0Us943FN91qBmagNqDyozKAAqDoKvdRxM0IlIDnOptj4AfbpJ1JThNOJDYBpU\n" - "+Azo8UoedANgndtZ2n11RSjmlQ6TE/WGlsirHExqr6y/l71znoQm1y3E2cArbsmy\n" - "hp0P5v42PKxmAx4pR0EjNKsd\n"; - // cspell:enable - - cert << // cspell:disable - "-----END PRIVATE KEY-----\n" - "Bag Attributes\n" - " localKeyID: 01 00 00 00 \n" - " 1.3.6.1.4.1.311.17.3.71: 61 00 6E 00 74 00 6B 00 2D 00 6C 00 61 00 70 00 " - "74 00 6F 00 70 00 00 00 \n" - "subject=CN = azure-identity-test\n" - "\n" - "issuer=CN = azure-identity-test\n" - "\n" - "-----BEGIN CERTIFICATE-----\n"; - // cspell:enable - - cert << // cspell:disable - "MIIDODCCAiCgAwIBAgIQNqa9U3MBxqBF7ksWk+XRkzANBgkqhkiG9w0BAQsFADAe\n" - "MRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0MCAXDTIyMDQyMjE1MDYwNloY\n" - "DzIyMjIwMTAxMDcwMDAwWjAeMRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0\n" - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz3ZuKbpDu7oBMfMF65qO\n" - "FSBKInKe8N0LBCRgNmzMfZxzL8LoBueLdeEKX6gUGEFi3i9R5qXA3or1Q/teWV3h\n" - "iwj1WQR4aGPGVhom34QAM6kND/QmtZMnY7weLiXBJxf0WLUL+p+jsJnTtcCdtiTX\n" - "EZTLWapp2/0NCJ9n41xG3ZfOfxmZWMzEEXcnyNMq4kkQXGFdpINM3lwsX5grwd62\n" - "+iNSqaFBR5ZHh7ZHg8JtFR1BLeB8/IIXAdNLSOXktnx9qz5CDUCnOvtEFAtiiAkA\n" - "vhsybGA28EDmqOVYZPNB+S0bjPTXc7/n1N5S55LWAoF4C/QF+C/0fWeD87bmqP6m\n"; - // cspell:enable - - cert << // cspell:disable - "0QIDAQABo3AwbjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIG\n" - "CCsGAQUFBwMBMB4GA1UdEQQXMBWCE2F6dXJlLWlkZW50aXR5LXRlc3QwHQYDVR0O\n" - "BBYEFCoJ5tInmafyNuR0tGxZOz522jlWMA0GCSqGSIb3DQEBCwUAA4IBAQBzLXpw\n" - "Xmrg1sQTmzMnS24mREKxj9B3YILmgsdBMrHkH07QUROee7IbQ8gfBKeln0dEcfYi\n" - "Jyh42jn+fmg9AR17RP80wPthD2eKOt4WYNkNM3H8U4JEo+0ML0jZyswynpR48h/E\n" - "m96sm/NUeKUViD5iVTb1uHL4j8mQAN1IbXcunXvrrek1CzFVn5Rpah0Tn+6cYVKd\n" - "Jg531i53udzusgZtV1NPZ82tzYkPQG1vxB//D9vd0LzmcfCvT50MKhz0r/c5yJYk\n" - "i9q94DBuzMhe+O9j+Ob2pVQt5akVFJVtIVSfBZzRBAd66u9JeADlT4sxwS4QAUHi\n" - "RrCsEpJsnJXkx/6O\n" - "-----END CERTIFICATE-----\n"; + else if (format == RsaRaw) + cert << // cspell:disable + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEAz3ZuKbpDu7oBMfMF65qOFSBKInKe8N0LBCRgNmzMfZxzL8Lo\n" + "BueLdeEKX6gUGEFi3i9R5qXA3or1Q/teWV3hiwj1WQR4aGPGVhom34QAM6kND/Qm\n" + "tZMnY7weLiXBJxf0WLUL+p+jsJnTtcCdtiTXEZTLWapp2/0NCJ9n41xG3ZfOfxmZ\n" + "WMzEEXcnyNMq4kkQXGFdpINM3lwsX5grwd62+iNSqaFBR5ZHh7ZHg8JtFR1BLeB8\n" + "/IIXAdNLSOXktnx9qz5CDUCnOvtEFAtiiAkAvhsybGA28EDmqOVYZPNB+S0bjPTX\n" + "c7/n1N5S55LWAoF4C/QF+C/0fWeD87bmqP6m0QIDAQABAoIBAQDEGSK6KIk7me7l\n" + "QtyWvemNSI8qjoN0EswF50hWSXLlTIuIWsgtNpIZI1VF477SyoNklv/ob0amVFzP\n" + "HHwrJtU5MYeP0+zoZ18jJecWoVP7gNCLAvHP8b9qw3cXkbJIfJkHfGJNTLZSCKUY\n" + "CHBKqfnscWPhZnZXbZLzUpHFVATcEJ14vqFj4RNoLqNoNQT5NoGxdPtxb0q0PEMB\n" + "h4PrkCcK0KSfkgfU8rkBWrhkef8Eqh/d3BR+WAv/r+SO6lumUHtH+6xCkA8mxlc5\n" + "AZSichglWJj5+12v8Ca4sLPhWSHx8395tJCYoMSXfx8E65ykoPh/KAYJ4O5WS3QW\n" + "FhzBiYQNAoGBAOPJqFu7M3oL3y7lBWtLB38irjcrzr+1rneLGtJcHSjx0vmrcC+k\n" + "zVFggBpKJmAAxHt6omIDFw1/VN4ZVus5LWBY9N7Z0YOIgY6fJ3ISwVS391neUz0c\n" + "NVSruGVuN8vAUYWFlft2eLNZ8jBAwDRWykZi+ywwdOaFh3STIxSvy+mHAoGBAOko\n" + "VeL9kUIl85Fuhh0gWQyFRwnlsLyJXTpRHxu8M2VuHvMDQ4X0jLV8ia832xMlwbVS\n" + "qBEnT+jZ5vVu37XMp1veuUveEx7su/qH7x6OiQJvIP9Ll+9MGdui1PKoZCTE1prD\n" + "jQTSi8FM5BU+1RrHWgZYmptUS743k1EXUIJ37SLnAoGBAOBWGpk9JNVuG7/zjgK9\n" + "QgTUAwATBOuJ4umY9jF2xsEsaLu7PCGwDQW4JHG/1Ut3dgqmHIaqxGlmng6ephvD\n" + "lAzvjzprCwyfw/jSheay0fS9ub2oWBI3Vc6t0E0U356rKZ52kd+2Lel1DDC5lJH3\n" + "Z/8qPHSoxHjDyUPmJQaanBjBAoGAWa5iGsVdsgvW/AF/JITku6QoBu6KZHqRmXTK\n" + "emiRfFo3HVIMDuJZnRUiAHuDkIHdWFlKvA5a9j2aUJ0s/0iQtw2cSEpLIIH+bAcN\n" + "Oruoh38nOgthjXHAIHMpZYzPuDTeNvkwrMIvb1KcCG/6mCpFvlsmXMi3uZq212IY\n" + "XZazZ9ECgYA3vGkRvjDklE014wFbLGw2NFLPeNxTfdagZmoDag8qMygAKg6Cr3Uc\n" + "TNCJSA5zqbY+AH26SdSU4TTiQ2AaVPgM6PFKHnQDYJ3bWdp9dUUo5pUOkxP1hpbI\n" + "qxxMaq+sv5e9c56EJtctxNnAK27JsoadD+b+NjysZgMeKUdBIzSrHQ==\n" + "-----END RSA PRIVATE KEY-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDODCCAiCgAwIBAgIQNqa9U3MBxqBF7ksWk+XRkzANBgkqhkiG9w0BAQsFADAe\n" + "MRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0MCAXDTIyMDQyMjE1MDYwNloY\n" + "DzIyMjIwMTAxMDcwMDAwWjAeMRwwGgYDVQQDDBNhenVyZS1pZGVudGl0eS10ZXN0\n" + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz3ZuKbpDu7oBMfMF65qO\n" + "FSBKInKe8N0LBCRgNmzMfZxzL8LoBueLdeEKX6gUGEFi3i9R5qXA3or1Q/teWV3h\n" + "iwj1WQR4aGPGVhom34QAM6kND/QmtZMnY7weLiXBJxf0WLUL+p+jsJnTtcCdtiTX\n" + "EZTLWapp2/0NCJ9n41xG3ZfOfxmZWMzEEXcnyNMq4kkQXGFdpINM3lwsX5grwd62\n" + "+iNSqaFBR5ZHh7ZHg8JtFR1BLeB8/IIXAdNLSOXktnx9qz5CDUCnOvtEFAtiiAkA\n" + "vhsybGA28EDmqOVYZPNB+S0bjPTXc7/n1N5S55LWAoF4C/QF+C/0fWeD87bmqP6m\n" + "0QIDAQABo3AwbjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIG\n" + "CCsGAQUFBwMBMB4GA1UdEQQXMBWCE2F6dXJlLWlkZW50aXR5LXRlc3QwHQYDVR0O\n" + "BBYEFCoJ5tInmafyNuR0tGxZOz522jlWMA0GCSqGSIb3DQEBCwUAA4IBAQBzLXpw\n" + "Xmrg1sQTmzMnS24mREKxj9B3YILmgsdBMrHkH07QUROee7IbQ8gfBKeln0dEcfYi\n" + "Jyh42jn+fmg9AR17RP80wPthD2eKOt4WYNkNM3H8U4JEo+0ML0jZyswynpR48h/E\n" + "m96sm/NUeKUViD5iVTb1uHL4j8mQAN1IbXcunXvrrek1CzFVn5Rpah0Tn+6cYVKd\n" + "Jg531i53udzusgZtV1NPZ82tzYkPQG1vxB//D9vd0LzmcfCvT50MKhz0r/c5yJYk\n" + "i9q94DBuzMhe+O9j+Ob2pVQt5akVFJVtIVSfBZzRBAd66u9JeADlT4sxwS4QAUHi\n" + "RrCsEpJsnJXkx/6O\n" + "-----END CERTIFICATE-----"; // cspell:enable } diff --git a/sdk/identity/azure-identity/vcpkg.json b/sdk/identity/azure-identity/vcpkg.json index 222462e84..a8811d221 100644 --- a/sdk/identity/azure-identity/vcpkg.json +++ b/sdk/identity/azure-identity/vcpkg.json @@ -3,6 +3,13 @@ "version-string": "1.0.0", "dependencies": [ "azure-core-cpp", - "openssl" + { + "name": "openssl", + "platform": "!windows & !uwp" + }, + { + "name": "wil", + "platform": "windows" + } ] } diff --git a/sdk/identity/azure-identity/vcpkg/Config.cmake.in b/sdk/identity/azure-identity/vcpkg/Config.cmake.in index 4a8a76896..ef47e86ba 100644 --- a/sdk/identity/azure-identity/vcpkg/Config.cmake.in +++ b/sdk/identity/azure-identity/vcpkg/Config.cmake.in @@ -6,7 +6,11 @@ include(CMakeFindDependencyMacro) find_dependency(azure-core-cpp) -find_dependency(OpenSSL) +if (WIN32) + find_dependency(wil) +else() + find_dependency(OpenSSL) +endif() include("${CMAKE_CURRENT_LIST_DIR}/azure-identity-cppTargets.cmake") diff --git a/sdk/identity/azure-identity/vcpkg/vcpkg.json b/sdk/identity/azure-identity/vcpkg/vcpkg.json index a98245ce5..00cc878be 100644 --- a/sdk/identity/azure-identity/vcpkg/vcpkg.json +++ b/sdk/identity/azure-identity/vcpkg/vcpkg.json @@ -16,7 +16,14 @@ "default-features": false, "version>=": "1.9.0" }, - "openssl", + { + "name": "openssl", + "platform": "!windows & !uwp" + }, + { + "name": "wil", + "platform": "windows" + }, { "name": "vcpkg-cmake", "host": true