diff --git a/README.md b/README.md index 95768d8..960ccf3 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,89 @@ +[![Build Status](https://travis-ci.org/Azure/azure-keyvault-java.svg?branch=dev)](https://travis-ci.org/Azure/azure-keyvault-java) + # Microsoft Azure Key Vault SDK for Java This is the Microsoft Azure Key Vault client library which allows for the consumption of Key Vault services. Azure Key Vault helps safeguard cryptographic keys and secrets used by cloud applications and services. By using Key Vault, you can encrypt keys and secrets (such as authentication keys, storage account keys, data encryption keys, .PFX files, and passwords) using keys protected by hardware security modules (HSMs). For added assurance, you can import or generate keys in HSMs. If you choose to do this, Microsoft processes your keys in FIPS 140-2 Level 2 validated HSMs (hardware and firmware). Key Vault streamlines the key management process and enables you to maintain control of keys that access and encrypt your data. Developers can create keys for development and testing in minutes, and then seamlessly migrate them to production keys. Security administrators can grant (and revoke) permission to keys, as needed. For more information refer to [What is Key Vault?](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis) or [Getting Started](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-get-started). +Documentation for this SDK can be found at [Azure Key Vault Java Documentation](https://docs.microsoft.com/en-us/java/api/overview/azure/keyvault) + ## Sample code You can find sample code that illustrates key vault usage scenarios [here](https://azure.microsoft.com/en-us/resources/samples/?sort=0&service=key-vault&platform=java). + + + + + + + + + + + + + + + + + +
CategorySamples
Authentication + +
Vault Management + +
Secret Management + +
+ +For more information on using Java with Azure, see [here](https://azure.microsoft.com/en-us/develop/java/) + ## Download -To get the binaries of this library as distributed by Microsoft, ready for use within your project, you can use Maven. +To get the binaries of this library as distributed by Microsoft, ready for use within your project, you can use Maven. Add the following fragment to you POM's dependencies. ```xml com.microsoft.azure - azure-keyvault - 1.1 - - - com.microsoft.azure - azure-keyvault-cryptography - 1.1 - - - com.microsoft.azure - azure-keyvault-extensions - 1.1 - - - com.microsoft.azure - azure-keyvault-core - 1.1 - - - com.microsoft.azure - azure-keyvault-webkey - 1.1 + azure-keyvault-complete + 1.1.1 ``` @@ -62,6 +110,15 @@ If you would like to become an active contributor to this project please follow 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request +# Previous Versions + +| Version | Comments | +| :-------: | :-------- | +| [1.1](https://github.com/Azure/azure-keyvault-java/tree/1.1) | Version 1.1 release | +| [1.1-beta-1](https://github.com/Azure/azure-keyvault-java/tree/1.1-beta-1) | Version 1.1.0 **beta** release | +| [1.1-alpha-2](https://github.com/Azure/azure-keyvault-java/tree/v1.1-alpha-2) | Version 1.1.0 **alpha** release | +| [1.0.0](https://github.com/Azure/azure-keyvault-java/tree/v1.0.0) | Version 1.0.0 release | + # More information * [Azure Key Vault Java Documentation](https://docs.microsoft.com/en-us/java/api/overview/azure/keyvault) * [What is Key Vault?](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis) diff --git a/azure-keyvault-complete/pom.xml b/azure-keyvault-complete/pom.xml new file mode 100644 index 0000000..1099d7c --- /dev/null +++ b/azure-keyvault-complete/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + + com.microsoft.azure + azure-keyvault-parent + 1.1.1 + ../pom.xml + + + com.microsoft.azure + azure-keyvault-complete + 1.1.1 + pom + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + repo + + + + Microsoft Azure Key Vault SDK Complete + This encapsulate all modules of the Microsoft Azure Key Vault SDK. + https://github.com/Azure/azure-keyvault-java + + + UTF-8 + + + + + scm:git:https://github.com/Azure/azure-keyvault-java + scm:git:git@github.com:Azure/azure-keyvault-java.git + HEAD + + + + + microsoft + Microsoft + + + + + + com.microsoft.azure + azure-keyvault + + + com.microsoft.azure + azure-keyvault-core + + + com.microsoft.azure + azure-keyvault-webkey + + + com.microsoft.azure + azure-keyvault-extensions + + + com.microsoft.azure + azure-keyvault-cryptography + + + + \ No newline at end of file diff --git a/azure-keyvault-core/pom.xml b/azure-keyvault-core/pom.xml index 7b53f5e..8414241 100644 --- a/azure-keyvault-core/pom.xml +++ b/azure-keyvault-core/pom.xml @@ -8,11 +8,12 @@ com.microsoft.azure azure-keyvault-parent - 1.1 + 1.1.1 ../pom.xml azure-keyvault-core + 1.1.1 jar Microsoft Azure SDK for Key Vault Core @@ -45,6 +46,19 @@ + + + + + org.apache.commons + commons-lang3 + + + com.google.guava + guava + + + @@ -92,16 +106,4 @@ - - - org.apache.commons - commons-lang3 - 3.4 - - - com.google.guava - guava - 20.0 - - diff --git a/azure-keyvault-cryptography/pom.xml b/azure-keyvault-cryptography/pom.xml index 66f8eba..d8763fe 100644 --- a/azure-keyvault-cryptography/pom.xml +++ b/azure-keyvault-cryptography/pom.xml @@ -7,11 +7,12 @@ com.microsoft.azure azure-keyvault-parent - 1.1 + 1.1.1 ../pom.xml azure-keyvault-cryptography + 1.1.1 jar Microsoft Azure SDK for Key Vault Cryptography @@ -41,37 +42,48 @@ - - junit - junit - test - - - org.bouncycastle - bcprov-jdk15on - test - 1.59 - - - com.microsoft.azure - azure-keyvault-webkey - 1.1 - - - com.microsoft.azure - azure-keyvault-core - 1.0.0 - - - com.microsoft.rest - client-runtime - 1.3.0 - - - com.microsoft.azure - azure-client-authentication - 1.3.0 - - + + + + com.microsoft.azure + azure-keyvault-webkey + + + com.microsoft.azure + azure-keyvault-core + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.apache.commons + commons-lang3 + + + commons-codec + commons-codec + + + com.google.guava + guava + + + + + + junit + junit + test + + + org.bouncycastle + bcprov-jdk15on + test + diff --git a/azure-keyvault-extensions/pom.xml b/azure-keyvault-extensions/pom.xml index 03610bf..98e6957 100644 --- a/azure-keyvault-extensions/pom.xml +++ b/azure-keyvault-extensions/pom.xml @@ -8,11 +8,12 @@ com.microsoft.azure azure-keyvault-parent - 1.1 + 1.1.1 ../pom.xml azure-keyvault-extensions + 1.1.1 jar Microsoft Azure SDK for Key Vault Extensions @@ -46,56 +47,86 @@ + + + + com.microsoft.azure + azure-keyvault-webkey + + + com.microsoft.azure + azure-keyvault-core + + + com.microsoft.azure + azure-keyvault-cryptography + + + com.microsoft.azure + azure-keyvault + 1.1.1 + + + com.microsoft.azure azure-client-runtime - commons-codec - commons-codec + com.microsoft.azure + azure-mgmt-resources + + - junit - junit - test + com.microsoft.rest + client-runtime + + - org.bouncycastle - bcprov-jdk15on - test - 1.54 + com.google.guava + guava - com.microsoft.azure - azure-keyvault-core - 1.1 + org.apache.commons + commons-lang3 - com.microsoft.azure - azure-keyvault-cryptography - 1.1 + commons-codec + commons-codec + + + + - com.microsoft.azure - azure-keyvault - 1.1 + com.microsoft.azure + azure-mgmt-resources + 1.3.1-SNAPSHOT + test-jar + test - com.microsoft.azure - azure-keyvault-webkey - 1.1 - - + com.microsoft.azure + adal4j + test + + com.microsoft.azure azure - 1.3.0 test - - com.microsoft.azure - azure-mgmt-resources - 1.3.1-SNAPSHOT - test-jar + + + + junit + junit + test + + + org.bouncycastle + bcprov-jdk15on test @@ -104,17 +135,8 @@ 1.10.19 test - - com.microsoft.azure - adal4j - test - - - com.google.guava - guava - 20.0 - + diff --git a/azure-keyvault-webkey/pom.xml b/azure-keyvault-webkey/pom.xml index c33885f..258ec05 100644 --- a/azure-keyvault-webkey/pom.xml +++ b/azure-keyvault-webkey/pom.xml @@ -6,11 +6,12 @@ com.microsoft.azure azure-keyvault-parent - 1.1 + 1.1.1 ../pom.xml azure-keyvault-webkey + 1.1.1 jar Microsoft Azure SDK for Key Vault WebKey @@ -44,10 +45,22 @@ + + com.fasterxml.jackson.core jackson-databind + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + commons-codec commons-codec @@ -55,24 +68,17 @@ com.google.guava guava - - - com.microsoft.rest - client-runtime - 1.3.0 - - - com.microsoft.azure - azure-client-authentication - 1.3.0 - - + + + junit junit test + + diff --git a/azure-keyvault/pom.xml b/azure-keyvault/pom.xml index 70f95dd..0e8da25 100644 --- a/azure-keyvault/pom.xml +++ b/azure-keyvault/pom.xml @@ -6,11 +6,12 @@ the MIT License. See License.txt in the project root for license information. -- com.microsoft.azure azure-keyvault-parent - 1.1 + 1.1.1 ../pom.xml azure-keyvault + 1.1.1 jar Microsoft Azure SDK for Key Vault @@ -58,76 +59,151 @@ the MIT License. See License.txt in the project root for license information. -- - + + + com.microsoft.azure - azure - 1.3.0 - test + azure-keyvault-cryptography com.microsoft.azure - azure-client-runtime - [1.1.0,2.0.0) + azure-keyvault-webkey - + + + com.microsoft.azure - azure-client-authentication - [1.1.0,2.0.0) + azure-client-runtime - - com.microsoft.azure - azure-keyvault-cryptography - 1.1 + + + + com.microsoft.rest + client-runtime + + + + + com.fasterxml.jackson.core + jackson-databind - - com.microsoft.azure - azure-keyvault-core - 1.1 + + com.fasterxml.jackson.core + jackson-annotations - - com.microsoft.azure - azure-keyvault-webkey - 1.0.0 + + com.fasterxml.jackson.core + jackson-core - - - junit - junit + + + + commons-codec + commons-codec + + + com.google.guava + guava + + + org.apache.commons + commons-lang3 + + + joda-time + joda-time + 2.1 + + + com.squareup.retrofit2 + retrofit + 2.4.0 + + + com.squareup.okhttp3 + okhttp + 3.10.0 + + + com.squareup.okio + okio + 1.14.0 + + + io.reactivex + rxjava + + + + + + com.microsoft.azure + azure-mgmt-storage + 1.3.0 + test + + + com.microsoft.azure + azure-mgmt-graph-rbac + 1.3.0 test - + + com.microsoft.azure + azure-mgmt-resources + test + + com.microsoft.azure azure-mgmt-keyvault - 1.11.1 test + + + com.microsoft.azure + azure-keyvault + + - + com.microsoft.azure azure-mgmt-resources 1.3.1-SNAPSHOT test-jar test - + com.microsoft.azure adal4j test - - org.bouncycastle - bcprov-jdk15on - 1.54 - test + + com.microsoft.azure + azure-storage + 4.4.0 + test + + + + + com.google.code.gson + gson + 2.2.4 + test + + + com.microsoft.azure + azure-client-authentication + [1.1.0,2.0.0) + test - - - commons-io - commons-io - 2.6 + + junit + junit test - - + + + @@ -166,6 +242,16 @@ the MIT License. See License.txt in the project root for license information. -- 1.7 + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.0 + + + ${basedir}/azure-keyvault/target/azure-keyvault-${project.version}.jar + + + org.apache.maven.plugins maven-javadoc-plugin diff --git a/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/EnhancedKeyVaultTest.java b/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/EnhancedKeyVaultTest.java index 772446f..abfd063 100644 --- a/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/EnhancedKeyVaultTest.java +++ b/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/EnhancedKeyVaultTest.java @@ -55,7 +55,7 @@ public void unprotectRequestEmptyKeysTest() throws Exception{ @Test public void protectRequestTest() throws Exception{ - String expectedEncryptedRequestBody = new String(Base64.decodeBase64("eyJwcm90ZWN0ZWQiOiJleUpoYkdjaU9pSlNVekkxTmlJc0ltdHBaQ0k2SWpZME9UWTFaR05pTFRKbE5qUXROR0V5TkMxaVlXTXdMV1ExWWpjMFkySXhaamRqTkNJc0ltRjBJam9pVkc5clpXNGlMQ0owY3lJNk1Dd2ljQ0k2Ym5Wc2JDd2lkSGx3SWpvaVVHOVFJbjAiLCJwYXlsb2FkIjoiZXlKd2NtOTBaV04wWldRaU9pSmxlVXBvWWtkamFVOXBTbE5WTUVWMFZEQkdSbFZEU1hOSmJYUndXa05KTmtscVFYcE9iVVUxVGtSWmVFeFVWVEJOUkVWMFRrUk5NVTFwTVdsT1JGRXlURlJhYkZreVdUQmFSRWt5V2xSQk5GbFRTWE5KYlZaMVdYbEpOa2xyUlhoTmFtaEVVV3ROZEZOR1RYbE9WRmxwWmxFaUxDSmxibU55ZVhCMFpXUmZhMlY1SWpvaVlUSldOU0lzSW1sMklqb2lWa1ZXVkZaRVJYbE5lbEpWVWxaT1ZVMVVTWHBPUVNJc0ltTnBjR2hsY25SbGVIUWlPaUpsYmpGTGRYZ3pSSE40ZERNellqbEtaRlI2UzNweVEzcGhlVkpsWldoR2VqaGZiMVpoUzE5V1QwVnphMEpUV214a1N6WmFieTFsVDJGblNVaFNha3BKY1VacllXcDFWblYwU0ZkUFkwaE5jV0Z3UVdjMGJtaE9kV1kxYlhKcFIzbFVRbWgxYTJWNFUzWlZNeTFaY0dGMVF6RkhXbGhhUjI1dFp6SjFOazVZYVVaVWEwVlZUWEpNUVcwdE5GWkRiWEZtUlhRdFFtSjRZMXBIWVdKMVJtNXlWVGxIUlhWTk5sWmpSVFZvVUZSNWFGUjFZelZoYkU1S1NpMXBNMFpQTW05dFdGUm5iUzFuVXpSUVVYRTVaRjk0U0VaQlVrcHZRM2gxTVdkSFJVcHFZbG8xUlRkeVNGZ3dRak5yV2xKaE1uUlJabXBmV1d0MFFqVTFVbmMzWW1SVlIxZDNSa05wWlhaWE9GVmhjakpJYms1dVZrWnRhWFpmUWpFeGVsUnVhRVp4VTFkd2VtbFdVV1JRVmprNE0wMVRNR2N4U2sxYVdERktWbTlVTFcxMFJWODRMWGhxTlhOTVdVZFBkbmxGTm5JdFprUlRPRFZoUTFOUlNtRkRVMUJ0TkVWM1JIbGlOVVZNUVc5WGFXTjJWMFpsVWtVNFdVZG9jekIzWDFSYVdqZENPSFk0VUdKTE1uWnFiRW8wUlc1ME4yRm1kMHRKVkd0bVRrMTZUM1pyWWprM1JWVjRSVkZRWlVOSWFYZFVUbHBRY1dGalUwUktOMEpWV0d4cFlVcE9WSGRXUkhaSFEzVlVTVE0wZUhOdVNYUkhlVXREUldocFRXbDRVR3B2ZWpaSmRYcFBTMTk1V0RWWWNrbEZMVXRmVVVSdVFYcEhkVmhVTUdkWFRYWkZVSFZJWjJScVZYbDVWSFpJWDFOWGEwcDBVelZZUzJOZmFIZExRVGRpTTNsSVpUTm1lbGRTWDNCc05GZEhhbmgxWlZKbmNFd3dUSFpQV1doMWVqZERibE5hVlZFNVpHcHRiMUJCU0VkUlowbHFhWGM0YTA5S2FHNHRVbEZoVHpoRVlXdGtkMUJKVmxKc2RYSlBRbU5qU21kT2IybEhWR0pDY2pRM1VIQTNTVE5NWlZSb1YyNVJObmwwVGtWdk5YTktZVk5SWlU1aFUwODRPV3hQVWpGRVpIUk5SRTF6VDBWc1ZXZFNRbE5vUTJWWFZta3hNalJwTUdOZlUzbFVSV1l5UkRVeFpYVXRNbFY2V1MxSU4wVTJiWGREYmxWamEzVlBkRkE0Ums5NVJrUXpVM0YzWXpCSWRGZHhaMmhMUVdvNVEyMU1UVTQyVFRoSWRXVnhRbEpTVEVNaUxDSjBZV2NpT2lKMVFtTnhMVk13UTNOMlNVNTNOVnBvYlhkQlpXaEJJbjAiLCJzaWduYXR1cmUiOiJZNmt6eHpEN0JqZzlZellXeW1rT2NsakpDSGNtMlJLUlpSQjQyQ21IY3Zuc19fakVWd3pTZ2xRUDhadEZCMmxVZk5iZDVCS01OdHNZd3FpUkp6Q1l3Wk05SmRPX0w4VnJWdTVvOWFvTkNRbmRTc2w3S01hUUlFZXg0OFA3LVNIcHg0b3E5VUk4bG9XRVY5Vy16Z19EdjlZYmYta3BmT1NjOTBsNEJCaGZuQkFHa3RpU0FUbTl0NHEzaTVmSzdPSTlUNllwM1hQTndxMHVyakQyX1dlQ1ZXS0NfRnRVbUVJZjlENXc5NmhTajdnMVN5VjQ4WXBfcmJKMWpMUFhjQzJwaW5zNDJBb0czMzU4LXFqR1NPanc4T2hQdXZ3ajZsaFk1TUlEeGFSQ042VlZETzNZb01ra0YyMlU3Znh4VE1WdG54YVRXUWpkMEZrR3l4SzR3RkR3c0EifQ==")); + String expectedEncryptedRequestBody = new String(Base64.decodeBase64("eyJwcm90ZWN0ZWQiOiJleUpoYkdjaU9pSlNVekkxTmlJc0ltdHBaQ0k2SWpZME9UWTFaR05pTFRKbE5qUXROR0V5TkMxaVlXTXdMV1ExWWpjMFkySXhaamRqTkNJc0ltRjBJam9pVkc5clpXNGlMQ0owY3lJNk1Dd2ljQ0k2Ym5Wc2JDd2lkSGx3SWpvaVVHOVFJbjAiLCJwYXlsb2FkIjoiZXlKd2NtOTBaV04wWldRaU9pSmxlVXBvWWtkamFVOXBTbE5WTUVWMFZEQkdSbFZEU1hOSmJYUndXa05KTmtscVFYcE9iVVUxVGtSWmVFeFVWVEJOUkVWMFRrUk5NVTFwTVdsT1JGRXlURlJhYkZreVdUQmFSRWt5V2xSQk5GbFRTWE5KYlZaMVdYbEpOa2xyUlhoTmFtaEVVV3ROZEZOR1RYbE9WRmxwWmxFaUxDSmxibU55ZVhCMFpXUmZhMlY1SWpvaVlUSldOU0lzSW1sMklqb2lWa1ZXVkZaRVJYbE5lbEpWVWxaT1ZVMVVTWHBPUVNJc0ltTnBjR2hsY25SbGVIUWlPaUpsYmpGTGRYZ3pSSE40ZERNellqbEtaRlI2UzNweVEzcGhlVkpsWldoR2VqaGZiMVpoUzE5V1QwVnphMEpUV214a1N6WmFieTFsVDJGblNVaFNha3BKY1VacllXcDFWblYwU0ZkUFkwaE5jV0Z3UVdjMGJtaE9kV1kxYlhKcFIzbFVRbWgxYTJWNFUzWlZNeTFaY0dGMVF6RkhXbGhhUjI1dFp6SjFOazVZYVVaVWEwVlZUWEpNUVcwdE5GWkRiWEZtUlhRdFFtSjRZMXBIWVdKMVJtNXlWVGxIUlhWTk5sWmpSVFZvVUZSNWFGUjFZelZoYkU1S1NpMXBNMFpQTW05dFdGUm5iUzFuVXpSUVVYRTVaRjk0U0VaQlVrcHZRM2gxTVdkSFJVcHFZbG8xUlRkeVNGZ3dRak5yV2xKaE1uUlJabXBmV1d0MFFqVTFVbmMzWW1SVlIxZDNSa05wWlhaWE9GVmhjakpJYms1dVZrWnRhWFpmUWpFeGVsUnVhRVp4VTFkd2VtbFdVV1JRVmprNE0wMVRNR2N4U2sxYVdERktWbTlVTFcxMFJWODRMWGhxTlhOTVdVZFBkbmxGTm5JdFprUlRPRFZoUTFOUlNtRkRVMUJ0TkVWM1JIbGlOVVZNUVc5WGFXTjJWMFpsVWtVNFdVZG9jekIzWDFSYVdqZENPSFk0VUdKTE1uWnFiRW8wUlc1ME4yRm1kMHRKVkd0bVRrMTZUM1pyWWprM1JWVjRSVkZRWlVOSWFYZFVUbHBRY1dGalUwUktOMEpWV0d4cFlVcE9WSGRXUkhaSFEzVlVTVE0wZUhOdVNYUkhlVXREUldocFRXbDRVR3B2ZWpaSmRYcFBTMTk1V0RWWWNrbEZMVXRmVVVSdVFYcEhkVmhVTUdkWFRYWkZVSFZJWjJScVZYbDVWSFpJWDFOWGEwcDBVelZZUzJOZmFIZExRVGRpTTNsSVpUTm1lbGRTWDNCc05GZEhhbmgxWlZKbmNFd3dUSFpQV1doMWVqZERibE5hVlZFNVpHcHRiMUJCU0VkUlowbHFhWGM0YTA5S2FHNHRVbEZoVHpoRVlXdGtkMUJKVmxKc2RYSlBRbU5qU21kT2IybEhWR0pDY2pRM1VIQTNTVE5NWlZSb1YyNVJObmwwVGtWdk5YTktZVk5SWlU1aFUwODRPV3hQVWpGRVpIUk5SRTF6VDBWc1ZXZFNRbE5vUTJWWFZta3hNalJwTUdOZlUzbFVSV1l5UkRVeFpYVXRNbFY2V1MxSU4wVTJiWGREYmxWamEzVlBkRkE0Ums5NVJrUXpVM0YzWXpCSWRGZHhaMmRRTVc1MGRIUnZVVkpTU0hwTWJFTjZaazF4TTBOamNYVmtiV0UzWW1vMk5teEpablE0VkZoV1gxSnFTWFpHY0VORGQxRmhOR2gxZFdwR1JrZ3haRFpCSWl3aWRHRm5Jam9pWjJKU05WbEtkWGwwTkZZMWRsUk9lazFRV0RScWR5SjkiLCJzaWduYXR1cmUiOiJtdVhWcmN1TjUzanhYY0xmc0Q5MlF2YW43cm41UGhHZW9qdTJaSGtEX3E3YlpHVGU0R0NzRkZuNnRsdzRDTVhNcDZsQ3N6VmRyMkJadjVDeFZHbGFFMVluSUh2bkg2Y3JWMklFVERUMUhiZ3NjMHF4NUtGaHI2cklXUjhJdm91X001MGlFc2UzZDRyN19ZR3dxbDhyWFN6N2NPWXFHRE91bEZyY1FaZ2xwZU15TVdRS19nQXRJSjBlTUk3ZGk5ZG5fQ0pKLUhKUlNUWWJsNkF4czgzOFAtR3pfcV9HNXNtSldfVmN2bVRFVlhRNGliLWNjUlpxYklZNUxSYmpkZl9UaWJ0XzUwZndkT3h2OHZWY1MyQUlISHduWVM1bmhUSGFfZ1hvdmtSU1lJVEw2SXd0Q1Y0TzRuTm12cHFQcDNiLW5ndnl4a2VQbVgzRE1KZHp2aml4Y2cifQ==")); HttpMessageSecurity messagesecurity = getMessageSecurityWithKeys(); Request request = getRequest(); @@ -106,6 +106,7 @@ private Response getResponse(){ .request(getRequest()) .protocol(okhttp3.Protocol.HTTP_2) .code(200) + .message("OK") .build(); } diff --git a/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ManagedStorageAccountKeyTest.java b/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ITManagedStorageAccountKey.java similarity index 97% rename from azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ManagedStorageAccountKeyTest.java rename to azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ITManagedStorageAccountKey.java index cc09e30..e490104 100644 --- a/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ManagedStorageAccountKeyTest.java +++ b/azure-keyvault/src/test/java/com/microsoft/azure/keyvault/test/ITManagedStorageAccountKey.java @@ -1,516 +1,516 @@ -package com.microsoft.azure.keyvault.test; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.security.InvalidKeyException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.microsoft.aad.adal4j.AuthenticationContext; -import com.microsoft.aad.adal4j.AuthenticationResult; -import com.microsoft.azure.AzureEnvironment; -import com.microsoft.azure.AzureResponseBuilder; -import com.microsoft.azure.PagedList; -import com.microsoft.azure.credentials.UserTokenCredentials; -import com.microsoft.azure.keyvault.KeyVaultClient; -import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials; -import com.microsoft.azure.keyvault.models.DeletedStorageBundle; -import com.microsoft.azure.keyvault.models.SasDefinitionAttributes; -import com.microsoft.azure.keyvault.models.SasDefinitionBundle; -import com.microsoft.azure.keyvault.models.SasTokenType; -import com.microsoft.azure.keyvault.models.SecretBundle; -import com.microsoft.azure.keyvault.models.StorageAccountAttributes; -import com.microsoft.azure.keyvault.models.StorageAccountItem; -import com.microsoft.azure.keyvault.models.StorageBundle; -import com.microsoft.azure.management.graphrbac.RoleDefinition; -import com.microsoft.azure.management.graphrbac.implementation.GraphRbacManager; -import com.microsoft.azure.management.keyvault.Vault; -import com.microsoft.azure.management.keyvault.implementation.KeyVaultManager; -import com.microsoft.azure.management.resources.core.InterceptorManager; -import com.microsoft.azure.management.resources.core.TestBase; -import com.microsoft.azure.management.resources.fluentcore.arm.Region; -import com.microsoft.azure.management.resources.fluentcore.utils.ResourceManagerThrottlingInterceptor; -import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext; -import com.microsoft.azure.management.storage.StorageAccount; -import com.microsoft.azure.management.storage.implementation.StorageManager; -import com.microsoft.azure.serializer.AzureJacksonAdapter; -import com.microsoft.azure.storage.CloudStorageAccount; -import com.microsoft.azure.storage.SharedAccessAccountPermissions; -import com.microsoft.azure.storage.SharedAccessAccountPolicy; -import com.microsoft.azure.storage.SharedAccessAccountResourceType; -import com.microsoft.azure.storage.SharedAccessAccountService; -import com.microsoft.azure.storage.StorageCredentials; -import com.microsoft.azure.storage.StorageCredentialsAccountAndKey; -import com.microsoft.azure.storage.StorageException; -import com.microsoft.rest.LogLevel; -import com.microsoft.rest.RestClient; -import com.microsoft.rest.credentials.ServiceClientCredentials; -import com.microsoft.rest.interceptors.LoggingInterceptor; - -import okhttp3.Interceptor; -import resources.MockUserTokenCredentials; - -public class ManagedStorageAccountKeyTest { - - private static TestBase.TestMode testMode = null; - - KeyVaultManager keyVaultManager; - StorageManager storageManager; - GraphRbacManager graphRbacManager; - protected static KeyVaultClient keyVaultClient; - - protected static final Region VAULT_REGION = Region.US_WEST_CENTRAL; - - // This is the default client ID that works across all Azure services - leave in - // for testing. - protected static final String CLIENT_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; - - protected static String MSAK_USER; - protected static String MSAK_PASSWORD; - protected static String RESOURCE_GROUP; - protected static String TENANT_ID; - protected static String SUBSCRIPTION_ID; - protected static String MSAK_USER_OID; - protected static RoleDefinition KEY_VAULT_ROLE; - - protected InterceptorManager interceptorManager = null; - - protected final static String ZERO_SUBSCRIPTION = "00000000-0000-0000-0000-000000000000"; - protected final static String ZERO_TENANT = "00000000-0000-0000-0000-000000000000"; - protected final static String ZERO_OID = "00000000-0000-0000-0000-000000000000"; - protected final static String ZERO_RESOURCE_GROUP = "rg-0"; - private static final String PLAYBACK_URI_BASE = "http://localhost:"; - protected static String playbackUri = null; - - @Rule - public TestName testName = new TestName(); - - @BeforeClass - public static void beforeClass() throws IOException { - initTestMode(); - initPlaybackUri(); - } - - @Before - public void beforeTests() throws Exception { - printThreadInfo(String.format("%s: %s", "beforeTest", testName.getMethodName())); - - interceptorManager = InterceptorManager.create(testName.getMethodName(), testMode); - - ServiceClientCredentials keyVaultCredentials = createTestCredentials(); - - // Due to the nature of the services, we have to use User Authentication for testing - // You must use a user with 2FA disabled for this to work. - - - if (isRecordMode()) { - // This needs to be set for playback. - RESOURCE_GROUP = System.getenv("msak.resourceGroup"); - - // These need to be set for recording. - MSAK_USER = System.getenv("msak.user"); - MSAK_PASSWORD = System.getenv("msak.password"); - MSAK_USER_OID = System.getenv("msak.useroid"); - TENANT_ID = System.getenv("arm.tenantid"); - SUBSCRIPTION_ID = System.getenv("arm.subscriptionId"); - - UserTokenCredentials credentials = new UserTokenCredentials(CLIENT_ID, TENANT_ID, MSAK_USER, MSAK_PASSWORD, - AzureEnvironment.AZURE); - Interceptor interceptor = interceptorManager.initInterceptor(); - Interceptor loggingInterceptor = new LoggingInterceptor(LogLevel.BODY_AND_HEADERS); - - RestClient keyVaultRestClient = new RestClient.Builder().withBaseUrl("https://{vaultBaseUrl}") - .withSerializerAdapter(new AzureJacksonAdapter()) - .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(keyVaultCredentials) - .withLogLevel(LogLevel.NONE).withNetworkInterceptor(loggingInterceptor) - .withNetworkInterceptor(interceptor).withInterceptor(new ResourceManagerThrottlingInterceptor()) - .build(); - - keyVaultClient = new KeyVaultClient(keyVaultRestClient); - credentials.withDefaultSubscriptionId(SUBSCRIPTION_ID); - - RestClient restClient = new RestClient.Builder().withBaseUrl("https://management.azure.com") - .withSerializerAdapter(new AzureJacksonAdapter()) - .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(credentials) - .withLogLevel(LogLevel.NONE).withReadTimeout(3, TimeUnit.MINUTES) - .withNetworkInterceptor(loggingInterceptor).withNetworkInterceptor(interceptor) - .withInterceptor(new ResourceManagerThrottlingInterceptor()).build(); - - String defaultSubscription = credentials.defaultSubscriptionId(); - interceptorManager.addTextReplacementRule(defaultSubscription, ZERO_SUBSCRIPTION); - interceptorManager.addTextReplacementRule(credentials.domain(), ZERO_TENANT); - interceptorManager.addTextReplacementRule("https://management.azure.com/", playbackUri + "/"); - interceptorManager.addTextReplacementRule("https://graph.windows.net/", playbackUri + "/"); - interceptorManager.addTextReplacementRule("vault.azure.net/", "vault.azure.net"); - interceptorManager.addTextReplacementRule(MSAK_USER_OID, ZERO_OID); - interceptorManager.addTextReplacementRule(RESOURCE_GROUP, ZERO_RESOURCE_GROUP); - initializeClients(restClient, defaultSubscription, credentials.domain()); - } else { - RESOURCE_GROUP = ZERO_RESOURCE_GROUP; - MSAK_USER_OID = ZERO_OID; - UserTokenCredentials credentials = new MockUserTokenCredentials(); - keyVaultClient = new KeyVaultClient(buildPlaybackRestClient(keyVaultCredentials, playbackUri )); - RestClient restClient = buildPlaybackRestClient(credentials, playbackUri ); - - initializeClients(restClient, ZERO_SUBSCRIPTION, ZERO_TENANT); - } - - KEY_VAULT_ROLE = getKeyVaultRole(); - - } - - @Test - public void testCrudOperationsForManagedStorageAccountKey() { - - String msak_UUID = null; - String storageAccountName = null; - String vaultName = null; - String fileName = System.getProperty("user.dir") - + "/src/test/java/com/microsoft/azure/keyvault/test/crudNames.json"; - - if (isRecordMode()) { - - msak_UUID = UUID.randomUUID().toString(); - storageAccountName = SdkContext.randomResourceName("sa", 15); - vaultName = SdkContext.randomResourceName("vault", 15); - JsonObject obj = new JsonObject(); - obj.addProperty("roleDefUUID", msak_UUID); - obj.addProperty("storageAccountName", storageAccountName); - obj.addProperty("vaultName", vaultName); - try { - BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName)); - fileWriter.write(obj.toString()); - fileWriter.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - } else { - try { - Gson gson = new Gson(); - BufferedReader br = new BufferedReader(new FileReader(fileName)); - JsonObject obj = gson.fromJson(br, JsonObject.class); - msak_UUID = obj.get("roleDefUUID").getAsString(); - storageAccountName = obj.get("storageAccountName").getAsString(); - vaultName = obj.get("vaultName").getAsString(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - StorageAccount storageAccount = initStorageAccount(storageAccountName, msak_UUID); - - Vault vault = initVault(vaultName); - - String vaultUri = vault.vaultUri(); - - String activeKeyName = "key1"; - String regenerationPeriod = "P30D"; - StorageAccountAttributes attributes = new StorageAccountAttributes().withEnabled(true); - keyVaultClient.setStorageAccount(vaultUri, storageAccount.name(), storageAccount.id(), activeKeyName, true, - regenerationPeriod, attributes, null); - List msaList = keyVaultClient.getStorageAccounts(vaultUri); - Assert.assertEquals(1, msaList.size()); - - StorageBundle bundle = keyVaultClient.getStorageAccount(vaultUri, storageAccount.name()); - Assert.assertTrue(bundle.id().contains(storageAccount.name())); - Assert.assertEquals(activeKeyName, bundle.activeKeyName()); - Assert.assertEquals(regenerationPeriod, bundle.regenerationPeriod()); - Assert.assertTrue(bundle.autoRegenerateKey()); - - String newActiveKeyName = "key2"; - String newRegenerationPeriod = "P60D"; - keyVaultClient.updateStorageAccount(vaultUri, storageAccount.name(), newActiveKeyName, false, - newRegenerationPeriod, null, null); - StorageBundle updatedBundle = keyVaultClient.getStorageAccount(vaultUri, storageAccount.name()); - Assert.assertTrue(updatedBundle.id().contains(storageAccount.name())); - Assert.assertEquals(newActiveKeyName, updatedBundle.activeKeyName()); - Assert.assertEquals(newRegenerationPeriod, updatedBundle.regenerationPeriod()); - Assert.assertFalse(updatedBundle.autoRegenerateKey()); - - DeletedStorageBundle deletedBundle = keyVaultClient.deleteStorageAccount(vaultUri, storageAccount.name()); - Assert.assertTrue(deletedBundle.id().contains(storageAccount.name())); - } - - @Test - public void testSetAndGetSasDefinitionForManagedStorageAccountKey() - throws ParseException, URISyntaxException, StorageException, InvalidKeyException, IOException { - - String sas_UUID = null; - String storageAccountName = null; - String vaultName = null; - String fileName = System.getProperty("user.dir") - + "/src/test/java/com/microsoft/azure/keyvault/test/sasNames.json"; - - // Write names to file to save it - if (isRecordMode()) { - sas_UUID = UUID.randomUUID().toString(); - storageAccountName = SdkContext.randomResourceName("sa", 15); - vaultName = SdkContext.randomResourceName("vault", 15); - JsonObject obj = new JsonObject(); - obj.addProperty("roleDefUUID", sas_UUID); - obj.addProperty("storageAccountName", storageAccountName); - obj.addProperty("vaultName", vaultName); - - try { - BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName)); - fileWriter.write(obj.toString()); - fileWriter.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - } else { - - try { - Gson gson = new Gson(); - BufferedReader br = new BufferedReader(new FileReader(fileName)); - JsonObject obj = gson.fromJson(br, JsonObject.class); - sas_UUID = obj.get("roleDefUUID").getAsString(); - storageAccountName = obj.get("storageAccountName").getAsString(); - vaultName = obj.get("vaultName").getAsString(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - StorageAccount storageAccount = initStorageAccount(storageAccountName, sas_UUID); - Vault vault = initVault(vaultName); - String vaultUri = vault.vaultUri(); - - final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd-MM-yyyy"); - - String activeKeyName = "key1"; - String regenerationPeriod = "P30D"; - StorageAccountAttributes storageAttributes = new StorageAccountAttributes().withEnabled(true); - keyVaultClient.setStorageAccount(vaultUri, storageAccount.name(), storageAccount.id(), activeKeyName, true, - regenerationPeriod, storageAttributes, null); - - StorageCredentials sas = new StorageCredentialsAccountAndKey(storageAccount.name(), "00000001"); - // Note that the key passed in is just a dummy key such that we can generate the - // correct signature for the template. - CloudStorageAccount account = new CloudStorageAccount(sas); - - // Create a new policy - SharedAccessAccountPolicy sharedAccessAccountPolicy = new SharedAccessAccountPolicy(); - sharedAccessAccountPolicy.setServices(EnumSet.of(SharedAccessAccountService.BLOB, - SharedAccessAccountService.FILE, SharedAccessAccountService.QUEUE, SharedAccessAccountService.TABLE)); - sharedAccessAccountPolicy - .setPermissions(EnumSet.of(SharedAccessAccountPermissions.ADD, SharedAccessAccountPermissions.CREATE, - SharedAccessAccountPermissions.DELETE, SharedAccessAccountPermissions.LIST, - SharedAccessAccountPermissions.PROCESS_MESSAGES, SharedAccessAccountPermissions.READ, - SharedAccessAccountPermissions.UPDATE, SharedAccessAccountPermissions.WRITE)); - sharedAccessAccountPolicy.setResourceTypes(EnumSet.of(SharedAccessAccountResourceType.CONTAINER, - SharedAccessAccountResourceType.OBJECT, SharedAccessAccountResourceType.SERVICE)); // all resources - // service, - // container, object - sharedAccessAccountPolicy.setSharedAccessExpiryTime(FORMATTER.parse("01-01-2020")); - - // Generate a signature based off of the policy and account. - String sasSignature = account.generateSharedAccessSignature(sharedAccessAccountPolicy); - - // Currently the key vault service cannot process the sr signature, so this - // needs to be manually removed. - sasSignature = sasSignature.substring(0, sasSignature.lastIndexOf("&")); - - String sasDefinitionName = "acctall"; - // Use the created template to create a sas definition in the vault. - SasDefinitionAttributes attributes = new SasDefinitionAttributes().withEnabled(true); - SasDefinitionBundle sasDefinition = keyVaultClient.setSasDefinition(vaultUri, storageAccount.name(), - sasDefinitionName, sasSignature, SasTokenType.ACCOUNT, "PT2H", attributes, null); - - // Grab the secretName from the full secretId (the trailing characters after the - // last slash) - String sasSecretId = sasDefinition.secretId(); - String secretName = sasSecretId.substring(sasSecretId.lastIndexOf("/")).substring(1); - SecretBundle acctSasToken = keyVaultClient.getSecret(vaultUri, secretName); - Assert.assertNotNull(acctSasToken); - - SasDefinitionBundle retrievedSasDefinition = keyVaultClient.getSasDefinition(vaultUri, storageAccount.name(), - sasDefinitionName); - Assert.assertEquals(sasDefinition.id(), retrievedSasDefinition.id()); - Assert.assertEquals(sasDefinition.secretId(), retrievedSasDefinition.secretId()); - Assert.assertEquals(sasDefinition.validityPeriod(), retrievedSasDefinition.validityPeriod()); - } - - @After - public void afterMethod() throws IOException { - interceptorManager.finalizeInterceptor(); - } - - // Creates a new storage account for use with this account - private StorageAccount initStorageAccount(final String storageAccountName, final String roleAccountUUID) { - StorageAccount storageAccount = storageManager.storageAccounts().define(storageAccountName) - .withRegion(VAULT_REGION).withExistingResourceGroup(RESOURCE_GROUP).create(); - - graphRbacManager.roleAssignments().define(roleAccountUUID).forObjectId("93c27d83-f79b-4cb2-8dd4-4aa716542e74") - .withRoleDefinition(KEY_VAULT_ROLE.id()).withScope(storageAccount.id()).create(); - - return storageAccount; - } - - private Vault initVault(final String VAULT_NAME) { - - Vault vault = keyVaultManager.vaults().define(VAULT_NAME).withRegion(VAULT_REGION) - .withExistingResourceGroup(RESOURCE_GROUP).defineAccessPolicy() - .forObjectId(MSAK_USER_OID).allowSecretAllPermissions() - .allowStorageAllPermissions().attach().withDeploymentDisabled().create(); - return vault; - } - - protected void initializeClients(RestClient restClient, String defaultSubscription, String domain) - throws IOException { - - keyVaultManager = KeyVaultManager.authenticate(restClient, domain, defaultSubscription); - - storageManager = StorageManager.authenticate(restClient, defaultSubscription); - - graphRbacManager = GraphRbacManager.authenticate(restClient, domain); - - } - - // User Auth flow for acquiring token - private static AuthenticationResult getAccessToken(String authorization, String resource) throws Exception { - AuthenticationResult result = null; - ExecutorService service = null; - try { - service = Executors.newFixedThreadPool(1); - AuthenticationContext context = new AuthenticationContext(authorization, false, service); - Future future = null; - future = context.acquireToken(resource, CLIENT_ID, MSAK_USER, MSAK_PASSWORD, null); - result = future.get(); - } finally { - service.shutdown(); - } - - if (result == null) { - throw new RuntimeException("authentication result was null"); - } - return result; - } - - // Creates serviceClientCredentials based on the credentials passed in. - private static ServiceClientCredentials createTestCredentials() throws Exception { - return new KeyVaultCredentials() { - - @Override - public String doAuthenticate(String authorization, String resource, String scope) { - try { - - if (isRecordMode()) { - AuthenticationResult authResult = getAccessToken(authorization, resource); - return authResult.getAccessToken(); - } else { - return ""; - } - - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - }; - } - - private static void initPlaybackUri() throws IOException { - if (isPlaybackMode()) { - Properties mavenProps = new Properties(); - InputStream in = TestBase.class.getResourceAsStream("/maven.properties"); - if (in == null) { - throw new IOException( - "The file \"maven.properties\" has not been generated yet. Please execute \"mvn compile\" to generate the file."); - } - mavenProps.load(in); - String port = mavenProps.getProperty("playbackServerPort"); - // 11080 and 11081 needs to be in sync with values in jetty.xml file - playbackUri = PLAYBACK_URI_BASE + port; - } else { - playbackUri = PLAYBACK_URI_BASE + "1234"; - } - } - - private static void initTestMode() throws IOException { - String azureTestMode = System.getenv("AZURE_TEST_MODE"); - if (azureTestMode != null) { - if (azureTestMode.equalsIgnoreCase("Record")) { - testMode = TestBase.TestMode.RECORD; - } else if (azureTestMode.equalsIgnoreCase("Playback")) { - testMode = TestBase.TestMode.PLAYBACK; - } else { - throw new IOException("Unknown AZURE_TEST_MODE: " + azureTestMode); - } - } else { - testMode = TestBase.TestMode.PLAYBACK; - } - } - - public static boolean isPlaybackMode() { - if (testMode == null) - try { - initTestMode(); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Can't init test mode."); - } - return testMode == TestBase.TestMode.PLAYBACK; - } - - public static boolean isRecordMode() { - return !isPlaybackMode(); - } - - private static void printThreadInfo(String what) { - long id = Thread.currentThread().getId(); - String name = Thread.currentThread().getName(); - System.out.println(String.format("\n***\n*** [%s:%s] - %s\n***\n", name, id, what)); - } - - // find the role definition for "Storage Account Key Operator Service Role" - private RoleDefinition getKeyVaultRole() { - RoleDefinition keyVaultRole = null; - PagedList roleDefinitions = graphRbacManager.roleDefinitions().listByScope("\\"); - Iterator roleDefs = roleDefinitions.iterator(); - while (roleDefs.hasNext()) { - RoleDefinition definition = roleDefs.next(); - if (definition.roleName().equals("Storage Account Key Operator Service Role")) { - keyVaultRole = definition; - break; - } - } - return keyVaultRole; - } - - protected RestClient buildPlaybackRestClient(ServiceClientCredentials credentials, String baseUrl) - throws IOException { - return new RestClient.Builder().withBaseUrl(baseUrl) - .withSerializerAdapter(new AzureJacksonAdapter()) - .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(credentials) - .withLogLevel(LogLevel.NONE).withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS)) - .withNetworkInterceptor(interceptorManager.initInterceptor()) - .withInterceptor(new ResourceManagerThrottlingInterceptor()).build(); - } -} +package com.microsoft.azure.keyvault.test; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.security.InvalidKeyException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.microsoft.aad.adal4j.AuthenticationContext; +import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.azure.AzureEnvironment; +import com.microsoft.azure.AzureResponseBuilder; +import com.microsoft.azure.PagedList; +import com.microsoft.azure.credentials.UserTokenCredentials; +import com.microsoft.azure.keyvault.KeyVaultClient; +import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials; +import com.microsoft.azure.keyvault.models.DeletedStorageBundle; +import com.microsoft.azure.keyvault.models.SasDefinitionAttributes; +import com.microsoft.azure.keyvault.models.SasDefinitionBundle; +import com.microsoft.azure.keyvault.models.SasTokenType; +import com.microsoft.azure.keyvault.models.SecretBundle; +import com.microsoft.azure.keyvault.models.StorageAccountAttributes; +import com.microsoft.azure.keyvault.models.StorageAccountItem; +import com.microsoft.azure.keyvault.models.StorageBundle; +import com.microsoft.azure.management.graphrbac.RoleDefinition; +import com.microsoft.azure.management.graphrbac.implementation.GraphRbacManager; +import com.microsoft.azure.management.keyvault.Vault; +import com.microsoft.azure.management.keyvault.implementation.KeyVaultManager; +import com.microsoft.azure.management.resources.core.InterceptorManager; +import com.microsoft.azure.management.resources.core.TestBase; +import com.microsoft.azure.management.resources.fluentcore.arm.Region; +import com.microsoft.azure.management.resources.fluentcore.utils.ResourceManagerThrottlingInterceptor; +import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext; +import com.microsoft.azure.management.storage.StorageAccount; +import com.microsoft.azure.management.storage.implementation.StorageManager; +import com.microsoft.azure.serializer.AzureJacksonAdapter; +import com.microsoft.azure.storage.CloudStorageAccount; +import com.microsoft.azure.storage.SharedAccessAccountPermissions; +import com.microsoft.azure.storage.SharedAccessAccountPolicy; +import com.microsoft.azure.storage.SharedAccessAccountResourceType; +import com.microsoft.azure.storage.SharedAccessAccountService; +import com.microsoft.azure.storage.StorageCredentials; +import com.microsoft.azure.storage.StorageCredentialsAccountAndKey; +import com.microsoft.azure.storage.StorageException; +import com.microsoft.rest.LogLevel; +import com.microsoft.rest.RestClient; +import com.microsoft.rest.credentials.ServiceClientCredentials; +import com.microsoft.rest.interceptors.LoggingInterceptor; + +import okhttp3.Interceptor; +import resources.MockUserTokenCredentials; + +public class ITManagedStorageAccountKey { + + private static TestBase.TestMode testMode = null; + + KeyVaultManager keyVaultManager; + StorageManager storageManager; + GraphRbacManager graphRbacManager; + protected static KeyVaultClient keyVaultClient; + + protected static final Region VAULT_REGION = Region.US_WEST_CENTRAL; + + // This is the default client ID that works across all Azure services - leave in + // for testing. + protected static final String CLIENT_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; + + protected static String MSAK_USER; + protected static String MSAK_PASSWORD; + protected static String RESOURCE_GROUP; + protected static String TENANT_ID; + protected static String SUBSCRIPTION_ID; + protected static String MSAK_USER_OID; + protected static RoleDefinition KEY_VAULT_ROLE; + + protected InterceptorManager interceptorManager = null; + + protected final static String ZERO_SUBSCRIPTION = "00000000-0000-0000-0000-000000000000"; + protected final static String ZERO_TENANT = "00000000-0000-0000-0000-000000000000"; + protected final static String ZERO_OID = "00000000-0000-0000-0000-000000000000"; + protected final static String ZERO_RESOURCE_GROUP = "rg-0"; + private static final String PLAYBACK_URI_BASE = "http://localhost:"; + protected static String playbackUri = null; + + @Rule + public TestName testName = new TestName(); + + @BeforeClass + public static void beforeClass() throws IOException { + initTestMode(); + initPlaybackUri(); + } + + @Before + public void beforeTests() throws Exception { + printThreadInfo(String.format("%s: %s", "beforeTest", testName.getMethodName())); + + interceptorManager = InterceptorManager.create(testName.getMethodName(), testMode); + + ServiceClientCredentials keyVaultCredentials = createTestCredentials(); + + // Due to the nature of the services, we have to use User Authentication for testing + // You must use a user with 2FA disabled for this to work. + + + if (isRecordMode()) { + // This needs to be set for playback. + RESOURCE_GROUP = System.getenv("msak.resourceGroup"); + + // These need to be set for recording. + MSAK_USER = System.getenv("msak.user"); + MSAK_PASSWORD = System.getenv("msak.password"); + MSAK_USER_OID = System.getenv("msak.useroid"); + TENANT_ID = System.getenv("arm.tenantid"); + SUBSCRIPTION_ID = System.getenv("arm.subscriptionId"); + + UserTokenCredentials credentials = new UserTokenCredentials(CLIENT_ID, TENANT_ID, MSAK_USER, MSAK_PASSWORD, + AzureEnvironment.AZURE); + Interceptor interceptor = interceptorManager.initInterceptor(); + Interceptor loggingInterceptor = new LoggingInterceptor(LogLevel.BODY_AND_HEADERS); + + RestClient keyVaultRestClient = new RestClient.Builder().withBaseUrl("https://{vaultBaseUrl}") + .withSerializerAdapter(new AzureJacksonAdapter()) + .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(keyVaultCredentials) + .withLogLevel(LogLevel.NONE).withNetworkInterceptor(loggingInterceptor) + .withNetworkInterceptor(interceptor).withInterceptor(new ResourceManagerThrottlingInterceptor()) + .build(); + + keyVaultClient = new KeyVaultClient(keyVaultRestClient); + credentials.withDefaultSubscriptionId(SUBSCRIPTION_ID); + + RestClient restClient = new RestClient.Builder().withBaseUrl("https://management.azure.com") + .withSerializerAdapter(new AzureJacksonAdapter()) + .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(credentials) + .withLogLevel(LogLevel.NONE).withReadTimeout(3, TimeUnit.MINUTES) + .withNetworkInterceptor(loggingInterceptor).withNetworkInterceptor(interceptor) + .withInterceptor(new ResourceManagerThrottlingInterceptor()).build(); + + String defaultSubscription = credentials.defaultSubscriptionId(); + interceptorManager.addTextReplacementRule(defaultSubscription, ZERO_SUBSCRIPTION); + interceptorManager.addTextReplacementRule(credentials.domain(), ZERO_TENANT); + interceptorManager.addTextReplacementRule("https://management.azure.com/", playbackUri + "/"); + interceptorManager.addTextReplacementRule("https://graph.windows.net/", playbackUri + "/"); + interceptorManager.addTextReplacementRule("vault.azure.net/", "vault.azure.net"); + interceptorManager.addTextReplacementRule(MSAK_USER_OID, ZERO_OID); + interceptorManager.addTextReplacementRule(RESOURCE_GROUP, ZERO_RESOURCE_GROUP); + initializeClients(restClient, defaultSubscription, credentials.domain()); + } else { + RESOURCE_GROUP = ZERO_RESOURCE_GROUP; + MSAK_USER_OID = ZERO_OID; + UserTokenCredentials credentials = new MockUserTokenCredentials(); + keyVaultClient = new KeyVaultClient(buildPlaybackRestClient(keyVaultCredentials, playbackUri )); + RestClient restClient = buildPlaybackRestClient(credentials, playbackUri ); + + initializeClients(restClient, ZERO_SUBSCRIPTION, ZERO_TENANT); + } + + KEY_VAULT_ROLE = getKeyVaultRole(); + + } + + @Test + public void testCrudOperationsForManagedStorageAccountKey() { + + String msak_UUID = null; + String storageAccountName = null; + String vaultName = null; + String fileName = System.getProperty("user.dir") + + "/src/test/java/com/microsoft/azure/keyvault/test/crudNames.json"; + + if (isRecordMode()) { + + msak_UUID = UUID.randomUUID().toString(); + storageAccountName = SdkContext.randomResourceName("sa", 15); + vaultName = SdkContext.randomResourceName("vault", 15); + JsonObject obj = new JsonObject(); + obj.addProperty("roleDefUUID", msak_UUID); + obj.addProperty("storageAccountName", storageAccountName); + obj.addProperty("vaultName", vaultName); + try { + BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName)); + fileWriter.write(obj.toString()); + fileWriter.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + try { + Gson gson = new Gson(); + BufferedReader br = new BufferedReader(new FileReader(fileName)); + JsonObject obj = gson.fromJson(br, JsonObject.class); + msak_UUID = obj.get("roleDefUUID").getAsString(); + storageAccountName = obj.get("storageAccountName").getAsString(); + vaultName = obj.get("vaultName").getAsString(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + StorageAccount storageAccount = initStorageAccount(storageAccountName, msak_UUID); + + Vault vault = initVault(vaultName); + + String vaultUri = vault.vaultUri(); + + String activeKeyName = "key1"; + String regenerationPeriod = "P30D"; + StorageAccountAttributes attributes = new StorageAccountAttributes().withEnabled(true); + keyVaultClient.setStorageAccount(vaultUri, storageAccount.name(), storageAccount.id(), activeKeyName, true, + regenerationPeriod, attributes, null); + List msaList = keyVaultClient.getStorageAccounts(vaultUri); + Assert.assertEquals(1, msaList.size()); + + StorageBundle bundle = keyVaultClient.getStorageAccount(vaultUri, storageAccount.name()); + Assert.assertTrue(bundle.id().contains(storageAccount.name())); + Assert.assertEquals(activeKeyName, bundle.activeKeyName()); + Assert.assertEquals(regenerationPeriod, bundle.regenerationPeriod()); + Assert.assertTrue(bundle.autoRegenerateKey()); + + String newActiveKeyName = "key2"; + String newRegenerationPeriod = "P60D"; + keyVaultClient.updateStorageAccount(vaultUri, storageAccount.name(), newActiveKeyName, false, + newRegenerationPeriod, null, null); + StorageBundle updatedBundle = keyVaultClient.getStorageAccount(vaultUri, storageAccount.name()); + Assert.assertTrue(updatedBundle.id().contains(storageAccount.name())); + Assert.assertEquals(newActiveKeyName, updatedBundle.activeKeyName()); + Assert.assertEquals(newRegenerationPeriod, updatedBundle.regenerationPeriod()); + Assert.assertFalse(updatedBundle.autoRegenerateKey()); + + DeletedStorageBundle deletedBundle = keyVaultClient.deleteStorageAccount(vaultUri, storageAccount.name()); + Assert.assertTrue(deletedBundle.id().contains(storageAccount.name())); + } + + @Test + public void testSetAndGetSasDefinitionForManagedStorageAccountKey() + throws ParseException, URISyntaxException, StorageException, InvalidKeyException, IOException { + + String sas_UUID = null; + String storageAccountName = null; + String vaultName = null; + String fileName = System.getProperty("user.dir") + + "/src/test/java/com/microsoft/azure/keyvault/test/sasNames.json"; + + // Write names to file to save it + if (isRecordMode()) { + sas_UUID = UUID.randomUUID().toString(); + storageAccountName = SdkContext.randomResourceName("sa", 15); + vaultName = SdkContext.randomResourceName("vault", 15); + JsonObject obj = new JsonObject(); + obj.addProperty("roleDefUUID", sas_UUID); + obj.addProperty("storageAccountName", storageAccountName); + obj.addProperty("vaultName", vaultName); + + try { + BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName)); + fileWriter.write(obj.toString()); + fileWriter.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + + try { + Gson gson = new Gson(); + BufferedReader br = new BufferedReader(new FileReader(fileName)); + JsonObject obj = gson.fromJson(br, JsonObject.class); + sas_UUID = obj.get("roleDefUUID").getAsString(); + storageAccountName = obj.get("storageAccountName").getAsString(); + vaultName = obj.get("vaultName").getAsString(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + StorageAccount storageAccount = initStorageAccount(storageAccountName, sas_UUID); + Vault vault = initVault(vaultName); + String vaultUri = vault.vaultUri(); + + final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd-MM-yyyy"); + + String activeKeyName = "key1"; + String regenerationPeriod = "P30D"; + StorageAccountAttributes storageAttributes = new StorageAccountAttributes().withEnabled(true); + keyVaultClient.setStorageAccount(vaultUri, storageAccount.name(), storageAccount.id(), activeKeyName, true, + regenerationPeriod, storageAttributes, null); + + StorageCredentials sas = new StorageCredentialsAccountAndKey(storageAccount.name(), "00000001"); + // Note that the key passed in is just a dummy key such that we can generate the + // correct signature for the template. + CloudStorageAccount account = new CloudStorageAccount(sas); + + // Create a new policy + SharedAccessAccountPolicy sharedAccessAccountPolicy = new SharedAccessAccountPolicy(); + sharedAccessAccountPolicy.setServices(EnumSet.of(SharedAccessAccountService.BLOB, + SharedAccessAccountService.FILE, SharedAccessAccountService.QUEUE, SharedAccessAccountService.TABLE)); + sharedAccessAccountPolicy + .setPermissions(EnumSet.of(SharedAccessAccountPermissions.ADD, SharedAccessAccountPermissions.CREATE, + SharedAccessAccountPermissions.DELETE, SharedAccessAccountPermissions.LIST, + SharedAccessAccountPermissions.PROCESS_MESSAGES, SharedAccessAccountPermissions.READ, + SharedAccessAccountPermissions.UPDATE, SharedAccessAccountPermissions.WRITE)); + sharedAccessAccountPolicy.setResourceTypes(EnumSet.of(SharedAccessAccountResourceType.CONTAINER, + SharedAccessAccountResourceType.OBJECT, SharedAccessAccountResourceType.SERVICE)); // all resources + // service, + // container, object + sharedAccessAccountPolicy.setSharedAccessExpiryTime(FORMATTER.parse("01-01-2020")); + + // Generate a signature based off of the policy and account. + String sasSignature = account.generateSharedAccessSignature(sharedAccessAccountPolicy); + + // Currently the key vault service cannot process the sr signature, so this + // needs to be manually removed. + sasSignature = sasSignature.substring(0, sasSignature.lastIndexOf("&")); + + String sasDefinitionName = "acctall"; + // Use the created template to create a sas definition in the vault. + SasDefinitionAttributes attributes = new SasDefinitionAttributes().withEnabled(true); + SasDefinitionBundle sasDefinition = keyVaultClient.setSasDefinition(vaultUri, storageAccount.name(), + sasDefinitionName, sasSignature, SasTokenType.ACCOUNT, "PT2H", attributes, null); + + // Grab the secretName from the full secretId (the trailing characters after the + // last slash) + String sasSecretId = sasDefinition.secretId(); + String secretName = sasSecretId.substring(sasSecretId.lastIndexOf("/")).substring(1); + SecretBundle acctSasToken = keyVaultClient.getSecret(vaultUri, secretName); + Assert.assertNotNull(acctSasToken); + + SasDefinitionBundle retrievedSasDefinition = keyVaultClient.getSasDefinition(vaultUri, storageAccount.name(), + sasDefinitionName); + Assert.assertEquals(sasDefinition.id(), retrievedSasDefinition.id()); + Assert.assertEquals(sasDefinition.secretId(), retrievedSasDefinition.secretId()); + Assert.assertEquals(sasDefinition.validityPeriod(), retrievedSasDefinition.validityPeriod()); + } + + @After + public void afterMethod() throws IOException { + interceptorManager.finalizeInterceptor(); + } + + // Creates a new storage account for use with this account + private StorageAccount initStorageAccount(final String storageAccountName, final String roleAccountUUID) { + StorageAccount storageAccount = storageManager.storageAccounts().define(storageAccountName) + .withRegion(VAULT_REGION).withExistingResourceGroup(RESOURCE_GROUP).create(); + + graphRbacManager.roleAssignments().define(roleAccountUUID).forObjectId("93c27d83-f79b-4cb2-8dd4-4aa716542e74") + .withRoleDefinition(KEY_VAULT_ROLE.id()).withScope(storageAccount.id()).create(); + + return storageAccount; + } + + private Vault initVault(final String VAULT_NAME) { + + Vault vault = keyVaultManager.vaults().define(VAULT_NAME).withRegion(VAULT_REGION) + .withExistingResourceGroup(RESOURCE_GROUP).defineAccessPolicy() + .forObjectId(MSAK_USER_OID).allowSecretAllPermissions() + .allowStorageAllPermissions().attach().withDeploymentDisabled().create(); + return vault; + } + + protected void initializeClients(RestClient restClient, String defaultSubscription, String domain) + throws IOException { + + keyVaultManager = KeyVaultManager.authenticate(restClient, domain, defaultSubscription); + + storageManager = StorageManager.authenticate(restClient, defaultSubscription); + + graphRbacManager = GraphRbacManager.authenticate(restClient, domain); + + } + + // User Auth flow for acquiring token + private static AuthenticationResult getAccessToken(String authorization, String resource) throws Exception { + AuthenticationResult result = null; + ExecutorService service = null; + try { + service = Executors.newFixedThreadPool(1); + AuthenticationContext context = new AuthenticationContext(authorization, false, service); + Future future = null; + future = context.acquireToken(resource, CLIENT_ID, MSAK_USER, MSAK_PASSWORD, null); + result = future.get(); + } finally { + service.shutdown(); + } + + if (result == null) { + throw new RuntimeException("authentication result was null"); + } + return result; + } + + // Creates serviceClientCredentials based on the credentials passed in. + private static ServiceClientCredentials createTestCredentials() throws Exception { + return new KeyVaultCredentials() { + + @Override + public String doAuthenticate(String authorization, String resource, String scope) { + try { + + if (isRecordMode()) { + AuthenticationResult authResult = getAccessToken(authorization, resource); + return authResult.getAccessToken(); + } else { + return ""; + } + + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + }; + } + + private static void initPlaybackUri() throws IOException { + if (isPlaybackMode()) { + Properties mavenProps = new Properties(); + InputStream in = TestBase.class.getResourceAsStream("/maven.properties"); + if (in == null) { + throw new IOException( + "The file \"maven.properties\" has not been generated yet. Please execute \"mvn compile\" to generate the file."); + } + mavenProps.load(in); + String port = mavenProps.getProperty("playbackServerPort"); + // 11080 and 11081 needs to be in sync with values in jetty.xml file + playbackUri = PLAYBACK_URI_BASE + port; + } else { + playbackUri = PLAYBACK_URI_BASE + "1234"; + } + } + + private static void initTestMode() throws IOException { + String azureTestMode = System.getenv("AZURE_TEST_MODE"); + if (azureTestMode != null) { + if (azureTestMode.equalsIgnoreCase("Record")) { + testMode = TestBase.TestMode.RECORD; + } else if (azureTestMode.equalsIgnoreCase("Playback")) { + testMode = TestBase.TestMode.PLAYBACK; + } else { + throw new IOException("Unknown AZURE_TEST_MODE: " + azureTestMode); + } + } else { + testMode = TestBase.TestMode.PLAYBACK; + } + } + + public static boolean isPlaybackMode() { + if (testMode == null) + try { + initTestMode(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Can't init test mode."); + } + return testMode == TestBase.TestMode.PLAYBACK; + } + + public static boolean isRecordMode() { + return !isPlaybackMode(); + } + + private static void printThreadInfo(String what) { + long id = Thread.currentThread().getId(); + String name = Thread.currentThread().getName(); + System.out.println(String.format("\n***\n*** [%s:%s] - %s\n***\n", name, id, what)); + } + + // find the role definition for "Storage Account Key Operator Service Role" + private RoleDefinition getKeyVaultRole() { + RoleDefinition keyVaultRole = null; + PagedList roleDefinitions = graphRbacManager.roleDefinitions().listByScope("\\"); + Iterator roleDefs = roleDefinitions.iterator(); + while (roleDefs.hasNext()) { + RoleDefinition definition = roleDefs.next(); + if (definition.roleName().equals("Storage Account Key Operator Service Role")) { + keyVaultRole = definition; + break; + } + } + return keyVaultRole; + } + + protected RestClient buildPlaybackRestClient(ServiceClientCredentials credentials, String baseUrl) + throws IOException { + return new RestClient.Builder().withBaseUrl(baseUrl) + .withSerializerAdapter(new AzureJacksonAdapter()) + .withResponseBuilderFactory(new AzureResponseBuilder.Factory()).withCredentials(credentials) + .withLogLevel(LogLevel.NONE).withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS)) + .withNetworkInterceptor(interceptorManager.initInterceptor()) + .withInterceptor(new ResourceManagerThrottlingInterceptor()).build(); + } +} diff --git a/pom.xml b/pom.xml index 7192abe..ca2cd91 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 com.microsoft.azure - 1.1 + 1.1.1 azure-keyvault-parent pom @@ -31,6 +31,11 @@ UTF-8 + + + 2.9.6 + + playback 11080 11081 @@ -81,28 +86,87 @@ - - - com.microsoft.azure - azure-mgmt-keyvault - 1.11.1 - + + + com.microsoft.azure + azure-keyvault-webkey + 1.1.1 + + + com.microsoft.azure + azure-keyvault-cryptography + 1.1.1 + + + com.microsoft.azure + azure-keyvault-core + 1.1.1 + + + com.microsoft.azure + azure-keyvault + 1.1.1 + + + com.microsoft.azure + azure-keyvault-extensions + 1.1.1 + + + + + + com.microsoft.azure + azure-mgmt-keyvault + 1.11.1 + + + com.microsoft.azure + azure-client-runtime + 1.3.0 + + + com.microsoft.azure + azure-mgmt-resources + 1.3.0 + + + com.microsoft.azure + azure + 1.3.0 + + + + com.microsoft.rest + client-runtime + 1.6.1 + + + + com.fasterxml.jackson.core jackson-core - 2.7.2 + ${jackson.version} com.fasterxml.jackson.core jackson-databind - 2.7.2 + ${jackson.version} com.fasterxml.jackson.core jackson-annotations - 2.7.0 + ${jackson.version} + + + + org.apache.commons + commons-lang3 + 3.4 + commons-codec commons-codec @@ -113,16 +177,12 @@ rxjava 1.2.4 - - com.microsoft.azure - azure-client-runtime - 1.3.0 - com.google.guava guava 20.0 + junit @@ -136,7 +196,11 @@ 1.4.0 test - + + org.bouncycastle + bcprov-jdk15on + 1.59 + @@ -316,6 +380,19 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.0 + + + + integration-test + verify + + + + @@ -368,5 +445,6 @@ ./azure-keyvault-webkey ./azure-keyvault-cryptography ./azure-keyvault-extensions + ./azure-keyvault-complete