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

如何用C#获取Azure软删除资源及Key Vault软删除条目

核心问题

你之前的实现逻辑从入口就错了,所以找不到对应数据:

  • 订阅下被软删除的通用Azure资源不归属任何现存资源组,根本不会出现在资源组下的普通资源枚举结果里,查询入口直接在订阅层级,不需要遍历资源组
  • 普通Key Vault资源下的GetSecrets()、GetVaultKeys()方法返回的都是未删除的活跃条目,软删除状态的密钥、机密不会出现在这个列表里,你找不到相关属性是因为调错了接口
依赖调整

你现在安装的Compute、Network、Storage等beta包和当前软删除检测需求无关,可以直接移除,保留以下包即可:

<PackageReference Include="Azure.Identity" Version="1.6.0" />
<PackageReference Include="Azure.ResourceManager" Version="1.0.0" />
<PackageReference Include="Azure.ResourceManager.Resources" Version="1.0.0" />
<PackageReference Include="Azure.ResourceManager.KeyVault" Version="1.0.0-beta.8" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.3.0" />
<PackageReference Include="Azure.Security.KeyVault.Keys" Version="4.3.0" />

权限前置要求:

  • 认证身份(本地调试的个人账号、Function托管标识)需要在订阅范围分配Microsoft.Resources/deletedResources/read权限,才能读取通用软删除资源
  • 同一身份需要拥有目标Key Vault数据平面的「列出已删除机密」「列出已删除密钥」权限,建议直接在订阅层级分配,避免逐KV配置
实现逻辑说明

1. 通用软删除资源查询

直接在订阅资源对象上调用GetDeletedResourcesAsync()方法即可,这个是Azure.ResourceManager.Resources 1.0稳定版自带的接口,返回结果包含软删除资源的名称、类型、原所属资源组、删除时间、计划永久删除时间等全量属性,不需要遍历资源组,还能查到原资源组已经被删除的软删除资源。

注意:只有开启了软删除功能的资源类型才会出现在结果里,未开启软删除的资源删除后会被直接清除,没有留存记录。

2. Key Vault软删除条目查询

分两步实现:

  • 第一步直接在订阅层级枚举所有Key Vault资源,不需要遍历资源组,调用subscription.GetVaultsAsync()即可拿到订阅下全部KV实例
  • 第二步跳过未开启软删除的KV,对开启软删除的KV实例,用数据平面的SecretClient、KeyClient调用GetDeletedSecretsAsync()、GetDeletedKeysAsync()方法,即可拿到所有软删除状态的机密、密钥,返回结果包含删除时间、计划清除时间等属性。如果需要查询软删除证书,新增CertificateClient调用GetDeletedCertificatesAsync()即可,逻辑完全一致。
可运行代码示例

替换你原来的DoSomething方法即可:

private async Task DoSomething(ILogger log)
{
    // 生产/本地通用认证类,本地自动读VS登录凭据,部署后自动用Function托管标识
    var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
    {
        ExcludeVisualStudioCodeCredential = true,
        ExcludeSharedTokenCacheCredential = true,
        ExcludeInteractiveBrowserCredential = true
    });
    var subscriptionId = Environment.GetEnvironmentVariable(Settings.SubscriptionId);
    ArmClient client = new ArmClient(credentials, subscriptionId);
    var subscription = await client.GetDefaultSubscriptionAsync();

    // 扫描通用软删除资源
    log.LogInformation("开始扫描订阅通用软删除资源");
    await foreach (var deletedResource in subscription.GetDeletedResourcesAsync())
    {
        var resData = deletedResource.Data;
        log.LogInformation($"发现软删除资源:名称{resData.Name},类型{resData.ResourceType},原资源组{resData.Properties?.ResourceGroup},删除时间{resData.Properties?.DeletedOn},计划清除时间{resData.Properties?.ScheduledPurgeOn}");
        // 此处添加自定义存储、告警逻辑
    }

    // 扫描Key Vault软删除条目
    log.LogInformation("开始扫描Key Vault软删除条目");
    await foreach (var vault in subscription.GetVaultsAsync())
    {
        var vaultProp = vault.Data.Properties;
        // 未开软删除的KV不存在软删除条目,直接跳过
        if (vaultProp.EnableSoftDelete != true)
        {
            log.LogInformation($"Key Vault {vault.Data.Name} 未开启软删除,跳过扫描");
            continue;
        }
        var vaultUri = new Uri($"https://{vault.Data.Name}.vault.azure.net/");
        
        // 查询软删除机密
        var secretClient = new SecretClient(vaultUri, credentials);
        await foreach (var deletedSecret in secretClient.GetDeletedSecretsAsync())
        {
            log.LogInformation($"KV {vault.Data.Name} 发现软删除机密:名称{deletedSecret.Name},删除时间{deletedSecret.DeletedOn},计划清除时间{deletedSecret.ScheduledPurgeDate}");
            // 自定义处理逻辑
        }

        // 查询软删除密钥
        var keyClient = new KeyClient(vaultUri, credentials);
        await foreach (var deletedKey in keyClient.GetDeletedKeysAsync())
        {
            log.LogInformation($"KV {vault.Data.Name} 发现软删除密钥:名称{deletedKey.Name},删除时间{deletedKey.DeletedOn},计划清除时间{deletedKey.ScheduledPurgeDate}");
            // 自定义处理逻辑
        }
    }
}
注意事项
  • 完全移除遍历资源组的逻辑,两个查询入口都在订阅层级,遍历资源组不仅效率低,还会漏掉原资源组已经被删除的软删除资源
  • 不要使用写死的VisualStudioCredential,部署到Azure后这个认证方式会直接失败,用DefaultAzureCredential即可兼容本地调试和生产环境
  • 如果需要扫描管理组范围的软删除资源,把入口换成ManagementGroupResource的对应扩展方法即可,逻辑和订阅级完全一致
  • Key Vault默认软删除保留期是90天,其他资源类型保留期根据配置不同有差异,可以根据返回的ScheduledPurgeDate字段做分级告警

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:45:54