Personalización de la codificación para los montajes de Azure Blob Storage
En esta sección se explica la personalización de la codificación para almacenar contenido en un formato cifrado en Azure Blob Storage. De fábrica, el contenido almacenado en Azure Blob Storage se cifra mediante el tipo de codificación serverSideEncryption. El contenido almacenado en los depósitos basados en sistema de ficheros no tiene formato.
Windchill soporta los siguientes tipos de codificación:
1. Lado del servidor: se puede elegir entre dos opciones.
a. Clave administrada de Azure: es el tipo de codificación por defecto y el sistema Azure la define automáticamente.
b. Clave administrada de Azure Key Vault: se puede definir la clave de Key Vault para un contenedor desde Azure Portal.
2. Lado del cliente: se puede elegir entre dos opciones.
a. clientSideEncryption-keyvault: este tipo de codificación utiliza las claves administradas de Azure Key Vault.
b. clientSideEncryption: este tipo de codificación utiliza las claves administradas del cliente.
Los detalles de las implementaciones de delegado para la codificación del lado del cliente se proporcionan en la sección "Cómo escribir implementaciones de delegado para la codificación en el cliente".
|
El usuario es responsable de gestionar las opciones de codificación. El usuario debe asegurarse de que el contenido sea accesible en caso de cambios en las opciones de codificación.
|
Cómo escribir implementaciones de delegado para la codificación en el cliente
Para personalizar la codificación de contenido en Azure Blob Storage, escriba implementaciones de delegado de la siguiente manera:
1. Delegado de configurador de codificación de blob: el delegado por defecto es
com.ptc.windchill.objectstorage.azureblob.encryption.DefaultBlobEncryptConfigurator. El delegado por defecto devuelve el tipo de codificación como
serverSideEncryption. Si desea utilizar otro tipo de codificación, escriba un delegado que devuelva el tipo de codificación esperado, implemente los ficheros de clase y realice la configuración con esta herramienta de línea de comandos. Para obtener más información sobre la configuración, consulte
Configuración de los depósitos de ficheros de Windchill para utilizar Azure Blob Storage.
El siguiente es un delegado de muestra.
SampleBlobEncryptConfigurator.java:
package com.abc.windchill.objectstorage.azureblob.encryption;
import com.ptc.windchill.objectstorage.azureblob.exception.BlobException;
public class SampleBlobEncryptConfigurator implements BlobEncryptConfigurator {
private static final String CSE_KEYVAULT_FOLDER = "keyvault";
private static final String CSE_FOLDER = "cse";
@Override
public String getBlobEncryptionType(String storageAccountName, String containerName, String blobName) throws BlobException {
if (blobName != null && blobName.contains(CSE_KEYVAULT_FOLDER)) {
return BlobEncryptionType.CSE_KEYVAULT;
} else if (blobName != null && blobName.contains(CSE_FOLDER)) {
return BlobEncryptionType.CSE;
} else {
return BlobEncryptionType.SSE;
}
}
}
En función de la ruta de montaje (nombre de blob), SampleBlobEncryptConfigurator devuelve serverSideEncryption, clientSideEncryption o clientSideEncryption-keyvault como tipo de codificación. El contenido almacenado en Azure Blob Storage se cifra con estos tipos de codificación. La API getBlobEncryptionType recibe el nombre de la cuenta de almacenamiento, el nombre del contenedor y el nombre de blob como argumento. Se puede programar el tipo de codificación con el nombre de la cuenta de almacenamiento, el nombre del contenedor y el nombre de blob. Por ejemplo, para el contenedor c1, devuelva el tipo de codificación como serverSideEncryption y, para el contenedor c2, devuelva el tipo de codificación como clientSideEncryption-keyvault.
Los valores válidos de tipo de codificación son:
a. serverSideEncryption: el contenido se almacena mediante la codificación del servidor con las claves gestionadas de Azure.
b. clientSideEncryption-keyvault: el contenido se almacena mediante la codificación del cliente con las claves gestionadas de Azure Key Vault.
c. clientSideEncryption: el contenido se almacena mediante la codificación del cliente con las claves proporcionadas por el cliente.
2. CSEKeyVaultKeyProvider Delegate : este delegado es aplicable si el tipo de la codificación se configura como
clientSideEncryption-keyvault. No hay implementación de fábrica por defecto para este delegado. Se debe escribir un delegado que devuelva los parámetros de conexión esperados de Azure Key Vault, implementar los ficheros de clase y configurarlo con la herramienta de línea de comandos. Para obtener más información sobre la configuración, consulte
Configuración de los depósitos de ficheros de Windchill para utilizar Azure Blob Storage.
|
No utilice las siguientes implementaciones de ejemplo, ya que se encuentra en un entorno de producción.
|
A continuación, se muestra el delegado de ejemplo:
package com.abc.windchill.objectstorage.azureblob.encryption.csekeyvault;
import com.ptc.windchill.objectstorage.azureblob.encryption.csekeyvault.CSEKeyVaultKeyProvider;
import com.ptc.windchill.objectstorage.azureblob.encryption.csekeyvault.KeyVaultConnectionParams;
import com.ptc.windchill.objectstorage.azureblob.exception.BlobException;
/**
* Sample implementation of CSEKeyVaultKeyProvider.
*/
public class SampleCSEKeyVaultKeyProvider implements CSEKeyVaultKeyProvider {
@Override
public KeyVaultConnectionParams getKeyVaultConnectionDetails(String containerName, String blobName)
throws BlobException {
String keyVaultKeyIdUrl = https://mykeyvault.vault.azure.net/keys/MyKeyVaultKey;
String appId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
String appAuthKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String tenantId = “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”;
KeyVaultConnectionParams connectionParams = new KeyVaultConnectionParams(keyVaultKeyIdUrl, appId,
appAuthKey, tenantId);
return connectionParams;
}
}
|
• A partir de la versión 12.1.2.0 de Windchill, para el tipo de codificación de clientSideEncryption-keyvault, el ID de inquilino (directorio) es una entrada obligatoria que se debe proporcionar al constructor de KeyVaultConnectionParams.
• Si desea evitar los cambios de código para el ID de inquilino (directorio), puede definir el ID de inquilino (directorio) mediante la propiedad wt wt.objectStorage.blob.csekeyvault.appTenantId.
|
3. CSESecKeyGenerator Delegate : si el tipo de codificación se configura como
clientSideEncryption, se debe crear la implementación de este delegado y configurar el delegado. Este delegado solo se aplica si el tipo de codificación se ha configurado en
clientSideEncryption. No hay implementación de fábrica por defecto para este delegado. Escriba un delegado que gestione
KeyPair y
KeyId, implemente los ficheros de clase y realice la configuración con esta herramienta de línea de comandos. Para obtener más información sobre la configuración, consulte
Configuración de los depósitos de ficheros de Windchill para utilizar Azure Blob Storage.
A continuación, se muestra el delegado de ejemplo:
SampleCSESecKeyGenerator.java: esta es una implementación de ejemplo que muestra cómo generar KeyPair y KeyId. En esta implementación de muestra se busca un elemento KeyPair existente. Si se encuentra, se devuelve el elemento KeyPair. De lo contrario, se genera un nuevo elemento KeyPair, se almacena en un fichero en el disco y se devuelve. Se puede decidir la estrategia para almacenar con seguridad el elemento KeyPair. Asimismo, esta implementación de muestra utiliza un único elemento KeyPair para todos los ficheros del depósito. Es posible escribir un algoritmo propio para gestionar varios pares de claves para los contenedores o para los blobs almacenados en Azure.
package com.abc.windchill.objectstorage.azureblob.encryption.cse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import com.ptc.windchill.objectstorage.azureblob.encryption.cse.CSESecKeyGenerator;
import com.ptc.windchill.objectstorage.azureblob.exception.BlobException;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.wrmf.delivery.ObjectIS;
import wt.wrmf.delivery.PayloadShippingItem;
import wt.wrmf.delivery.ShippingHelper;
/**
* Sample implementation of CSESecKeyGenerator.
*/
public class SampleCSESecKeyGenerator implements CSESecKeyGenerator {
private File keyPairFile;
public static String keyPairFileName;
static {
try {
WTProperties props = WTProperties.getLocalProperties();
String windchillHome = props.getProperty("wt.home");
keyPairFileName = windchillHome + File.separator + "RsaKey";
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
@Override
public KeyPair getKeyPair(String storageAccountName, String containerName, String blobName) throws BlobException {
try{
KeyPair wrapKey = getKeyPairFromFileStore();
if(wrapKey == null){
// Create the IKey used for encryption.
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
wrapKey = keyGen.generateKeyPair();
storeKeyPairInFileStore(containerName, blobName, wrapKey);
storeKeyPairInFileStoreOnReplica(containerName, blobName, wrapKey);
}
return wrapKey;
}
catch(Exception e){
throw new BlobException(e);
}
}
@Override
public String getKeyId(String storageAccountName, String containerName, String blobName) throws BlobException {
return containerName;//using container name as key id
}
private KeyPair getKeyPairFromFileStore()throws IOException, ClassNotFoundException{
KeyPair keyPair = null;
File keyPairFile = getKeyPairFile();
try(
FileInputStream fis = new FileInputStream(keyPairFile);
ObjectInputStream ois = new ObjectInputStream(fis);){
keyPair = (KeyPair)ois.readObject();
}catch (IOException ignore){
ignore.printStackTrace();
}
return keyPair;
}
public synchronized void storeKeyPairInFileStore(String containerName, String blobName, KeyPair keyPair)throws IOException{
File keyPairFile = getKeyPairFile();
try(FileOutputStream fos = new FileOutputStream(keyPairFile, true);
ObjectOutputStream oos = new ObjectOutputStream(fos);){
oos.writeObject(keyPair);
oos.flush();
}
}
private synchronized void storeKeyPairInFileStoreOnReplica(String containerName, String blobName, KeyPair keyPair)
throws Exception {
//this is a private method that invokes method call on replica site
invokeMethodOnReplica(getReplicaSite(),
SampleCSESecKeyGenerator.class.getName(), "setKeyPairOnReplica",
new String[] { String.class.getName(), String.class.getName(), KeyPair.class.getName() },
new Serializable[] { containerName, blobName, keyPair });
}
private synchronized File getKeyPairFile() throws IOException {
if (keyPairFile == null) {
keyPairFile = new File(keyPairFileName);
if (!keyPairFile.exists()) {
keyPairFile.createNewFile();
}
}
return keyPairFile;
}
@Override
public boolean removeKeyPair(String storageAccountName, String containerName, String blobName) {
return true;//do not remove the KeyPair, since sample code uses single KeyPair for all files in vault.
}
public static PayloadShippingItem setKeyPairOnReplica(String storageAccountName,
String containerName, String blobName, KeyPair keyPair) throws WTException {
PayloadShippingItem psi = ShippingHelper.service.createPayloadShippingItem();
try {
File keyPairFile = new File(keyPairFileName);
if (!keyPairFile.exists()) {
keyPairFile.createNewFile();
}
try (FileOutputStream fos = new FileOutputStream(keyPairFile, false);
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
oos.writeObject(keyPair);
oos.flush();
}
Object[] valuesToReturn = new Object[] {};
ObjectIS retValsIS = new ObjectIS(valuesToReturn);
psi.setPayload(retValsIS);
} catch (Exception e) {
throw new WTException(e);
}
return psi;
}
}
Gestión del tipo de codificación
Si desea cambiar el tipo de codificación para un depósito de ficheros, realice los siguientes pasos:
1. Cree un nuevo depósito y configúrelo para el tipo de codificación deseado mediante la implementación de delegado. Para obtener más información, consulte la sección "Cómo escribir implementaciones de delegado para la codificación en el cliente".
2. Actualice la regla de reasignación para dirigir el contenido al nuevo depósito.
3. Ejecute la programación de la reasignación.