Поддержка KeyVaultReference для приложений Service Fabric, развертываемых в Azure

При создании облачных приложений распространенной проблемой является выбор безопасного способа передачи секретов в приложения и управления ими. Поддержка Service Fabric KeyVaultReference упрощает эту задачу. После настройки вы можете ссылаться на URL-адрес секрета, который хранится в Key Vault, в определении приложения, и Service Fabric будет обрабатывать получение этого секрета и активацию приложения с помощью него. При использовании версии функции, управляемой SF, Service Fabric также может отслеживать Key Vault и автоматически запускать последовательное обновление параметров приложения при смене секретов в хранилище.

Варианты доставки секретов приложениям в Service Fabric

Классический способ доставки секретов в приложение Service Fabric заключался в объявлении зашифрованных параметров. Для этого выполнялось шифрование секретов с помощью сертификата шифрования и передача этих зашифрованных секретов в приложение. Такой метод имеет несколько недостатков: требуется управлять сертификатом шифрования, раскрытием секретов в конвейере развертывания, а также невозможно контролировать метаданные секретов, добавляемые в развертываемое приложение. Соответственно для смены секретов требуется развертывание приложения. Мы больше не рекомендуем использовать зашифрованные параметры за исключением случая, когда используется автономный кластер.

Другой вариант связан с использованием ссылок на хранилище секретов. В этом случае можно централизованно управлять секретами приложения, лучше контролировать метаданные развернутых секретов, а также централизованно управлять сертификатом шифрования. Некоторые могут предпочесть этот стиль управления секретами при использовании автономных кластеров Service Fabric.

В настоящее время рекомендуется по возможности не использовать секреты, а использовать для приложений Service Fabric управляемые удостоверения. Управляемые удостоверения можно использовать для проверки подлинности непосредственно в службе хранилища Azure, Azure SQL и т. д. Это означает, что при доступе к службам Azure, поддерживающим проверку подлинности Microsoft Entra, нет необходимости управлять отдельными учетными данными.

Если невозможно использовать управляемое удостоверение в качестве клиента, рекомендуется использовать KeyVaultReferences. Вместо использования управляемого удостоверения следует использовать keyVaultReferences, чтобы перейти непосредственно в Key Vault. Ссылки KeyVaultReferences помогают повысить доступность приложения, поскольку в этом случае изменения секретов выполняются во время последовательного обновления. Данный метод также лучше масштабируется, поскольку секреты кэшируются и передаются из кластера. Если сейчас приложение использует зашифрованные параметры, в коде приложения потребуются лишь минимальные изменения для использования KeyVaultReferences. Приложение может по-прежнему ожидать получения одного секрета и этот секрет может быть одинаковым в течение всего времени существования процесса.

Необходимые компоненты

  • Управляемое удостоверение для приложений Service Fabric

    Поддержка KeyVaultReference в Service Fabric использует управляемое удостоверение для получения секретов от имени приложения. Необходимо развернуть приложение с помощью ARM и назначить ему управляемое удостоверение. Чтобы включить управляемое удостоверение для приложения, следуйте инструкциям в этом документе.

  • Центральное хранилище секретов (CSS).

    Центральное хранилище секретов (CSS) — это зашифрованный локальный кэш секретов Service Fabric. Описываемая функция использует CSS для защиты и сохранения секретов после их получения из Key Vault. Включение этой системной службы является обязательным для использования KeyVaultReferences. Чтобы включить и настроить CSS, следуйте инструкциям в этом документе.

  • Предоставление разрешения на доступ к Key Vault для управляемого удостоверения приложения

    Инструкции по предоставлению управляемому удостоверению разрешения на доступ к Key Vault см. в этом документе. Обратите внимание, что при использовании управляемого удостоверения, назначаемого системой, оно создается только после развертывания приложения. При этом может возникнуть состояние гонки, в котором приложение пытается получить доступ к секрету до того, как удостоверению предоставлен доступ к хранилищу. Назначаемое системой удостоверение получает имя {cluster name}/{application name}/{service name}.

KeyVaultReferences и управляемые KeyVaultReferences

Основная идея KeyVaultReferences заключается в том, чтобы не задавать значение параметра приложения в качестве секрета, а вместо этого присвойте ему URL-адрес Key Vault. Затем на основе его после активации приложения будет получено значение секрета. В Key Vault один секрет, например https://my.vault.azure.net/secrets/MySecret/, может иметь несколько версий, например https://my.vault.azure.net/secrets/MySecret/<oid1> и <oid2>. При использовании KeyVaultReference значение должно быть ссылкой на версию (https://my.vault.azure.net/secrets/MySecret/<oid1>). При смене этого секрета в хранилище, например, на <oid2>, следует активировать обновление приложения для получения новой ссылки. При использовании ManagedKeyVaultReference значение должно быть ссылкой без версии (https://my.vault.azure.net/secrets/MySecret/). Service Fabric определит последний экземпляр <oid1> и активирует приложение с помощью этого секрета. При смене секрета в хранилище на <oid2> Service Fabric автоматически активируется обновление параметра приложения для перехода на <oid2> от вашего имени.

Примечание.

Функция поддержки KeyVaultReference (секреты с указанием версий) для приложений Service Fabric является общедоступной, начиная с версии Service Fabric 7.2 CU5. Перед использованием функции рекомендуется выполнить обновление до указанной версии.

Примечание.

Функция поддержки управляемых KeyVaultReference (секреты без указания версий) для приложений Service Fabric является общедоступной, начиная с Service Fabric версии 9.0.

Использование KeyVaultReference в приложении

Ссылки KeyVaultReference можно использовать

Как переменная среды

<EnvironmentVariables>
      <EnvironmentVariable Name="MySecret" Type="KeyVaultReference" Value="<KeyVaultURL>"/>
</EnvironmentVariables>
string secret =  Environment.GetEnvironmentVariable("MySecret");

Вставка в контейнер в виде файла

  • Добавьте раздел в файл settings.xml.

    Определите параметр MySecret с типом KeyVaultReference и значением <KeyVaultURL>.

    <Section Name="MySecrets">
        <Parameter Name="MySecret" Type="KeyVaultReference" Value="<KeyVaultURL>"/>
    </Section>
    
  • Укажите ссылку на новый раздел в части <ConfigPackagePolicies> файла ApplicationManifest.xml.

    <ServiceManifestImport>
        <Policies>
        <IdentityBindingPolicy ServiceIdentityRef="MyServiceMI" ApplicationIdentityRef="MyApplicationMI" />
        <ConfigPackagePolicies CodePackageRef="Code">
            <!--Linux container example-->
            <ConfigPackage Name="Config" SectionName="MySecrets" EnvironmentVariableName="SecretPath" MountPoint="/var/secrets"/>
            <!--Windows container example-->
            <!-- <ConfigPackage Name="Config" SectionName="dbsecrets" EnvironmentVariableName="SecretPath" MountPoint="C:\secrets"/> -->
        </ConfigPackagePolicies>
        </Policies>
    </ServiceManifestImport>
    
  • Используйте секреты из кода службы.

    Каждый параметр, указанный в разделе <Section Name=MySecrets>, будет представлять собой файл в папке, на которую указывает переменная среды SecretPath. Приведенный ниже фрагмент кода C# показывает, как прочитать MySecret из приложения.

    string secretPath = Environment.GetEnvironmentVariable("SecretPath");
    using (StreamReader sr = new StreamReader(Path.Combine(secretPath, "MySecret"))) 
    {
        string secret =  sr.ReadToEnd();
    }
    

    Примечание.

    Параметр MountPoint определяет папку, в которую будут добавлены файлы, содержащие значения секретов.

Как ссылка на пароль репозитория контейнеров

 <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="MyACRUser" Type="KeyVaultReference" Password="<KeyVaultURL>"/>
      </ContainerHostPolicies>

Использование Managed KeyVaultReferences в приложении

Во-первых, необходимо включить мониторинг секретов, обновив определение кластера, чтобы добавить EnableSecretMonitoring этот параметр, помимо других необходимых конфигураций CSS:

"fabricSettings": [
    {
        "name": "CentralSecretService",     
        "parameters": [
            {
                "name": "EnableSecretMonitoring",
                "value": "true"
            },
            {
                "name":  "DeployedState",
                "value":  "enabled"
            },
            {
                "name" : "EncryptionCertificateThumbprint",
                "value": "<thumbprint>"
            },
            {
                "name":  "MinReplicaSetSize",
                "value":  "<size>"
            },
            {
                "name":  "TargetReplicaSetSize",
                "value":  "<size>"
            }
        ]
    }
],

Примечание.

Значение по умолчанию может в будущем стать true

После завершения обновления кластера можно обновить пользовательское приложение. В любом месте можно использовать KeyVaultReference, ManagedKeyVaultReference также можно использовать, например:

    <Section Name="MySecrets">
        <Parameter Name="MySecret" Type="ManagedKeyVaultReference" Value="[MySecretReference]"/>
    </Section>

Основное различие в указании ManagedKeyVaultReferences заключается в том, что они не могут быть жестко закодированы в манифесте типа приложения. Они должны объявляться как параметры уровня приложения, а затем их необходимо переопределять в определении приложения ARM.

Вот фрагмент с правильным манифестом

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyAppType" ApplicationTypeVersion="1.0.0">
  <Parameters>
    <Parameter Name="MySecretReference" DefaultValue="" />
  </Parameters>
  <ServiceManifestImport>
    <EnvironmentOverrides CodePackageRef="Code">
      <EnvironmentVariable Name="MySecret" Value="[MySecretReference]" Type="ManagedKeyVaultReference" />
    </EnvironmentOverrides>
    <Policies>
      <IdentityBindingPolicy ServiceIdentityRef="MySvcIdentity" ApplicationIdentityRef="MyAppIdentity" />
    </Policies>
  </ServiceManifestImport>
  <Principals>
    <ManagedIdentities>
      <ManagedIdentity Name="MyAppIdentity" />
    </ManagedIdentities>
  </Principals>
</ApplicationManifest>

и фрагмент определения ресурса приложения:

{
    "type": "Microsoft.ServiceFabric/clusters/applications",
    "name": "MyApp",
    "identity": {
        "type" : "userAssigned",
        "userAssignedIdentities": {
            "[variables('userAssignedIdentityResourceId')]": {}
        }
    },
    "properties": {
        "parameters": {
            "MySecretReference": "https://my.vault.azure.net/secrets/MySecret/"
        },
        "managedIdentities": [
            {
            "name" : "MyAppIdentity",
            "principalId" : "<guid>"
            }
        ]
    }
}

В обоих случаях ManagedKeyVaultReference объявляется как параметр приложения, и этот параметр необходимо переопределить во время развертывания, чтобы Service Fabric успешно управлять жизненным циклом развернутого секрета.

Следующие шаги