使用 Azure Key Vault 存储用户名和密码
Using Azure Key Vault for storing username and password
我正在开发一个应用程序,我想在其中存储将由守护程序服务使用的服务帐户的用户名和密码。
想法是为应用程序管理员提供一个仪表板,他/她可以在其中输入服务帐户的凭据,稍后可以将其存储在安全的地方。
我可以考虑将其存储在 Azure Vault 等安全位置,并在需要时从那里获取。但是,key 和 secret 在 Azure Vault 中是不同的实体。我无法将它们作为组合存储在某个地方。
以前有人这样做过吗?或者是否有更好的替代方法来在 Azure 中存储凭据?
您可以使用 Azure Blob 存储用于加密静态数据的技术(信封法):
https://docs.microsoft.com/en-us/azure/storage/storage-client-side-encryption
KeyVault 能够打包/解包 (encrypt/decrypt) 对称密钥,因此您可以安全地将它们与加密数据一起存储。
以下是一般步骤:
- 使用 RNGCryptoServiceProvider 生成 AES 密钥(256 位,CBC 模式)
- 加密数据(凭据)
- 保存初始化向量 (IV)。您可以将它连接到密文字节数组,以便稍后在您想要解密时检索 - IV 不需要保护。
- 使用 KeyVault 中的密钥包装(加密)生成的 AES 对称密钥。
- 存储包装的 AES 密钥、IV、密文和密钥版本(KeyVault 中 URI 末尾的 GUID)。
- 确保将 KeyVault 中的 Wrap / Unwrap 权限授予在 Azure AD 中创建的应用程序注册。在 GetToken() 中使用客户端 ID / 应用程序 ID + 密钥或 pfx 向 Azure 进行授权。
您将需要这些 nuget 包:
Install-Package Microsoft.Azure.KeyVault
Install-Package Microsoft.Azure.KeyVault.Extensions
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.16.204221202
获取 KeyVaultKeyResolver 的引用
KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(Utils.GetToken);
// Example GetToken implementation
public class Utils {
// Retrive JWT token to be used for KeyVault access.
internal async static Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
// Could use pfx instead
ClientCredential clientCred = new ClientCredential(
ConfigurationManager.AppSettings["clientId"],
ConfigurationManager.AppSettings["clientSecret"]);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
throw new InvalidOperationException("Failed to obtain the JWT token.");
return result.AccessToken;
}
}
拥有 KeyResolver 后,您可以获得一个 IKey 来包装/解包您的 AES 对称密钥,如下所示...
包装/加密 AES 密钥
keyID 是来自 Key Vault 的 URI,aesKey 是要加密的 AES 密钥的字节[]:
// Resolve an IKey by Key ID from URI in KeyVault
var keyEncryptionKey = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult();
// Take our gen'ed AES Key and wrap (encrypt) it.
Tuple<byte[], string> wrappedKey = keyEncryptionKey.WrapKeyAsync(aeskey, null /* algorithm */, CancellationToken.None).GetAwaiter().GetResult();
元组中的byte[]包含对称密钥的加密字节和使用的算法名称。用您的密文将这些保存为元数据。
解包/解密 AES 密钥
使用相同的密钥调用(密钥版本很重要),algoName 是用于包装密钥的算法的名称(例如 "RSA-OAEP")。
// Retrieve the IKey by Key ID
// Unwrap Key
byte[] aesKey = rsa.UnwrapKeyAsync(wrappedKeyBytes, algoName, CancellationToken.None).GetAwaiter().GetResult();
其他需要考虑的细节是密钥 backup/recovery 和密钥轮换。
我正在开发一个应用程序,我想在其中存储将由守护程序服务使用的服务帐户的用户名和密码。
想法是为应用程序管理员提供一个仪表板,他/她可以在其中输入服务帐户的凭据,稍后可以将其存储在安全的地方。
我可以考虑将其存储在 Azure Vault 等安全位置,并在需要时从那里获取。但是,key 和 secret 在 Azure Vault 中是不同的实体。我无法将它们作为组合存储在某个地方。
以前有人这样做过吗?或者是否有更好的替代方法来在 Azure 中存储凭据?
您可以使用 Azure Blob 存储用于加密静态数据的技术(信封法): https://docs.microsoft.com/en-us/azure/storage/storage-client-side-encryption
KeyVault 能够打包/解包 (encrypt/decrypt) 对称密钥,因此您可以安全地将它们与加密数据一起存储。
以下是一般步骤:
- 使用 RNGCryptoServiceProvider 生成 AES 密钥(256 位,CBC 模式)
- 加密数据(凭据)
- 保存初始化向量 (IV)。您可以将它连接到密文字节数组,以便稍后在您想要解密时检索 - IV 不需要保护。
- 使用 KeyVault 中的密钥包装(加密)生成的 AES 对称密钥。
- 存储包装的 AES 密钥、IV、密文和密钥版本(KeyVault 中 URI 末尾的 GUID)。
- 确保将 KeyVault 中的 Wrap / Unwrap 权限授予在 Azure AD 中创建的应用程序注册。在 GetToken() 中使用客户端 ID / 应用程序 ID + 密钥或 pfx 向 Azure 进行授权。
您将需要这些 nuget 包:
Install-Package Microsoft.Azure.KeyVault
Install-Package Microsoft.Azure.KeyVault.Extensions
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.16.204221202
获取 KeyVaultKeyResolver 的引用
KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(Utils.GetToken);
// Example GetToken implementation
public class Utils {
// Retrive JWT token to be used for KeyVault access.
internal async static Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
// Could use pfx instead
ClientCredential clientCred = new ClientCredential(
ConfigurationManager.AppSettings["clientId"],
ConfigurationManager.AppSettings["clientSecret"]);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
throw new InvalidOperationException("Failed to obtain the JWT token.");
return result.AccessToken;
}
}
拥有 KeyResolver 后,您可以获得一个 IKey 来包装/解包您的 AES 对称密钥,如下所示...
包装/加密 AES 密钥
keyID 是来自 Key Vault 的 URI,aesKey 是要加密的 AES 密钥的字节[]:
// Resolve an IKey by Key ID from URI in KeyVault
var keyEncryptionKey = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult();
// Take our gen'ed AES Key and wrap (encrypt) it.
Tuple<byte[], string> wrappedKey = keyEncryptionKey.WrapKeyAsync(aeskey, null /* algorithm */, CancellationToken.None).GetAwaiter().GetResult();
元组中的byte[]包含对称密钥的加密字节和使用的算法名称。用您的密文将这些保存为元数据。
解包/解密 AES 密钥
使用相同的密钥调用(密钥版本很重要),algoName 是用于包装密钥的算法的名称(例如 "RSA-OAEP")。
// Retrieve the IKey by Key ID
// Unwrap Key
byte[] aesKey = rsa.UnwrapKeyAsync(wrappedKeyBytes, algoName, CancellationToken.None).GetAwaiter().GetResult();
其他需要考虑的细节是密钥 backup/recovery 和密钥轮换。