Оптимізація DevOps-процесів за допомогою єдиного входу (SSO): переваги, проблеми та практичні приклади
У кращих практихах DevOps безпроблемна інтеграція єдиного входу (Single Sign-On, SSO) стає ключовим фактором підвищення ефективності, безпеки та зручності користувачів. Оскільки організації прагнуть пришвидшити розробку і доставку програмного забезпечення, важливість уніфікованого та безпечного механізму автентифікації неможливо переоцінити.
Єдиний вхід не тільки спрощує керування доступом, дозволяючи користувачам входити один раз і отримувати доступ до кількох систем, але й також відіграє вирішальну роль у посиленні загальних заходів кібербезпеки.
У цій статті розглядається перетин DevOps і SSO, а також описуються переваги, проблеми та практики, які виникають під час інтеграції єдиного входу в структуру робочого процесу проєкту.
Насамперед визначивши необхідність упровадження єдиного входу для всіх застосунків і на всіх рівнях, де це можливо, потрібно ретельно оглянути програми та сервіси, які використовуються в проєкті. Розгляньмо рішення, які використовує моя команда, розподіливши їх за рівнями складності внесення змін і рівнем ієрархії у проєкті.
Розпочнемо із застосунків: Grafana для моніторингу, Jenkins для безперервної інтеграції (CI) й Argo CD для безперервної доставки (CD). Далі йде Amazon EKS, оскільки всі зазначені інструменти розгортаються саме в ньому, а налаштування доступу до нього виявляється більш складним завданням.
Завершимо ми не менш важливим налаштуванням платформи Amazon Web Services (AWS), де нам доведеться забезпечити доступ багатьом користувачам до десятків облікових записів організації. Водночас на всіх рівнях застосовується принцип найменших привілеїв, що стверджує, що особам має бути дозволено лише найменший набір дій, необхідних для виконання конкретного завдання.
Grafana
Як один з інструментів логування та моніторингу ми використовуємо Prometheus & Grafana у вигляді Helm
-чарта kube-prometheus-stack
. Оскільки автоматизація — це запорука успіху, всі налаштування будуть проводитися в Terraform у файлі values.yaml
, де власне конфігурується застосунок.
resource "helm_release" "kube_prometheus_stack" {
name = "kube-prometheus-stack"
chart = "kube-prometheus-stack"
version = "48.3.0"
repository = "https://prometheus-community.github.io/helm-charts"
namespace = "monitoring"
create_namespace = true
values = [
templatefile("chart_values/values.yaml", {
grafana_sso_client = data.aws_secretsmanager_secret_version.grafana_sso_client_id_version.secret_string,
grafana_sso_secret = data.aws_secretsmanager_secret_version.grafana_sso_client_secret_version.secret_string,
tenant = data.aws_secretsmanager_secret_version.tenant_id_version.secret_string
})
]
}
resource "aws_secretsmanager_secret" "grafana_sso_client_id" {
name = "grafana_sso_client_id"
}
data "aws_secretsmanager_secret" "grafana_sso_client_id_data" {
arn = aws_secretsmanager_secret.grafana_sso_client_id.arn
}
data "aws_secretsmanager_secret_version" "grafana_sso_client_id_version" {
secret_id = data.aws_secretsmanager_secret.grafana_sso_client_id_data.id
}
resource "aws_secretsmanager_secret" "grafana_sso_client_secret" {
name = "grafana_sso_client_secret"
}
data "aws_secretsmanager_secret" "grafana_sso_client_secret_data" {
arn = aws_secretsmanager_secret.grafana_sso_client_secret.arn
}
data "aws_secretsmanager_secret_version" "grafana_sso_client_secret_version" {
secret_id = data.aws_secretsmanager_secret.grafana_sso_client_secret_data.id
}
resource "aws_secretsmanager_secret" "tenant_id" {
name = "tenant_id"
}
data "aws_secretsmanager_secret" "tenant_id_data" {
arn = aws_secretsmanager_secret.tenant_id.arn
}
data "aws_secretsmanager_secret_version" "tenant_id_version" {
secret_id = data.aws_secretsmanager_secret.tenant_id_data.id
}
Але для того, щоб розпочати налаштування, необхідно мати групу в постачальнику ідентифікаційних даних (IdP
). У нашому випадку в ролі IdP
використовується Azure AD.
В Azure нам необхідно створити застосунок у тенанті нашої організації. У цій аплікації ми створюємо групу та додаємо користувачів, яким хочемо дати можливість входити до користувацького інтерфейсу (UI).
Після маніпуляцій в IdP
необхідно передати значення Tenant
, Client ID
і Client Secret
. Це зручно та безпечно робити завдяки AWS-сервісу Secrets Manager, у якому ми будемо зберігати наші значення для SSO.
Також деякі із цих значень будуть використані повторно, оскільки Tenant
створюється на всю організацію і його значення не змінюється.
Технічні деталі
Створення застосунку в Azure AD. Щоб створити застосунок в Azure AD, виконайте такі дії:
- Відкрийте портал Azure.
- У лівому меню перейдіть до розділу Azure Active Directory.
- У розділі Застосунки натисніть кнопку Створити застосунок.
- У списку типів застосунків виберіть
Web app/API
. - Введіть ім’я застосунку та натисніть кнопку Створити.
Після створення застосунку Azure AD надасть вам такі значення:
- Client ID;
- Client Secret;
- Tenant ID.
Зберігання значень в Secrets Manager. Щоб зберегти значення в Secrets Manager, виконайте такі дії:
- Після виконання команди
terraform apply
в лівому меню консолі AWS перейдіть до розділу Secrets Manager. - Знайдіть новостворенний секрет.
- У полі Значення секрету введіть відповідні значення, отримані в Azure AD.
- Натисніть кнопку Зберегти.
Налаштування Grafana. Щоб налаштувати Grafana, виконайте такі дії:
- Відкрийте файл
values.yaml
для Helm-чартаkube-prometheus-stack
. - Знайдіть розділ
grafana
. - У полі
server.auth.provider
виберітьAzure AD
. - У полі
server.auth.azuread.tenantId
введіть значенняTenant ID
, отримане вAzure AD
. - У полі
server.auth.azuread.clientId
введіть значенняClient ID
, отримане вAzure AD
. - У полі
server.auth.azuread.clientSecret
введіть значенняClient secret
, отримане вAzure AD
. - Збережіть файл
values.yaml.
grafana:
grafana.ini:
auth.azuread:
name: Azure AD
enabled: true
allow_sign_up: true
auto_login: false
client_id: ${grafana_sso_client}
client_secret: ${grafana_sso_secret}
scopes: openid email profile
auth_url: https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize
token_url: https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token
allowed_organizations: ${tenant}
role_attribute_strict: false
allow_assign_grafana_admin: false
skip_org_role_sync: false
use_pkce: true
Після виконання цих кроків Grafana буде налаштована на використання SSO з Azure AD. Користувачі, які належать до групи, створеної в Azure AD, зможуть входити до Grafana, використовуючи свої облікові записи Azure AD.
Під час входу в Grafana UI у вас зʼявиться вибір, яким способом залогінитись, й обравши Azure AD, ви авторизуєтесь, використовуючи ваш обліковий запис Microsoft.
Jenkins
Jenkins — це сервер, який підтримує концепцію Continuous Integration. Він написаний на Java, але працює з будь-якими мовами. Цей інструмент збере проєкт згідно з вашими інструкціями та виконає деплой на сервер, який ви прив’язали до нього.
Jenkins дозволяє автоматизувати частину процесу розробки програмного забезпечення без участі людини. Ця система призначена для забезпечення процесу безперервної інтеграції програмного забезпечення. Також із створенням Jenkins helm
необхідно за аналогією до Grafana створити застосунок у Azure AD та секрет, у якому ми зберігаємо значення Client ID, Client Secret, Tenant ID.
resource "helm_release" "jenkins" {
name = "jenkins"
namespace = var.namespace_devops
chart = "jenkins"
repository = "https://charts.jenkins.io"
values = [templatefile("files/values/jenkins.yaml", {
site = var.site,
client_id = jsondecode(data.aws_secretsmanager_secret_version.jenkins_sso_secrets_version.secret_string)["Client_ID"],
client_secret = jsondecode(data.aws_secretsmanager_secret_version.jenkins_sso_secrets_version.secret_string)["Client_Secret"],
tenant_id = jsondecode(data.aws_secretsmanager_secret_version.jenkins_sso_secrets_version.secret_string)["Tenant_ID"]
})]
wait = false
}
# Jenkins SSO secret
resource "aws_secretsmanager_secret" "jenkins_sso_secrets" {
name = "jenkins_sso_secrets"
}
data "aws_secretsmanager_secret" "jenkins_sso_secrets_data" {
arn = aws_secretsmanager_secret.jenkins_sso_secrets.arn
}
data "aws_secretsmanager_secret_version" "jenkins_sso_secrets_version" {
secret_id = data.aws_secretsmanager_secret.jenkins_sso_secrets_data.id
}
Плагіни розширюють функціональність Jenkins. Їх існує тисячі, різних: від зображень з Чаком Норрісом до справді важливих речей.
Сам собою сервер порожній, і навіть Git потрібно налаштовувати через такі розширення. У цьому немає нічого складного — достатньо завантажити потрібний плагін. Припустимо, що ваш проєкт на Python і ви хочете знайти для нього розширення. Вводите ключове слово у пошуку й отримуєте список плагінів:
Для налаштування єдиного входу нам також необхідно встановити плагін Microsoft Entra ID (previously Azure AD).
Це виконується в Helm values
-файлі.
Щоб не налаштовувати плагін після кожного перезапуску аплікації, важливим є нюанс: вам необхідно слідкувати за версіями плагінів, оскільки не всі вони сумісні й треба обирати, враховуючи версію самого Jenkins. У іншому разі застосунок може не запуститись або працювати некоректно.
Встановлення плагіну azure-ad
та його налаштування необхідно зробити за аналогією з продемострованним кодом й передавши у змінних ваші значення Azure AD:
controller:
jenkinsUrl: https://jenkins.${site}
installLatestPlugins: false
installPlugins:
- azure-ad:385.v5d9f88612dd2
JCasC:
securityRealm: |-
azure:
cacheDuration: 3600
clientId: "${client_id}"
clientSecret: "${client_secret}"
tenant: "${tenant_id}"
authorizationStrategy: |-
loggedInUsersCanDoAnything:
allowAnonymousRead: false
configScripts:
Після прийняття змін й перестворення поду Jenkins вам необхідно буде увійти під вашим обліковим записом Microsoft. Якщо у консолі ви перейдете Dashboard > Сonfigure Jenkins > Security, то зможете побачити ваші налаштування з Azure AD, які додавались у конфігураційному файлі Jenkins Helm і завдяки яким працює SSO в цьому застосунку.
Argo CD
Argo CD став потужним та одним з основних інструментів для автоматизації розгортання застосунків і використовується багатьма організаціями, зокрема Alibaba, Cisco та Indeed. Імплементація системи єдиного входу (SSO) для Argo CD через такі популярні платформи, як-от Microsoft, Google, Auth0 та інші IdP, покликане спростити роботу DevOps-інженера або розробника та підвищити безпеку доступу.
У контексті єдиного входу в Argo CD, Dex займає центральне місце як постачальник ідентифікації та автентифікації з відкритим кодом. Він відіграє ключову роль у з’єднанні ваших застосунків з різноманітними постачальниками ідентифікаційної інформації, такими як LDAP, SAML і OAuth2, одночасно реалізуючи основний протокол OpenID Connect (OIDC).
Важливо, що коли ви вирішуєте встановити Argo CD за допомогою діаграми Helm
або маніфесту YAML
, Dex
постачається в комплекті, що спрощує налаштування безперебійної функції єдиного входу. Щоб налаштувати єдиний вхід для Argo CD, вам необхідно створити застосунок в Azure AD і отримати значення Client ID, Tenant ID
та CaCert
.
Після цього ви можете налаштувати конфігурацію Argo CD, використовуючи наступні кроки.
Створіть конфігурацію Helm, як у прикладі нижче:
resource "helm_release" "argocd" {
name = "argo-cd"
repository = "https://argoproj.github.io/argo-helm"
chart = "argo-cd"
namespace = "argocd"
version = "5.43.3"
create_namespace = true
reset_values = true
values = [templatefile("files/values/argocd.yaml", {
argocd_site_name = local.argocd_site_name,
argocd_sso_certificate = data.aws_secretsmanager_secret_version.argocd_sso_certificate_version.secret_string,
argocd_sso_url = jsondecode(data.aws_secretsmanager_secret_version.argocd_sso_version.secret_string)["SSO_URL"],
argocd_sso_group = jsondecode(data.aws_secretsmanager_secret_version.argocd_sso_version.secret_string)["USER_GROUP"]
})]
}
Створіть секрети в AWS Secrets Manager, які містять значення Client ID
, Tenant ID
та CaCert
.
# ArgoCD SSO secrets
resource "aws_secretsmanager_secret" "argocd_sso" {
name = "argocd_sso"
}
data "aws_secretsmanager_secret" "argocd_sso_data" {
arn = aws_secretsmanager_secret.argocd_sso.arn
}
data "aws_secretsmanager_secret_version" "argocd_sso_version" {
secret_id = data.aws_secretsmanager_secret.argocd_sso_data.id
}
resource "aws_secretsmanager_secret" "argocd_sso_certificate" {
name = "argocd_sso_certificate"
}
data "aws_secretsmanager_secret" "argocd_sso_certificate_data" {
arn = aws_secretsmanager_secret.argocd_sso_certificate.arn
}
data "aws_secretsmanager_secret_version" "argocd_sso_certificate_version" {
secret_id = data.aws_secretsmanager_secret.argocd_sso_certificate_data.id
}
Налаштуйте конфігурацію Argo CD, використовуючи такі параметри:
argocd_site_name
: Ім’я вебсайту (Host) Argo CD.argocd_sso_certificate
: Кодований уBase64
сертифікат підписуSAML
.argocd_sso_url
: URL-адреса служби єдиного входу.argocd_sso_group
: ID групи користувачів, яким надається доступ до Argo CD.
3.1 Налаштуйте права доступу користувачам, яким надаєте доступ до Argo CD.
configs:
cm:
create: true
url: https://${argocd_site_name}
dex.config: |
logger:
level: debug
format: json
connectors:
- type: saml
id: saml
name: saml
config:
entityIssuer: https://${argocd_site_name}/api/dex/callback
ssoURL: ${argocd_sso_url}
caData: |
${argocd_sso_certificate}
redirectURI: https://${argocd_site_name}/api/dex/callback
usernameAttr: email
emailAttr: email
groupsAttr: Group
rbac:
create: true
policy.csv: |
p, role:devops, applications, *, */*, allow
p, role:devops, clusters, get, *, allow
p, role:devops, repositories, get, *, allow
p, role:devops, repositories, create, *, allow
p, role:devops, repositories, update, *, allow
p, role:devops, projects, get, *, allow
p, role:devops, projects, create, *, allow
p, role:devops, projects, update, *, allow
p, role:devops, logs, get, *, allow
p, role:devops, exec, create, */*, allow
g, "${argocd_sso_group}", role:devops
Після конфігурації Argo CD Helm
під час спроби ввійти у застосунок у вас зʼявиться альтернативний варіант входу, використовуючи SAML
.
Amazon EKS
Щоб налаштувати SSO в інфраструктурі Kubernetes, дотримуйтесь наведених нижче кроків, які детально описують конфігурацію Terraform, необхідну для реалізації OIDC у нашому кластері EKS. Додамо ресурс постачальника ідентифікаційної інформації:
resource "aws_eks_identity_provider_config" "eks_identity_provider" {
cluster_name = terraform.workspace
oidc {
client_id = jsondecode(data.aws_secretsmanager_secret_version.eks_sso_secret_version.secret_string)["CLIENT_ID"]
groups_claim = "groups"
groups_prefix = "aad:"
identity_provider_config_name = "AzureAD"
issuer_url = "https://sts.windows.net/${data.aws_secretsmanager_secret_version.tenant_id_version.secret_string}/"
username_claim = "upn"
username_prefix = "aad:"
}
timeouts {
create = "2h"
delete = "2h"
}
}
Тайм-аути тут є важливими, тому що стандартні параметри здавалися недостатньо довгими для успішного завершення конфігурації. Тепер нам потрібно додати ClusterRoleBindings
або RoleBindings
до кластера, щоб після автентифікації користувачі мали доступ для взаємодії з кластером, приклад чого можна побачити нижче.
# Cluster role for developers
resource "kubernetes_cluster_role" "dev"
metadata {
name = "dev"
}
rule {
api_groups = ["*"]
resources = ["*"]
verbs = ["get", "list", "watch"]
}
}
# Cluster role binding for Azure users
resource "kubernetes_cluster_role_binding" "sso_dev_users_cluster_role_binding" {
metadata {
name = "sso-dev"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "ClusterRole"
name = "dev"
}
subject {
api_group = "rbac.authorization.k8s.io"
kind = "Group"
name = "aad:${local.dev-sso-group}"
}
}
Перед назвою групи має бути префікс aad
, щоб відповідати префіксу, який ми додали як частину конфігурації EKS у рядку з username_prefix
цієї реалізації. Гарною практикою є перед будь-якими прив’язками ClusterRole/Role
додати ім’я, яке ви запам’ятаєте, щоб спершу об’єднати всі прив’язки разом під час їх переліку, а також зробити очевидним, що ви повинні використовувати SSO, щоб використовувати їх.
Для автентифікації ми використовуємо kubelogin. Перш за все потрібно встановити плагін kubectl krew install oidc-login
.
По-друге, вам потрібно автентифікуватись за допомогою такої команди:
kubectl oidc-login setup \
--oidc-issuer-url https://sts.windows.net/<Tenant ID>/ \
--oidc-client-id CLIENT_ID \
--oidc-client-secret CLIENT_SECRET
Наведена вище команда виводить ваш маркер JWT
для підтвердження того, що ви успішно пройшли автентифікацію в Azure. Далі вам потрібно додати до вашого файлу kubeconfig
, розташованого за адресою ~/.kube/config:
apiVersion: v1
kind: Config
clusters:
- name: arn:aws:eks:<aws_region>:<aws_acc_id>:cluster/<cluster_name>
cluster:
server: https://***.gr7.<aws_region>.eks.amazonaws.com
certificate-authority-data: >-
***
insecure-skip-tls-verify: false
users:
- name: oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- oidc-login
- get-token
- >-
--oidc-issuer-url=https://sts.windows.net/<Tenant ID>/
- '--oidc-client-id=<CLIENT_ID>'
- '--oidc-client-secret=<CLIENT_SECRET>'
command: kubectl
env: null
interactiveMode: IfAvailable
provideClusterInfo: false
contexts: []
preferences: {}
current-context: arn:aws:eks:<aws_region>:<aws_acc_id>:cluster/<cluster_name>
Щоб впевнитися, що нова конфігурація працює, можемо звернутись до кластера командою по типу kubectl --user=oidc get nodes
. Після того, як ви впевнились, що у вас все працює та ви підключили всіх необхдних користувачів до кластеру, додавши їх у відведену для цього групу, можете видалити їх IAM користувачів з кластеру.
Amazon Web Services
AWS пропонує кілька способів налаштувати єдиний вхід для своїх послуг. Один з них — використовувати службу AWS Identity and Access Management (IAM) для створення ролей і прив’язок ролей, які надають користувачам доступ до певних ресурсів AWS.
Інший спосіб (основний) — використовувати постачальника ідентифікаційної інформації (IdP), такий як Azure AD або Okta, для аутентифікації користувачів і надання їм доступу до ресурсів AWS. Для нашого способу підʼєднання нам знадобиться root-акаунт організації, бо саме в ньому будуть відбуватися налаштування Single Sign-On на стороні AWS і саме з нього регулюється рівень доступу до інших акаунтів організації.
Перш за все необхідно в Microsoft Azure зайти в Azure AD, створити Enterprice application і додати в нього групи з користувачами.
Створивши застосунок для AWS у вкладці Single Sign-on, потрібно завантажити Federation Metadata XML, який нам знадобиться для IAM Identity Center. У головному акаунті організації переходимо до IAM Identity Center і вмикаємо його, натискаючи на відповідну кнопку.
Увімкнувши IAM Identity Center в головному акаунті організації, наступним кроком необхідно перейти в налаштування й у вкладці Choose identity source обрати пункт External identity provider.
Далі необхідно обмінятись SAML metadata між AWS і Azure AD, для чого додаємо Federation Metadata XML у консолі AWS й зберігаємо файл Service provider metadata, щоб потім перенести його у додаток, створенний в Azure AD.
Також для автоматизованої синхронізації користувачів між Azure AD і AWS потрібно у налаштуваннях IAM Identity Center у пункті Provisioning увімкнути автоматичну синхронізацію, скопіювавши SCIM endpoint й Access token, щоб додати його до аплікації в Microsoft Azure.
Перейшовши до Microsoft Azure в аплікації, яка створена для AWS у вкладці Single Sign-on, потрібно загрузити раніше встановлений Service provider metadata. Щоб увімкнути автоматичну синхронізацію, перемикаємо режим на автоматичний, вставляємо раніше скопійовані значення SCIM endpoint й Access token і натискаємо кнопку Test connection. Якщо на рівні з полями значень ви бачите відповідні галочки, значить зʼєднання встановлене.
Отже тепер SSO налаштоване, й у мірі додавання груп та користувачів до цієї аплікації вони будуть автоматично переноситись й в AWS IAM Identity Center.
Без змін цей механізм працює з видаленням, тобто, якщо користувача прибрати в Azure AD, за наступної синхронізації він видалиться. Автоматична синхронізація працює з деякою періодичністю, тож щоб зміни синхронізувалися, потрібно або зачекати, або провести синхронізацію власноруч, якщо це терміново.
Як тільки в консолі у вас зʼявились групи й користувачі, можете переходити до налаштування доступу, памʼятаючи про принцип найменших привілеїв під час розподілення ролей й доступів до акаунтів. Також гарною практикою є зменшення часу дії токену, який надається користувачу під час аутентифікації.
Перевіривши ролі й інші конфігурації, тепер можна відмовитись від використання IAM користувачів в акаунтах вашої організації, що значно покращує рівень безпеки інфраструктури, централізує керування обліковими записами й полегшує комунікацію у вашій команді, замінивши десятки паролів й відповідних MFA на один логін і пароль від пошти та відповідний двофакторний аутентифікатор.
4 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів