Центральная служба секретов в Azure Service Fabric

Центральная служба секретов, также называемая центральным хранилищем секретов (Central Secret Service, далее CSS), — это системная служба Service Fabric, предназначенная для защиты секретов в кластере. CSS упрощает управление секретами для приложений SF, устраняя необходимость использовать зашифрованные параметры.

Центральная служба секретов — это устойчивый и реплицируемый кэш секретов в кластере. При хранении в CSS все секреты шифруются с использованием предоставленного клиентом сертификата шифрования. CSS предоставляет клиентские API-интерфейсы для управления секретами. Их могут использовать сущности, проходящие проверку подлинности от имени кластера или пользователя с правами администратора кластера. Модель приложений среды выполнения Service Fabric интегрируется с CSS, позволяя объявлять параметры приложения в формате ссылки CSS на секрет.

Кроме того, CSS позволяет предоставлять секреты приложения, объявленные как коды URI секрета в KeyVault, в сочетании с управляемым удостоверением для приложений Service Fabric, развернутых в Azure.

Центральная служба секретов не рассчитана на использование вместо выделенной внешней службы управления секретами, такой как Azure Key Vault.

Примечание

Активация CSS в кластере SF под управлением более ранней версии, чем 7.1. CU3, может завершиться ошибкой и оставить CSS в неработоспособном состоянии без возможности восстановления. Такое происходит, если в кластере настроена проверка подлинности Windows, неправильно объявлен EncryptionCertificateThumbprint или не установлен соответствующий сертификат. Мы рекомендуем во всех случаях предварительно обновить кластер до версии среды выполнения SF выше 7.1. CU3, прежде чем продолжать работу.

Включение центральной службы секретов

Чтобы включить центральную службу секретов, измените конфигурацию кластера, как указано ниже. Рекомендуется использовать сертификат шифрования, отличный от сертификата кластера. Этот сертификат нужно установить во всех узлах.

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

Примечание

Параметр конфигурации "DeployedState" (Состояние развертывания), который появился в Service Fabric версии 8.0, является предпочтительным механизмом для включения или отключения CSS. Эта возможность в предыдущих версиях обрабатывалась с помощью параметра конфигурации IsEnabled, который теперь считается устаревшим.

Модель секретов в центральной службе секретов

API центральной службы секретов предоставляет два типа данных: ресурс секрета и версия секрета. Тип ресурса секрета представляет семейство версий одного секрета, используемого для определенной цели. Это могут быть строки подключения, пароли, сертификаты конечной точки и т. п. Объект с типом ресурса секрета содержит метаданные, связанные с этим секретом, в частности назначение, тип содержимого и описание. Тип версии секрета представляет конкретный экземпляр связанного с ним секрета и хранит секрет в формате зашифрованного открытого текста. В приведенных выше примерах версия секрета содержит текущее значение пароля, а объект сертификата действует до конца текущего месяца. При каждом обновлении этих секретов следует создавать новые версии секрета и добавлять их в CSS.

Ниже приведены правила формального описания модели, которые реализуются и применяются в реализации CSS:

  • ресурс секрета может иметь ноль или более версий;
  • каждая версия секрета является дочерней по отношению к конкретному ресурсу секрета и может иметь только один родительский ресурс;
  • можно удалить отдельную версию секрета, не влияя на другие версии того же секрета;
  • удаление ресурса секрета приводит к удалению всех его версий;
  • значение версии секрета нельзя изменить.

Объявление ресурса секрета

Создать ресурс секрета можно с помощью REST API.

Примечание

Если кластер использует проверку подлинности Windows без сертификата HttpGateway, запрос REST отправляется по незащищенному каналу HTTP. Чтобы включить TLS для такого канала, необходимо обновить определение кластера, указав сертификат HTTP сервера шлюза.

Чтобы создать ресурс секрета supersecret с помощью REST API, выполните запрос PUT к конечной точке https://<clusterfqdn>:19080/Resources/Secrets/supersecret?api-version=6.4-preview. Для создания ресурса секрета необходимо пройти проверку подлинности с использованием сертификата кластера или администратора клиента.

$json = '{"properties": {"kind": "inlinedValue", "contentType": "text/plain", "description": "supersecret"}}'
Invoke-WebRequest  -Uri https://<clusterfqdn>:19080/Resources/Secrets/supersecret?api-version=6.4-preview -Method PUT -CertificateThumbprint <CertThumbprint> -Body $json

Установка значения секрета

Чтобы задать значение секрета с помощью REST API, используйте приведенный ниже скрипт.

$Params = '{"properties": {"value": "mysecretpassword"}}'
Invoke-WebRequest -Uri https://<clusterfqdn>:19080/Resources/Secrets/supersecret/values/ver1?api-version=6.4-preview -Method PUT -Body $Params -CertificateThumbprint <ClusterCertThumbprint>

Проверка значения секрета

Invoke-WebRequest -CertificateThumbprint <ClusterCertThumbprint> -Method POST -Uri "https:<clusterfqdn>/Resources/Secrets/supersecret/values/ver1/list_value?api-version=6.4-preview"

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

Приложение может использовать секрет из CSS, объявляя его как переменную среды, или указывая путь для сериализации секрета в формате открытого текста. Чтобы сослаться на секрет CSS, выполните следующие действия:

  1. Добавьте в файл settings.xml раздел со следующим фрагмента кода. Обратите внимание, что значение здесь указано в формате {secretname:version}.
     <Section Name="testsecrets">
      <Parameter Name="TopSecret" Type="SecretsStoreRef" Value="supersecret:ver1"/
     </Section>
  1. Импортируйте раздел в файл ApplicationManifest.xml.
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="testservicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<Policies>
 <ConfigPackagePolicies CodePackageRef="Code">
   <ConfigPackage Name="Config" SectionName="testsecrets" EnvironmentVariableName="SecretPath" />
   </ConfigPackagePolicies>
</Policies>
</ServiceManifestImport>

Пример 1. Подключите секреты к контейнеру. Единственное изменение, необходимое для того, чтобы секреты были доступны внутри контейнера, — задать (specify) точку подключения в <ConfigPackage>. Следующий фрагмент кода является измененным файлом ApplicationManifest.xml.

   <ServiceManifestImport>
       <ServiceManifestRef ServiceManifestName="testservicePkg" ServiceManifestVersion="1.0.0" />
       <ConfigOverrides />
       <Policies>
         <ConfigPackagePolicies CodePackageRef="Code">
           <ConfigPackage Name="Config" SectionName="testsecrets" MountPoint="C:\secrets" EnvironmentVariableName="SecretPath" />
           <!-- Linux Container
            <ConfigPackage Name="Config" SectionName="testsecrets" MountPoint="/mnt/secrets" EnvironmentVariableName="SecretPath" />
           -->
         </ConfigPackagePolicies>
       </Policies>
     </ServiceManifestImport>

Секреты доступны в точке подключения внутри контейнера.

Пример 2. Привязка секрета к переменной среды процесса путем указания Type='SecretsStoreRef. В следующем фрагменте кода приведен пример привязки версии supersecretver1 к переменной среды MySuperSecret в файле ServiceManifest.xml.

   <EnvironmentVariables>
     <EnvironmentVariable Name="MySuperSecret" Type="SecretsStoreRef" Value="supersecret:ver1"/>
   </EnvironmentVariables>

Переменная среды SecretPath будет указывать на каталог, в котором хранятся все секреты. Каждый параметр, указанный в разделе testsecrets, хранится в отдельном файле. Теперь приложение может использовать секрет, как показано ниже.

secretValue = IO.ReadFile(Path.Join(Environment.GetEnvironmentVariable("SecretPath"),  "TopSecret"))

Смена сертификата шифрования в центральной службе секретов

Важно отметить, что сертификаты остаются действительными для расшифровки даже по истечении срока действия. Сейчас мы рекомендуем сохранять в доступном виде старые сертификаты шифрования после их смены, чтобы снизить вероятность блокировки. Чтобы сменить сертификат шифрования в CSS, выполните следующие действия:

  1. Подготовьте новый сертификат для каждого узла кластера. Пока не удаляйте предыдущий сертификат шифрования и не прекращайте его предоставление.
  2. Запустите обновление конфигурации кластера, чтобы изменить значение EncryptionCertificateThumbprint отпечатком SHA-1 нового сертификата. Когда обновление завершится, CSS начнет повторно шифровать все существующее содержимое с использованием нового сертификата шифрования. Все секреты, добавленные в CSS после этого момента, будут сразу шифроваться с использованием нового сертификата шифрования. Так как переход к защите всех секретов новым сертификатом выполняется асинхронно, важно сохранять прежний сертификат шифрования установленным во всех узлах и предоставлять его через CSS.

Удаление центральной службы секретов из кластера

Для безопасного удаления центральной службы секретов из кластера требуются два обновления. С помощью первого обновления отключается работа CSS, а с помощью второго эта служба удаляется из определения кластера. Содержимое службы удаляется без возможности восстановления. Такой двухэтапный процесс предотвращает случайное удаление службы и позволяет гарантировать отсутствие потерянных зависимостей от CSS на этапе удаления. Эта функция доступна в SF 8.0 и более поздних версий.

Шаг 1. Изменение значения DeployedState в CSS на removing (удаление)

Измените в определении кластера "IsEnabled" = "true" или "DeployedState" = "enabled" на

{
    "name":  "DeployedState",
    "value":  "removing"
}

Когда центральная служба секретов переходит в развернутое состояние Removing, она отклоняет все входящие вызовы к API секретов, будь то прямые вызовы REST или активации служб, содержащих SecretStoreRefs или KeyVaultReferences. Все приложения или компоненты в кластере, которые на этот момент зависят от CSS, переходят в состояние "Предупреждение". В этом случае необходимо выполнить откат изменения состояния развертывания на Removing. Если обновление уже выполнено успешно, необходимо запустить новое обновление, чтобы для CSS снова задать DeployedState = Enabled. Если централизованная служба секретов получает запрос в состоянии развертывания Removing, она возвращает код HTTP 401 (не авторизовано) и переходит в состояние работоспособности Warning (Предупреждение).

Шаг 2. Изменение значения DeployedState в CSS на disabled (отключено)

Измените в определении кластера значение "DeployedState" = "removing" на

{
    "name":  "DeployedState",
    "value":  "disabled"
}

Центральная служба секретов теперь не будет выполняться в кластере и исчезнет из списка системных служб. Все содержимое CSS удаляется без возможности восстановления.

Дальнейшие действия