You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效从共享Azure Key Vault下载指定密钥?含代码优化需求

问题场景

我们的平台使用一个共享Azure Key Vault实例,存储了5000+供各类应用使用的密钥。我需要高效获取仅与我负责的特定应用相关的约10个密钥,但当前方案需先下载所有密钥属性再本地过滤,导致大量服务器往返请求,在密钥数量庞大时存在性能瓶颈。

当前实现代码如下:

// 获取Key Vault中所有密钥的名称
public async IAsyncEnumerable<string> GetKeys()
{
    var keyVaultSecureValueManager = (KeyVaultSecureValueManager)this.SecureValueManager;
    var allPages = keyVaultSecureValueManager.Client.GetPropertiesOfSecretsAsync().AsPages();

    await foreach (var page in allPages)
    {
        foreach (var secretProperties in page.Values)
        {
            yield return secretProperties.Name;
        }
    }
}

// 本地过滤出目标密钥
private static async Task<List<string>> GetKeysAsync(IAsyncEnumerable<string> keyvaultKeys)
{
    List<string> keys = new List<string>();
    await foreach (var key in keyvaultKeys)
    {
        if (key.StartsWith("myKeys", StringComparison.InvariantCultureIgnoreCase))
        {
            keys.Add(key);
        }
    }

    return keys;
}

// 获取单个密钥值
private async Task<KeyVaultResponse> GetCertAsync(string key)
{
    return await secretManager.GetKeyAsync(key);
}

// 获取所有目标证书密钥
public async Task<Certs> GetAllCertsAsync()
{
    var keyvaultKeys = this._secretManager.GetKeys();
    var selectedKeys = await GetKeysAsync(keyvaultKeys);
    var allCertKeys = selectedKeys.Where(s => s.EndsWith("cert", StringComparison.InvariantCultureIgnoreCase));
    var allPwdKeys = selectedKeys.Where(s => s.EndsWith("pwd", StringComparison.InvariantCultureIgnoreCase));

    // 并发获取所有证书
    var fetchTasks = allCertKeys.Select(c => this.GetCertAsync(c, allPwdKeys));
    var results = await Task.WhenAll(fetchTasks);

    // 检查请求错误
    var badRequest = results.FirstOrDefault(res => res.IsBadRequest);
    if (badRequest != null)
    {
        return BadRequestResponse(badRequest.ErrorMessage);
    }

    return results;
}

我有两个技术问题需要解决:

  1. 使用Azure.Security.KeyVault.Secrets命名空间下的SecretClient时,能否通过服务器端过滤减少服务器往返次数?
  2. 共享Azure Key Vault中组织密钥的推荐最佳实践有哪些?例如按应用或领域分组以实现特定集合查询。

问题解答

1. 服务器端过滤减少往返次数

可以通过SecretClient.GetPropertiesOfSecretsAsync的**Filter参数**实现服务器端过滤,利用OData筛选器直接在Azure Key Vault服务端筛选密钥,无需拉取全量数据,大幅减少服务器往返次数和数据传输量。

代码示例:按名称前缀服务器端筛选

修改原GetKeys方法,添加OData筛选器筛选名称以myKeys开头的密钥:

using Azure.Security.KeyVault.Secrets;

public async IAsyncEnumerable<string> GetFilteredKeys()
{
    var keyVaultSecureValueManager = (KeyVaultSecureValueManager)this.SecureValueManager;
    SecretClient client = keyVaultSecureValueManager.Client;

    // 服务器端筛选:名称以"myKeys"开头(OData filter语法)
    var filter = $"name starts with 'myKeys'";
    var filteredPages = client.GetPropertiesOfSecretsAsync(filter: filter).AsPages();

    await foreach (var page in filteredPages)
    {
        foreach (var secretProperties in page.Values)
        {
            yield return secretProperties.Name;
        }
    }
}

进阶:按标签筛选

如果密钥带有标签(比如app=myapp),也可以通过标签做服务器端筛选:

// 筛选标签app等于myapp的密钥
var filter = $"tags/app eq 'myapp'";
var filteredPages = client.GetPropertiesOfSecretsAsync(filter: filter).AsPages();

直接批量获取已知密钥

如果已经明确知道目标密钥的名称,无需先查询属性,直接批量并发获取密钥值,进一步优化性能:

public async Task<Certs> GetAllCertsDirectlyAsync()
{
    // 预先定义目标密钥名称列表
    var targetCertKeys = new List<string> { "myKeys-db-cert", "myKeys-api-cert" };
    var targetPwdKeys = new List<string> { "myKeys-db-pwd", "myKeys-api-pwd" };

    // 并发获取所有证书密钥
    var fetchTasks = targetCertKeys.Select(c => this.GetCertAsync(c));
    var results = await Task.WhenAll(fetchTasks);

    // 检查请求错误
    var badRequest = results.FirstOrDefault(res => res.IsBadRequest);
    if (badRequest != null)
    {
        return BadRequestResponse(badRequest.ErrorMessage);
    }

    return results;
}

2. 共享Azure Key Vault密钥组织最佳实践

- 统一命名规范

采用分层命名结构,包含应用标识、环境、密钥类型等信息,例如:
{应用名}-{环境}-{资源类型}-{密钥用途}
比如:myapp-dev-db-cert、myapp-prod-api-pwd
这种命名方式便于通过OData前缀筛选,也能快速识别密钥归属。

- 利用标签(Tags)分类

给每个密钥添加标签,比如app=myapp、env=dev、type=cert,支持更灵活的服务器端筛选,同时便于在Azure门户中快速分组查看。

- 最小权限访问控制(Azure RBAC)

避免给应用分配Key Vault的全局权限,通过Azure RBAC的密钥/证书/机密权限,结合Filter条件限制应用只能访问特定前缀或标签的密钥。例如创建自定义RBAC角色,允许应用仅读取名称以myapp-开头的密钥。

- 避免全量拉取密钥属性

永远优先使用服务器端过滤(OData筛选器),不要拉取所有密钥后再本地过滤,尤其当Key Vault中密钥数量超过1000个时,全量拉取会触发多次分页请求,严重影响性能。

- 缓存密钥(按需)

对于不频繁变更的密钥,可在AKS应用中添加本地缓存(比如用IMemoryCache或分布式缓存),减少对Key Vault的重复请求,进一步提升性能。注意缓存过期时间要匹配密钥的更新频率,避免使用过期密钥。


内容的提问来源于stack exchange,提问作者pingpong2020

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:43:13