使用Azure Key Vault存储用户名和密码

时间:2016-10-20 03:43:56

标签: azure azure-keyvault

我正在开发一个应用程序,我想存储将由守护程序服务使用的服务帐户的用户名和密码。

我们的想法是为应用程序管理员提供一个仪表板,他/她可以在其中输入服务帐户的凭据,之后可以将其存储在安全的地方。

我可以考虑将它存储在像Azure Vault这样的安全位置,并在需要时从那里获取它。但是,密钥和密钥是Azure Vault中的不同实体。我无法将它们存储在某个地方。

之前有人这样做过吗?或者是否有更好的替代方法来存储Azure中的凭据?

1 个答案:

答案 0 :(得分:6)

您可以使用Azure blob存储用于加密静态数据的技术(信封方法): https://docs.microsoft.com/en-us/azure/storage/storage-client-side-encryption

KeyVault能够对对称密钥进行包装/解包(加密/解密),以便您可以安全地存储加密数据。

以下是一般步骤:

  1. 使用RNGCryptoServiceProvider生成AES密钥(256位,CBC模式)
  2. 加密数据(凭据)
  3. 保存初始化向量(IV)。您可以将其连接到密文字节数组,以便以后在需要解密时进行检索 - IV不需要保护。
  4. 使用KeyVault中的密钥包裹(加密)生成的AES Symmetric Key。
  5. 存储Wraped AES Key,IV,CipherText和Key Version(KeyVault中URI末尾的GUID)。
  6. 确保将KeyVault中的Wrap / Unwrap权限授予Azure AD中创建的应用程序注册。使用客户端ID /应用程序ID +密钥或pfx在GetToken()中对Azure进行身份验证。
  7. 你需要这些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密钥的byte []:

    // 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();
    

    要考虑的其他细节是密钥备份/恢复和密钥轮换。