Методы аутентификации. Kubernetes
|
Данный механизм может использовать внешние сертификаты X.509 как часть проверки TLS или подписи. Проверка подписей по сертификатам X.509, использующим SHA-1, является устаревшей и больше не используется без обходного пути. Дополнительную информацию см. в разделе FAQ об устаревании. |
Метод аутентификации kubernetes можно использовать для аутентификации в StarVault с помощью токена учетной записи сервиса Kubernetes. Этот метод аутентификации позволяет легко внедрить токен StarVault в под Kubernetes.
Также можете использовать токен учетной записи сервиса Kubernetes для входа в систему через JWT-аутентификацию. В разделе "Как работать с недолговечными токенами Kubernetes" кратко описана работа с недолговечными токенами Kubernetes, и как сравнить JWT-аутентификацию с аутентификацией Kubernetes.
|
Если вы обновляетесь до Kubernetes v1.21+, убедитесь, что параметр конфигурации |
1. Аутентификация
1.1. С помощью CLI
По умолчанию используется путь /kubernetes. Если этот метод авторизации был включен по другому пути, укажите в CLI -path=/my-path, где my-path — путь, по которому выключен метод аутентификации.
starvault write auth/kubernetes/login role=demo jwt=...
1.2. С помощью API
По умолчанию, конечная точка — auth/kubernetes/login. Если этот метод авторизации был включен по другому пути, используйте это значение вместо kubernetes.
curl \
--request POST \
--data '{"jwt": "<your service account jwt>", "role": "demo"}' \
http://127.0.0.1:8200/v1/auth/kubernetes/login
В ответе будет содержаться токен auth.client_token:
{
"auth": {
"client_token": "38fe9691-e623-7238-f618-c94d4e7bc674",
"accessor": "78e87a38-84ed-2692-538f-ca8b9f400ab3",
"policies": ["default"],
"metadata": {
"role": "demo",
"service_account_name": "myapp",
"service_account_namespace": "default",
"service_account_secret_name": "myapp-token-pd21c",
"service_account_uid": "aa9aa8ff-98d0-11e7-9bb7-0800276d99bf"
},
"lease_duration": 2764800,
"renewable": true
}
}
2. Конфигурация
Методы аутентификации должны быть настроены заранее, прежде чем пользователи или машины смогут пройти аутентификацию. Эти шаги обычно выполняются оператором или инструментом управления конфигурацией.
-
Включите метод аутентификации Kubernetes:
starvault auth enable kubernetes -
Используйте конечную точку
/config, чтобы настроить StarVault на взаимодействие с Kubernetes. Используйтеkubectl cluster-infoдля проверки адреса хоста и TCP-порта Kubernetes.starvault write auth/kubernetes/config \ token_reviewer_jwt="<your reviewer service account JWT>" \ kubernetes_host=https://192.168.99.100:<your TCP port or blank for 443> \ kubernetes_ca_cert=@ca.crtШаблон, который StarVault использует для аутентификации подов, зависит от обмена JWT-токеном по сети. Учитывая модель безопасности StarVault, это допустимо, поскольку StarVault является частью базы доверенных вычислений. В целом, приложения Kubernetes не должны передавать этот JWT другим приложениям, поскольку позволяет выполнять вызовы API от имени пода и может привести к непреднамеренному предоставлению доступа третьим лицам.
-
Создайте именованную роль:
starvault write auth/kubernetes/role/demo \ bound_service_account_names=myapp \ bound_service_account_namespaces=default \ policies=default \ ttl=1hЭта роль авторизует учетную запись службы myapp в пространстве имен по умолчанию и наделяет ее политикой по умолчанию.
3. Kubernetes 1.21
Начиная с версии 1.21, функция Kubernetes BoundServiceAccountTokenVolume по умолчанию включена. Это изменяет JWT-токен, устанавливаемый в контейнеры по умолчанию, двумя способами, важными для аутентификации Kubernetes :
-
Имеет срок действия и привязан к сроку жизни пода и учетной записи сервиса.
-
Значение параметра "iss" в JWT зависит от конфигурации кластера.
Изменения в сроке жизни токена важны при настройке опции token_reviewer_jwt. Если используется токен с коротким сроком действия, Kubernetes отзовет его, как только под или учетная запись сервиса будут удалены, или если истечет срок действия, и StarVault больше не сможет использовать API TokenReview. Подробнее о том, как работать с недолговечными токенами Kubernetes, читайте ниже.
В ответ на изменения эмитента в StarVault был обновлен метод аутентификации Kubernetes, который по умолчанию не проверяет эмитент. API Kubernetes выполняет ту же проверку при просмотре токенов, поэтому включение проверки эмитента на стороне StarVault — дублирование работы. Без отключения проверки эмитента StarVault невозможно, чтобы одна конфигурация аутентификации Kubernetes работала для установленных по умолчанию токенов подов в Kubernetes 1.20 и в 1.21. Если хотите включить проверку эмитента в StarVault, смотрите раздел Обнаружение issuer учетной записи службы ниже.
3.1. Как работать с недолговечными токенами kubernetes
Существует несколько способов настройки аутентификации для подов Kubernetes, когда установленные по умолчанию токены подов недолговечны, каждый из которых имеет свои преимущества. В этой таблице представлены все варианты, каждый из которых более подробно описан ниже.
| Опция | Все токены недолговечны | Можно досрочно отозвать токены | Другие соображения |
|---|---|---|---|
Используйте локальный токен в качестве JWT-ревьюера |
Да |
Да |
Требуется развертывание StarVault на кластере Kubernetes |
Используйте JWT клиента в качестве JWT-ревьюера |
Да |
Да |
Операционные накладные расходы |
Использование долгоживущего токена в качестве JWT-ревьюера |
Нет |
Да |
|
Вместо этого используйте JWT-авторизацию |
Да |
Нет |
|
По умолчанию Kubernetes продлевает срок действия внедренных токенов учетных записей сервисов до года, чтобы сгладить переход к недолговечным токенам. Если хотите отключить эту функцию, задайте |
3.1.1. Используйте токен учетной записи локальной службы в качестве JWT-ревьюера
При запуске StarVault в поде Kubernetes рекомендуется использовать токен локальной учетной записи службы пода. StarVault будет периодически перечитывать файл, чтобы поддерживать недолговечные токены. Чтобы использовать локальный токен и сертификат центра сертификации, опустите token_reviewer_jwt и kubernetes_ca_cert при настройке метода аутентификации. StarVault попытается загрузить их из файлов token и ca.crt соответственно в папке монтирования по умолчанию /var/run/secrets/kubernetes.io/serviceaccount/.
starvault write auth/kubernetes/config \
kubernetes_host=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
|
Когда срок действия токена учетной записи сервиса истечет или он будет отозван, StarVault больше не сможет использовать API |
3.1.2. Используйте JWT клиента StarVault в качестве JWT-ревьюера.
При настройке Kubernetes auth можно опустить параметр token_reviewer_jwt, и StarVault будет использовать JWT клиента StarVault в качестве собственного auth-токена при взаимодействии с Kubernetes TokenReview API. Если StarVault работает в Kubernetes, также нужно установить disable_local_ca_jwt=true.
Это означает, что StarVault не хранит никаких JWT и позволяет использовать недолговечные токены повсеместно, но добавляет некоторые операционные накладные расходы на поддержание привязки ролей кластера к набору учетных записей служб, которые хотите аутентифицировать в StarVault. Каждому клиенту StarVault потребуется кластерная роль (ClusterRole)system:auth-delegator:
kubectl create clusterrolebinding starvault-client-auth-delegator \
--clusterrole=system:auth-delegator \
--group=group1 \
--serviceaccount=default:svcaccount1 \
...
3.1.3. Продолжайте использовать долгоживущие токены
Можете создать долгоживущий секрет, используя инструкции здесь, и использовать его в качестве token_reviewer_jwt. В этом примере учетной записи службы хранилища потребуется роль (ClusterRole) system:auth-delegator:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: starvault-k8s-auth-secret
annotations:
kubernetes.io/service-account.name: starvault
type: kubernetes.io/service-account-token
EOF
Использование этого способа позволяет сохранить прежние рабочие процессы, но не получить преимущества от повышения уровня безопасности недолговечных токенов.
3.1.4. Используйте JWT-авторизацию
Аутентификация Kubernetes специализируется на использовании API TokenReview от Kubernetes. Однако JWT-токены, которые генерирует Kubernetes, также можно проверять, используя Kubernetes в качестве OIDC-провайдера. В документации по методу JWT-аутентификации есть инструкции по настройке JWT-аутентификацию с Kubernetes в качестве OIDC-провайдера.
Это решение позволяет использовать недолговечные токены для всех клиентов и устраняет необходимость в ревьювере JWT. Однако клиентские токены не могут быть отозваны до истечения их TTL, поэтому рекомендуется держать TTL коротким с учетом этого ограничения.
3.2. Обнаружение issuer учетной записи обслуживания
|
Следующий раздел применим только в том случае, если установлено |
Для кластеров Kubernetes 1.21+ может потребоваться установить эмитента (issuer) учетной записи сервиса в то же значение, что и флаг kube-apiserver --service-account-issuer. Это связано с тем, что JWT-файлы учетных записей сервисов для этих кластеров могут иметь эмитента, специфичного для самого кластера, вместо старого значения по умолчанию kubernetes/serviceaccount. Если нет возможности проверить это значение напрямую, то можете выполнить следующую процедуру и найти нужное значение в поле "iss":
echo '{"apiVersion": "authentication.k8s.io/v1", "kind": "TokenRequest"}' \
| kubectl create -f- --raw /api/v1/namespaces/default/serviceaccounts/default/token \
| jq -r '.status.token' \
| cut -d . -f2 \
| base64 -d
В большинстве кластеров эта информация также доступна в конечной точке .well-known/openid-configuration:
kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
Это значение затем используется при настройке аутентификации Kubernetes, например:
starvault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT" \
issuer="\"test-aks-cluster-dns-d6cbb78e.hcp.uksouth.azmk8s.io\""
4. Конфигурация kubernetes
Этот метод авторизации обращается к API Kubernetes TokenReview для проверки того, что предоставленный JWT все еще действителен. Kubernetes должен быть запущен с параметром --service-account-lookup. Начиная с Kubernetes 1.7 по умолчанию установлено значение true. В противном случае удаленные токены в Kubernetes не будут должным образом отозваны и смогут аутентифицироваться в этом методе авторизации.
Учетные записи служб, используемые в этом методе аутентификации, должны иметь доступ к API TokenReview. Если Kubernetes настроена на использование ролей RBAC, учетной записи службы должны быть предоставлены разрешения на доступ к этому API. Следующий пример ClusterRoleBinding может быть использован для предоставления этих разрешений:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: role-tokenreview-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: starvault-auth
namespace: default
5. API
Плагин Kubernetes Auth имеет полноценный HTTP API. Более подробную информацию можно найти в документации по API.
6. Пример кода
Следующий пример демонстрирует метод Kubernetes для аутентификации в StarVault.
package main
import (
"fmt"
"os"
vault "github.com/hashicorp/vault/api"
auth "github.com/hashicorp/vault/api/auth/kubernetes"
)
// Fetches a key-value secret (kv-v2) after authenticating to Vault with a Kubernetes service account.
// For a more in-depth setup explanation, please see the relevant readme in the hashicorp/vault-examples repo.
func getSecretWithKubernetesAuth() (string, error) {
// If set, the VAULT_ADDR environment variable will be the address that
// your pod uses to communicate with Vault.
config := vault.DefaultConfig() // modify for more granular configuration
client, err := vault.NewClient(config)
if err != nil {
return "", fmt.Errorf("unable to initialize Vault client: %w", err)
}
// The service-account token will be read from the path where the token's
// Kubernetes Secret is mounted. By default, Kubernetes will mount it to
// /var/run/secrets/kubernetes.io/serviceaccount/token, but an administrator
// may have configured it to be mounted elsewhere.
// In that case, we'll use the option WithServiceAccountTokenPath to look
// for the token there.
k8sAuth, err := auth.NewKubernetesAuth(
"dev-role-k8s",
auth.WithServiceAccountTokenPath("path/to/service-account-token"),
)
if err != nil {
return "", fmt.Errorf("unable to initialize Kubernetes auth method: %w", err)
}
authInfo, err := client.Auth().Login(context.TODO(), k8sAuth)
if err != nil {
return "", fmt.Errorf("unable to log in with Kubernetes auth: %w", err)
}
if authInfo == nil {
return "", fmt.Errorf("no auth info was returned after login")
}
// get secret from Vault, from the default mount path for KV v2 in dev mode, "secret"
secret, err := client.KVv2("secret").Get(context.Background(), "creds")
if err != nil {
return "", fmt.Errorf("unable to read secret: %w", err)
}
// data map can contain more than one key-value pair,
// in this case we're just grabbing one of them
value, ok := secret.Data["password"].(string)
if !ok {
return "", fmt.Errorf("value type assertion failed: %T %#v", secret.Data["password"], secret.Data["password"])
}
return value, nil
}
using System;
using System.IO;
using VaultSharp;
using VaultSharp.V1.AuthMethods;
using VaultSharp.V1.AuthMethods.Kubernetes;
using VaultSharp.V1.Commons;
namespace Examples
{
public class KubernetesAuthExample
{
const string DefaultTokenPath = "path/to/service-account-token";
// Fetches a key-value secret (kv-v2) after authenticating to Vault with a Kubernetes service account.
// For a more in-depth setup explanation, please see the relevant readme in the hashicorp/vault-examples repo.
public string GetSecretWithK8s()
{
var vaultAddr = Environment.GetEnvironmentVariable("VAULT_ADDR");
if(String.IsNullOrEmpty(vaultAddr))
{
throw new System.ArgumentNullException("Vault Address");
}
var roleName = Environment.GetEnvironmentVariable("VAULT_ROLE");
if(String.IsNullOrEmpty(roleName))
{
throw new System.ArgumentNullException("Vault Role Name");
}
// Get the path to service account token or fall back on default path
string pathToToken = String.IsNullOrEmpty(Environment.GetEnvironmentVariable("SA_TOKEN_PATH")) ? DefaultTokenPath : Environment.GetEnvironmentVariable("SA_TOKEN_PATH");
string jwt = File.ReadAllText(pathToToken);
IAuthMethodInfo authMethod = new KubernetesAuthMethodInfo(roleName, jwt);
var vaultClientSettings = new VaultClientSettings(vaultAddr, authMethod);
IVaultClient vaultClient = new VaultClient(vaultClientSettings);
// We can retrieve the secret after creating our VaultClient object
Secret<SecretData> kv2Secret = null;
kv2Secret = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(path: "/creds").Result;
var password = kv2Secret.Data.Data["password"];
return password.ToString();
}
}
}