Проблеми безпеки
Неправильна автентифікація кінцевого користувача
В Istio ви можете включити автентифікацію для кінцевих користувачів через політики автентифікації запитів. Дотримуйтесь цих кроків для усунення несправностей у специфікації політики.
Якщо
jwksUri
не вказано, переконайтеся, що видавець JWT має формат url, і щоurl + /.well-known/openid-configuration
можна відкрити в оглядачі; наприклад, якщо видавець JWT —https://accounts.google.com
, переконайтеся, щоhttps://accounts.google.com/.well-known/openid-configuration
є дійсним url і його можна відкрити в браузері.apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: "example-3" spec: selector: matchLabels: app: httpbin jwtRules: - issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/jwks.json"
Якщо токен JWT розміщено в заголовку Authorization у http запитах, переконайтеся, що токен JWT є дійсним (не прострочений тощо). Поля в токені JWT можна декодувати за допомогою онлайн інструментів для парсингу JWT, наприклад, jwt.io.
Перевірте конфігурацію проксі Envoy для цільового навантаження, використовуючи команду
istioctl proxy-config
.З застосованою вище політикою використовуйте наступну команду для перевірки конфігурації
listener
на вхідному порту80
. Ви повинні побачити фільтрenvoy.filters.http.jwt_authn
з налаштуваннями, що відповідають видавцю та JWKS, як зазначено в політиці.$ POD=$(kubectl get pod -l app=httpbin -n foo -o jsonpath={.items..metadata.name}) $ istioctl proxy-config listener ${POD} -n foo --port 80 --type HTTP -o json <redacted> { "name": "envoy.filters.http.jwt_authn", "typedConfig": { "@type": "type.googleapis.com/envoy.config.filter.http.jwt_authn.v2alpha.JwtAuthentication", "providers": { "origins-0": { "issuer": "testing@secure.istio.io", "localJwks": { "inlineString": "*redacted*" }, "payloadInMetadata": "testing@secure.istio.io" } }, "rules": [ { "match": { "prefix": "/" }, "requires": { "requiresAny": { "requirements": [ { "providerName": "origins-0" }, { "allowMissing": {} } ] } } } ] } }, <redacted>
Авторизація занадто обмежувальна або надто ліберальна
Переконайтесь, що в YAML файлі політики немає помилок
Одна з поширених помилок — це випадкове вказання кількох елементів у YAML. Розглянемо наступну політику як приклад:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: example
namespace: foo
spec:
action: ALLOW
rules:
- to:
- operation:
paths:
- /foo
- from:
- source:
namespaces:
- foo
Ви можете очікувати, що політика дозволить запити, якщо шлях /foo
і простір імен джерела foo
. Однак, насправді політика дозволяє запити, якщо шлях /foo
або простір імен джерела foo
, що є більш ліберальним.
У синтаксисі YAML, -
перед from:
означає, що це новий елемент у списку. Це створює 2 правила в політиці замість 1. В політиці авторизації кілька правил мають семантику OR
.
Щоб виправити проблему, просто видаліть зайвий -
, щоб політика мала тільки 1 правило, яке дозволяє запити, якщо шлях /foo
і простір імен джерела foo
, що є більш обмежувальним.
Переконайтесь, що ви НЕ використовуєте тільки HTTP-поля на TCP портах
Політика авторизації буде більш обмежувальною, оскільки тільки HTTP-поля (наприклад, host
, path
, headers
, JWT тощо) не існують у чистих TCP зʼєднаннях.
У випадку політики ALLOW
ці поля ніколи не збігаються. У випадку дій DENY
і CUSTOM
ці поля вважаються завжди збігаються. Остаточний ефект — це більш обмежувальна політика, яка може спричинити несподівані відмови.
Перевірте визначення сервісу Kubernetes, щоб переконатися, що порт названий правильним протоколом. Якщо ви використовуєте тільки HTTP-поля на порту, переконайтесь, що імʼя порту має префікс http-
.
Переконайтесь, що політика застосована до правильних цілей
Перевірте селектор навантаження і простір імен, щоб підтвердити, що вона застосована до правильних цілей. Ви можете визначити діючу політику авторизації, запустивши istioctl x authz check POD-NAME.POD-NAMESPACE
.
Зверніть увагу на дію, зазначену в політиці
Якщо не вказано, стандартна політика використовує дію
ALLOW
.Коли навантаження має кілька дій (
CUSTOM
,ALLOW
іDENY
), застосованих одночасно, всі дії повинні бути задоволені, щоб дозволити запит. Іншими словами, запит відхиляється, якщо будь-яка з дій відмовляє, і дозволяється тільки якщо всі дії дозволяють.Дія
AUDIT
не забезпечує контроль доступу і не відхиляє запит у будь-яких випадках.
Читайте неявне включення авторизації для отримання докладної інформації про порядок оцінки.
Переконайтесь, що Istiod приймає політики
Istiod конвертує та розподіляє ваші політики авторизації до проксі. Наступні кроки допоможуть переконатися, що Istiod працює як очікується:
Запустіть наступну команду для включення журналювання налагодження в istiod:
$ istioctl admin log --level authorization:debug
Отримайте журнал Istiod за допомогою наступної команди:
$ kubectl logs $(kubectl -n istio-system get pods -l app=istiod -o jsonpath='{.items[0].metadata.name}') -c discovery -n istio-system
Перевірте вивід і переконайтеся, що помилок немає. Наприклад, ви можете побачити щось подібне до наступного:
2021-04-23T20:53:29.507314Z info ads Push debounce stable[31] 1: 100.981865ms since last change, 100.981653ms since last push, full=true 2021-04-23T20:53:29.507641Z info ads XDS: Pushing:2021-04-23T20:53:29Z/23 Services:15 ConnectedEndpoints:2 Version:2021-04-23T20:53:29Z/23 2021-04-23T20:53:29.507911Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details: * found 0 CUSTOM actions 2021-04-23T20:53:29.508077Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details: * found 0 CUSTOM actions 2021-04-23T20:53:29.508128Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details: * found 1 DENY actions, 0 ALLOW actions, 0 AUDIT actions * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on HTTP filter chain successfully * built 1 HTTP filters for DENY action * added 1 HTTP filters to filter chain 0 * added 1 HTTP filters to filter chain 1 2021-04-23T20:53:29.508158Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details: * found 0 DENY actions, 0 ALLOW actions, 0 AUDIT actions 2021-04-23T20:53:29.509097Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details: * found 0 CUSTOM actions 2021-04-23T20:53:29.509167Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details: * found 0 DENY actions, 0 ALLOW actions, 0 AUDIT actions 2021-04-23T20:53:29.509501Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details: * found 0 CUSTOM actions 2021-04-23T20:53:29.509652Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details: * found 1 DENY actions, 0 ALLOW actions, 0 AUDIT actions * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on HTTP filter chain successfully * built 1 HTTP filters for DENY action * added 1 HTTP filters to filter chain 0 * added 1 HTTP filters to filter chain 1 * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on TCP filter chain successfully * built 1 TCP filters for DENY action * added 1 TCP filters to filter chain 2 * added 1 TCP filters to filter chain 3 * added 1 TCP filters to filter chain 4 2021-04-23T20:53:29.510903Z info ads LDS: PUSH for node:curl-557747455f-6dxbl.foo resources:18 size:85.0kB 2021-04-23T20:53:29.511487Z info ads LDS: PUSH for node:httpbin-74fb669cc6-lpscm.foo resources:18 size:86.4kB
Це показує, що Istiod згенерував:
Конфігурацію HTTP-фільтра з політикою
ns[foo]-policy[deny-path-headers]-rule[0]
для навантаженняhttpbin-74fb669cc6-lpscm.foo
.Конфігурацію TCP-фільтра з політикою
ns[foo]-policy[deny-path-headers]-rule[0]
для навантаженняhttpbin-74fb669cc6-lpscm.foo
.
Переконайтесь, що Istiod коректно розподіляє політики до проксі
Istiod розподіляє політики авторизації до проксі. Наступні кроки допоможуть вам переконатися, що Istiod працює як очікується:
Запустіть наступну команду, щоб отримати дамп конфігурації проксі для навантаження
httpbin
:$ kubectl exec $(kubectl get pods -l app=httpbin -o jsonpath='{.items[0].metadata.name}') -c istio-proxy -- pilot-agent request GET config_dump
Перевірте журнал і переконайтеся, що:
- Журнал містить фільтр
envoy.filters.http.rbac
для забезпечення політики авторизації на кожен вхідний запит. - Istio оновлює фільтр відповідно після оновлення вашої політики авторизації.
- Журнал містить фільтр
Наступний вивід означає, що проксі
httpbin
активував фільтрenvoy.filters.http.rbac
з правилами, які забороняють будь-кому доступ до шляху/headers
.{ "name": "envoy.filters.http.rbac", "typed_config": { "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", "rules": { "action": "DENY", "policies": { "ns[foo]-policy[deny-path-headers]-rule[0]": { "permissions": [ { "and_rules": { "rules": [ { "or_rules": { "rules": [ { "url_path": { "path": { "exact": "/headers" } } } ] } } ] } } ], "principals": [ { "and_ids": { "ids": [ { "any": true } ] } } ] } } }, "shadow_rules_stat_prefix": "istio_dry_run_allow_" } },
Переконайтесь, що проксі коректно застосовують політики
Проксі зрештою застосовують політики авторизації. Наступні кроки допоможуть вам переконатися, що проксі працює як очікується:
Увімкніть журналювання налагодження авторизації в проксі за допомогою наступної команди:
$ istioctl proxy-config log deploy/httpbin --level "rbac:debug"
Перевірте, чи ви бачите наступний вихід:
active loggers: ... ... rbac: debug ... ...
Надішліть кілька запитів до навантаження
httpbin
, щоб згенерувати журнали.Виведіть журнали проксі за допомогою наступної команди:
$ kubectl logs $(kubectl get pods -l app=httpbin -o jsonpath='{.items[0].metadata.name}') -c istio-proxy
Перевірте вивід і переконайтеся, що:
У виводі журналу показано або
enforced allowed
, абоenforced denied
, залежно від того, чи запит був дозволений або відхилений відповідно.Ваша політика авторизації очікує дані, отримані з запиту.
Наступний приклад виводу для запиту на шляху
/httpbin
:... 2021-04-23T20:43:18.552857Z debug envoy rbac checking request: requestedServerName: outbound_.8000_._.httpbin.foo.svc.cluster.local, sourceIP: 10.44.3.13:46180, directRemoteIP: 10.44.3.13:46180, remoteIP: 10.44.3.13:46180,localAddress: 10.44.1.18:80, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/foo/sa/curl, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'httpbin:8000' ':path', '/headers' ':method', 'GET' ':scheme', 'http' 'user-agent', 'curl/7.76.1-DEV' 'accept', '*/*' 'x-forwarded-proto', 'http' 'x-request-id', '672c9166-738c-4865-b541-128259cc65e5' 'x-envoy-attempt-count', '1' 'x-b3-traceid', '8a124905edf4291a21df326729b264e9' 'x-b3-spanid', '21df326729b264e9' 'x-b3-sampled', '0' 'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=d64cd6750a3af8685defbbe4dd8c467ebe80f6be4bfe9ca718e81cd94129fc1d;Subject="";URI=spiffe://cluster.local/ns/foo/sa/curl' , dynamicMetadata: filter_metadata { key: "istio_authn" value { fields { key: "request.auth.principal" value { string_value: "cluster.local/ns/foo/sa/curl" } } fields { key: "source.namespace" value { string_value: "foo" } } fields { key: "source.principal" value { string_value: "cluster.local/ns/foo/sa/curl" } } fields { key: "source.user" value { string_value: "cluster.local/ns/foo/sa/curl" } } } } 2021-04-23T20:43:18.552910Z debug envoy rbac enforced denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0] ...
Запис
enforced denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
означає, що запит відхилено політикоюns[foo]-policy[deny-path-headers]-rule[0]
.Наступний приклад виводу для політики авторизації у режимі dry-run:
... 2021-04-23T20:59:11.838468Z debug envoy rbac checking request: requestedServerName: outbound_.8000_._.httpbin.foo.svc.cluster.local, sourceIP: 10.44.3.13:49826, directRemoteIP: 10.44.3.13:49826, remoteIP: 10.44.3.13:49826,localAddress: 10.44.1.18:80, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/foo/sa/curl, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'httpbin:8000' ':path', '/headers' ':method', 'GET' ':scheme', 'http' 'user-agent', 'curl/7.76.1-DEV' 'accept', '*/*' 'x-forwarded-proto', 'http' 'x-request-id', 'e7b2fdb0-d2ea-4782-987c-7845939e6313' 'x-envoy-attempt-count', '1' 'x-b3-traceid', '696607fc4382b50017c1f7017054c751' 'x-b3-spanid', '17c1f7017054c751' 'x-b3-sampled', '0' 'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=d64cd6750a3af8685defbbe4dd8c467ebe80f6be4bfe9ca718e81cd94129fc1d;Subject="";URI=spiffe://cluster.local/ns/foo/sa/curl' , dynamicMetadata: filter_metadata { key: "istio_authn" value { fields { key: "request.auth.principal" value { string_value: "cluster.local/ns/foo/sa/curl" } } fields { key: "source.namespace" value { string_value: "foo" } } fields { key: "source.principal" value { string_value: "cluster.local/ns/foo/sa/curl" } } fields { key: "source.user" value { string_value: "cluster.local/ns/foo/sa/curl" } } } } 2021-04-23T20:59:11.838529Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0] 2021-04-23T20:59:11.838538Z debug envoy rbac no engine, allowed by default ...
Запис
shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
означає, що запит буде відхилений політикою dry-runns[foo]-policy[deny-path-headers]-rule[0]
.Запис
no engine, allowed by default
означає, що запит фактично дозволений, оскільки політика dry-run є єдиною політикою на навантаженні.
Помилки з ключами та сертифікатами
Якщо ви підозрюєте, що деякі з ключів і/або сертифікатів, що використовуються Istio, є некоректними, ви можете перевірити вміст з будь-якого podʼа:
$ istioctl proxy-config secret curl-8f795f47d-4s4t7
RESOURCE NAME TYPE STATUS VALID CERT SERIAL NUMBER NOT AFTER NOT BEFORE
default Cert Chain ACTIVE true 138092480869518152837211547060273851586 2020-11-11T16:39:48Z 2020-11-10T16:39:48Z
ROOTCA CA ACTIVE true 288553090258624301170355571152070165215 2030-11-08T16:34:52Z 2020-11-10T16:34:52Z
Передавши прапорець -o json
, ви можете передати повний вміст сертифіката до openssl
для аналізу його вмісту:
$ istioctl proxy-config secret curl-8f795f47d-4s4t7 -o json | jq '[.dynamicActiveSecrets[] | select(.name == "default")][0].secret.tlsCertificate.certificateChain.inlineBytes' -r | base64 -d | openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
99:59:6b:a2:5a:f4:20:f4:03:d7:f0:bc:59:f5:d8:40
Signature Algorithm: sha256WithRSAEncryption
Issuer: O = k8s.cluster.local
Validity
Not Before: Jun 4 20:38:20 2018 GMT
Not After : Sep 2 20:38:20 2018 GMT
...
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
URI:spiffe://cluster.local/ns/my-ns/sa/my-sa
...
Переконайтесь, що показаний сертифікат містить дійсну інформацію. Зокрема, поле Subject Alternative Name
повинно бути URI:spiffe://cluster.local/ns/my-ns/sa/my-sa
.
Помилки Mutual TLS
Якщо ви підозрюєте проблеми з mutual TLS, спочатку переконайтесь, що istiod працює коректно, а по-друге, що ключі та сертифікати доставляються до sidecarʼів правильно.
Якщо все здається в порядку, наступний крок — перевірити, чи застосована правильна політика автентифікації і чи є правильні правила призначення.
Якщо ви підозрюєте, що sidecar з боку клієнта може неправильно надсилати трафік mutual TLS або plaintext, перевірте панель Grafana Workload. Чи вихідні запити анотовані, чи використовується mTLS. Після перевірки, якщо ви вважаєте, що sidecar з боку клієнта поводиться неналежно, повідомте про проблему на GitHub.