Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/keyvault/azure-security-keyvault-certificates/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
--add-exports com.azure.core/com.azure.core.implementation.http=ALL-UNNAMED

--add-opens com.azure.security.keyvault.certificates/com.azure.security.keyvault.certificates=ALL-UNNAMED
--add-opens com.azure.security.keyvault.certificates/com.azure.security.keyvault.certificates.models=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.azure.core.util.Configuration;
import com.azure.core.util.logging.ClientLogger;
import com.azure.security.keyvault.certificates.implementation.KeyVaultCredentialPolicy;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificateIdentifier;

import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -162,7 +163,9 @@ public CertificateAsyncClient buildAsyncClient() {
/**
* Sets the vault endpoint url to send HTTP requests to.
*
* @param vaultUrl The vault endpoint url is used as destination on Azure to send requests to.
* @param vaultUrl The vault endpoint url is used as destination on Azure to send requests to. If you have a
* certificate identifier, use {@link KeyVaultCertificateIdentifier#parse(String)} to parse it and obtain the
* {@code vaultUrl} and other information.
* @return the updated ServiceClientBuilder object.
* @throws IllegalArgumentException if {@code vaultUrl} is null or it cannot be parsed into a valid URL.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.certificates.models;

import com.azure.security.keyvault.certificates.CertificateAsyncClient;
import com.azure.security.keyvault.certificates.CertificateClient;

import java.net.MalformedURLException;
import java.net.URL;

/**
* Information about a {@link KeyVaultCertificate} parsed from the certificate URL. You can use this information when
* calling methods of {@link CertificateClient} or {@link CertificateAsyncClient}.
*/
public final class KeyVaultCertificateIdentifier {
private final String certificateId, vaultUrl, name, version;

private KeyVaultCertificateIdentifier(String certificateId, String vaultUrl, String name, String version) {
this.certificateId = certificateId;
this.vaultUrl = vaultUrl;
this.name = name;
this.version = version;
}

/**
* Gets the key identifier used to create this object
*
* @return The certificate identifier.
*/
public String getCertificateId() {
return certificateId;
}

/**
* Gets the URL of the Key Vault.
*
* @return The Key Vault URL.
*/
public String getVaultUrl() {
return vaultUrl;
}

/**
* Gets the name of the certificate.
*
* @return The certificate name.
*/
public String getName() {
return name;
}

/**
* Gets the optional version of the certificate.
*
* @return The certificate version.
*/
public String getVersion() {
return version;
}

/**
* Create a new {@link KeyVaultCertificateIdentifier} from a given certificate identifier.
*
* <p>Valid examples are:
*
* <ul>
* <li>https://{key-vault-name}.vault.azure.net/certificates/{certificate-name}</li>
* <li>https://{key-vault-name}.vault.azure.net/certificates/{certificate-name}/pending</li>
* <li>https://{key-vault-name}.vault.azure.net/certificates/{certificate-name}/{unique-version-id}</li>
* <li>https://{key-vault-name}.vault.azure.net/deletedcertificates/{deleted-certificate-name}</li>
* </ul>
*
* @param certificateId The certificate identifier to extract information from.
* @return a new instance of {@link KeyVaultCertificateIdentifier}.
* @throws IllegalArgumentException if the given identifier is {@code null}.
* @throws MalformedURLException if the given identifier is not a valid Key Vault Certificate identifier
*/
public static KeyVaultCertificateIdentifier parse(String certificateId) throws IllegalArgumentException, MalformedURLException {
if (certificateId == null) {
throw new IllegalArgumentException("certificateId cannot be null");
}

URL url = new URL(certificateId);
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
// We expect an identifier with either 2 or 3 path segments: collection + name [+ version]
String[] pathSegments = url.getPath().split("/");

if ((pathSegments.length != 3 && pathSegments.length != 4) // More or less segments in the URI than expected.
|| !"https".equals(url.getProtocol()) // Invalid protocol.
|| (!"certificates".equals(pathSegments[1]) && !"deletedcertificates".equals(pathSegments[1])) // Invalid collection.
|| ("deletedcertificates".equals(pathSegments[1]) && pathSegments.length == 4)) { // Deleted items do not include a version.
throw new IllegalArgumentException("certificateId is not a valid Key Vault Certificate identifier");
}

return new KeyVaultCertificateIdentifier(certificateId, url.getProtocol() + "://" + url.getHost(),
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
pathSegments[2], pathSegments.length == 4 ? pathSegments[3] : null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.certificates.models;

import org.junit.jupiter.api.Test;

import java.net.MalformedURLException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

class KeyVaultCertificateIdentifierTest {
@Test
void parseWithoutVersion() throws MalformedURLException {
String certificateId = "https://test-key-vault.vault.azure.net/certificates/test-certificate";
KeyVaultCertificateIdentifier keyVaultCertificateIdentifier =
KeyVaultCertificateIdentifier.parse(certificateId);

assertEquals(certificateId, keyVaultCertificateIdentifier.getCertificateId());
assertEquals("https://test-key-vault.vault.azure.net", keyVaultCertificateIdentifier.getVaultUrl());
assertEquals("test-certificate", keyVaultCertificateIdentifier.getName());
assertNull(keyVaultCertificateIdentifier.getVersion());
}

@Test
void parseWithVersion() throws MalformedURLException {
String certificateId = "https://test-key-vault.vault.azure.net/certificates/test-certificate/version";
KeyVaultCertificateIdentifier keyVaultCertificateIdentifier =
KeyVaultCertificateIdentifier.parse(certificateId);

assertEquals(certificateId, keyVaultCertificateIdentifier.getCertificateId());
assertEquals("https://test-key-vault.vault.azure.net", keyVaultCertificateIdentifier.getVaultUrl());
assertEquals("test-certificate", keyVaultCertificateIdentifier.getName());
assertEquals("version", keyVaultCertificateIdentifier.getVersion());
}

@Test
void parseForDeletedCertificate() throws MalformedURLException {
String certificateId = "https://test-key-vault.vault.azure.net/deletedcertificates/test-certificate";
KeyVaultCertificateIdentifier keyVaultCertificateIdentifier = KeyVaultCertificateIdentifier.parse(certificateId);

assertEquals(certificateId, keyVaultCertificateIdentifier.getCertificateId());
assertEquals("https://test-key-vault.vault.azure.net", keyVaultCertificateIdentifier.getVaultUrl());
assertEquals("test-certificate", keyVaultCertificateIdentifier.getName());
}

@Test
void parseInvalidIdentifierForDeletedCertificate() {
String certificateId = "https://test-key-vault.vault.azure.net/deletedcertificates/test-certificate/version";
Exception exception = assertThrows(IllegalArgumentException.class,
() -> KeyVaultCertificateIdentifier.parse(certificateId));

assertEquals("certificateId is not a valid Key Vault Certificate identifier", exception.getMessage());
}

@Test
void parseNullIdentifier() {
Exception exception = assertThrows(IllegalArgumentException.class,
() -> KeyVaultCertificateIdentifier.parse(null));

assertEquals("certificateId cannot be null", exception.getMessage());
}

@Test
void parseInvalidIdentifierWithWrongCollection() {
String certificateId = "https://test-key-vault.vault.azure.net/keys/test-certificate";
Exception exception = assertThrows(IllegalArgumentException.class,
() -> KeyVaultCertificateIdentifier.parse(certificateId));

assertEquals("certificateId is not a valid Key Vault Certificate identifier", exception.getMessage());
}

@Test
void parseInvalidIdentifierWithExtraSegment() {
String certificateId = "https://test-key-vault.vault.azure.net/keys/test-certificate/version/extra-segment";
Exception exception = assertThrows(IllegalArgumentException.class,
() -> KeyVaultCertificateIdentifier.parse(certificateId));

assertEquals("certificateId is not a valid Key Vault Certificate identifier", exception.getMessage());
}
}
1 change: 1 addition & 0 deletions sdk/keyvault/azure-security-keyvault-keys/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@

--add-opens com.azure.security.keyvault.keys/com.azure.security.keyvault.keys=ALL-UNNAMED
--add-opens com.azure.security.keyvault.keys/com.azure.security.keyvault.keys.cryptography=ALL-UNNAMED
--add-opens com.azure.security.keyvault.keys/com.azure.security.keyvault.keys.models=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import com.azure.core.util.CoreUtils;
import com.azure.core.util.logging.ClientLogger;
import com.azure.security.keyvault.keys.implementation.KeyVaultCredentialPolicy;
import com.azure.security.keyvault.keys.models.KeyVaultKeyIdentifier;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
Expand Down Expand Up @@ -163,7 +165,9 @@ public KeyAsyncClient buildAsyncClient() {
/**
* Sets the vault url to send HTTP requests to.
*
* @param vaultUrl The vault url is used as destination on Azure to send requests to.
* @param vaultUrl The vault url is used as destination on Azure to send requests to. If you have a key identifier,
* use {@link KeyVaultKeyIdentifier#parse(String)} to parse it and obtain the {@code vaultUrl} and other
* information.
* @return the updated ServiceClientBuilder object.
* @throws IllegalArgumentException if {@code vaultUrl} is null or it cannot be parsed into a valid URL.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.models;

import com.azure.security.keyvault.keys.KeyAsyncClient;
import com.azure.security.keyvault.keys.KeyClient;

import java.net.MalformedURLException;
import java.net.URL;

/**
* Information about a {@link KeyVaultKey} parsed from the key URL. You can use this information when calling methods
* of {@link KeyClient} or {@link KeyAsyncClient}.
*/
public final class KeyVaultKeyIdentifier {
private final String keyId, vaultUrl, name, version;

private KeyVaultKeyIdentifier(String keyId, String vaultUrl, String name, String version) {
this.keyId = keyId;
this.vaultUrl = vaultUrl;
this.name = name;
this.version = version;
}

/**
* Gets the key identifier used to create this object.
*
* @return The key identifier.
*/
public String getKeyId() {
return keyId;
}

/**
* Gets the URL of the Key Vault.
*
* @return The Key Vault URL.
*/
public String getVaultUrl() {
return vaultUrl;
}

/**
* Gets the name of the key.
*
* @return The key name.
*/
public String getName() {
return name;
}

/**
* Gets the optional version of the key.
*
* @return The key version.
*/
public String getVersion() {
return version;
}

/**
* Create a new {@link KeyVaultKeyIdentifier} from a given key identifier.
*
* <p>Valid examples are:
*
* <ul>
* <li>https://{key-vault-name}.vault.azure.net/keys/{key-name}</li>
* <li>https://{key-vault-name}.vault.azure.net/keys/{key-name}/pending</li>
* <li>https://{key-vault-name}.vault.azure.net/keys/{key-name}/{unique-version-id}</li>
* <li>https://{key-vault-name}.vault.azure.net/deletedkeys/{deleted-key-name}</li>
* </ul>
*
* @param keyId The key identifier to extract information from.
* @return a new instance of {@link KeyVaultKeyIdentifier}.
* @throws IllegalArgumentException if the given identifier is {@code null}.
* @throws MalformedURLException if the given identifier is not a valid Key Vault Key identifier
*/
public static KeyVaultKeyIdentifier parse(String keyId) throws IllegalArgumentException, MalformedURLException {
if (keyId == null) {
throw new IllegalArgumentException("keyId cannot be null");
}

URL url = new URL(keyId);
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
// We expect an identifier with either 2 or 3 path segments: collection + name [+ version]
String[] pathSegments = url.getPath().split("/");

if ((pathSegments.length != 3 && pathSegments.length != 4) // More or less segments in the URI than expected.
|| !"https".equals(url.getProtocol()) // Invalid protocol.
|| (!"keys".equals(pathSegments[1]) && !"deletedkeys".equals(pathSegments[1])) // Invalid collection.
|| ("deletedkeys".equals(pathSegments[1]) && pathSegments.length == 4)) { // Deleted items do not include a version.
throw new IllegalArgumentException("keyId is not a valid Key Vault Key identifier");
}

return new KeyVaultKeyIdentifier(keyId, url.getProtocol() + "://" + url.getHost(), pathSegments[2],
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
pathSegments.length == 4 ? pathSegments[3] : null);
}
}
Loading