Azure Blob 儲存庫裝載適用的加密自訂
本節說明在 Azure Blob 儲存庫上以已加密格式儲存內容的加密自訂。依預設,儲存在 Azure Blob 儲存庫上的內容會使用 serverSideEncryption 加密類型加密。儲存在檔案系統型儲存庫中的內容採用一般格式。
Windchill 支援下列加密類型:
1. 伺服器端 - 有兩個選項可供選擇:
a. Azure 所管理的金鑰 - 這是預設加密類型,由 Azure 系統自動設定。
b. Azure Key Vault 所管理的金鑰 - 您可以在 Azure 入口網站的金鑰儲存庫中,設定容器的金鑰。
2. 用戶端 - 有兩個選項可供選擇:
a. clientSideEncryption-keyvault - 此加密類型會使用 Azure Key Vault 所管理的金鑰。
b. clientSideEncryption - 此加密類型會使用客戶所管理的金鑰。
如需用戶端加密的委派實行詳細資訊,請參閱「寫入用戶端加密的委派實行」部份。
|
使用者負責管理加密選項。您務必確保在加密選項有所變更的情況下,也可以存取該內容。
|
寫入用戶端加密的委派實行
欲自訂 Azure Blob Stoarge 中的內容加密,請以下列方式寫入委派實行︰
1. Blob 加密組態配置器委派 - 預設委派即
com.ptc.windchill.objectstorage.azureblob.encryption.DefaultBlobEncryptConfigurator。預設委派會傳回
serverSideEncryption 作為加密類型。如果您想使用其他加密類型,請寫入會傳回預期加密類型的委派,然後部署類別檔案並使用指令行工具進行配置。如需有關組態的詳細資訊,請參閱
配置 Windchill 檔案儲存庫,以使用 Azure Blob 儲存庫。
以下是範例委派。
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;
}
}
}
視裝載路徑 (Blob 名稱) 而定,SampleBlobEncryptConfigurator 會傳回 serverSideEncryption、clientSideEncryption 或 clientSideEncryption-keyvault 作為加密類型。儲存在 Azure Blob 儲存庫上的內容會以這些加密類型予以加密。API getBlobEncryptionType 會獲得儲存帳戶名稱、容器名稱和 Blob 名稱作為引數。您可以使用儲存帳戶名稱、容器名稱及 Blob 名稱編寫加密類型。例如,針對容器 c1,傳回加密類型 serverSideEncryption,針對容器 c2,傳回加密類型 clientSideEncryption-keyvault。
加密類型的有效值為︰
a. serverSideEncryption - 會將伺服器端加密與 Azure 受管理金鑰搭配使用來儲存內容。
b. clientSideEncryption-keyvault - 會將用戶端加密與 Azure Key Vault 受管理金鑰搭配使用來儲存內容。
c. clientSideEncryption - 會將用戶端加密與客戶提供的金鑰搭配使用來儲存內容。
2. CSEKeyVaultKeyProvider Delegate - 此委派適用於加密類型配置為
clientSideEncryption-keyvault 的情況。此委派沒有預設現成實行。您必須寫入會傳回預期的 Azure Key Vault 連接對參數的委派、部署類別檔案及使用指令行工具配置。如需有關組態的詳細資訊,請參閱
配置 Windchill 檔案儲存庫,以使用 Azure Blob 儲存庫。
範例委派如下所示:
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";
KeyVaultConnectionParams connectionParams = new KeyVaultConnectionParams(keyVaultKeyIdUrl, appId,
appAuthKey);
return connectionParams;
}
}
3. CSESecKeyGenerator Delegate - 如果您將加密類型配置為
clientSideEncryption,則必須寫入此委派的實行,並配置委派。此委派僅在加密類型配置為
clientSideEncryption 的情況下才適用。此委派沒有預設現成實行。寫入會管理
KeyPair 及
KeyId 的委派、部署類別檔案並使用此指令行工具進行配置。如需有關組態的詳細資訊,請參閱
配置 Windchill 檔案儲存庫,以使用 Azure Blob 儲存庫。
範例委派如下所示:
SampleCSESecKeyGenerator.java︰這是示範如何產生 KeyPair 及 KeyId 的範例實行。此範例實行會搜尋現有 KeyPair。若找到,會傳回 KeyPair。否則會產生新的 KeyPair,並將其儲存在磁碟上的檔案中後傳回。您可以決定安全儲存 KeyPair 的策略。此外,此範例實行針對儲存庫中的所有檔案使用單一 KeyPair。您可以撰寫自己演算法,以針對容器或儲存在 Azure 中的 Blob 管理多個 KeyPairs。
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;
}
}
管理加密類型
如果您想要變更檔案儲存庫的加密類型,請執行下列步驟:
1. 建立新儲存庫並使用委派實行將其配置為所需的加密類型。如需詳細資訊,請參閱〈寫入用戶端加密的委派實行〉一節。
2. 更新存放規則以便將內容導入新儲存庫。
3. 執行重新存放排程。