{"id":472173,"date":"2025-08-26T09:04:01","date_gmt":"2025-08-26T09:04:01","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=472173"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=472173","title":{"rendered":"<span>Single Sign\u2011On \u0434\u043b\u044f MLflow, Jupyterhub \u0438 Airflow: OIDC \u0431\u0435\u0437 \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f (ML)\u00a0 \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0412 \u0438\u0445 \u0441\u043e\u0441\u0442\u0430\u0432 \u0432\u0445\u043e\u0434\u0438\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u2014 \u043e\u0442 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e \u0441\u0438\u0441\u0442\u0435\u043c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u0410 \u043f\u043e \u043c\u0435\u0440\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430 \u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u043b\u0430\u043d \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u044e. \u0420\u0435\u0448\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e, \u0432\u043d\u0435\u0434\u0440\u0438\u0432 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e Single Sign-On (SSO), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0441\u0440\u0430\u0437\u0443 \u043a\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.\u00a0<\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041c\u0430\u0442\u0443\u0448\u043a\u0438\u043d, \u044f \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b <a href=\"https:\/\/www.orionsoft.ru\/nova\" rel=\"noopener noreferrer nofollow\">Nova Container Platfrom<\/a> \u0432 Orion soft. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <a href=\"https:\/\/www.orionsoft.ru\/starvault\" rel=\"noopener noreferrer nofollow\">StarVault <\/a>(\u0430\u043d\u0430\u043b\u043e\u0433 HashiCorp Vault, \u043d\u043e \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0442\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432 Vault) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 OpenID Connect (OIDC) \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0435\u0434\u0438\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 ML-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: MLflow, Airflow \u0438 JupyterHub.\u00a0\u00a0\u00a0<\/p>\n<p>\u0412\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 Nova Container Platform, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0437\u0430 10 \u043c\u0438\u043d\u0443\u0442. \u0422\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0432 StarVault \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d OIDC provider, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;some_provider&#187;.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3ef\/79c\/733\/3ef79c733fe93807371d54ce7a62920c.jpg\" width=\"1536\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3ef\/79c\/733\/3ef79c733fe93807371d54ce7a62920c.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3ef\/79c\/733\/3ef79c733fe93807371d54ce7a62920c.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e SSO?<\/h3>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c c \u0418\u0418-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438 \u0431\u0435\u0437 SSO \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e? \u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u041f\u0443\u0442\u0430\u043d\u0438\u0446\u0430 \u0438 \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438. <\/strong>SSO \u0434\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0421\u0440\u0435\u0434\u044b \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434 \u2013 \u0431\u0435\u0437 SSO \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0445 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0443\u0442\u0430\u043d\u0438\u0446\u0435 \u0438\u0437-\u0437\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430. \u0418, \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435, \u043a \u0432\u044b\u0442\u0435\u043a\u0430\u044e\u0449\u0438\u043c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0440\u0438\u0441\u043a\u0430\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430. <\/strong>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u043b\u043e\u0441\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0443\u0447\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 SSO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0445 \u0438\u0437 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430\u043c \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b Data Scientist \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b, \u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442 \u043d\u0438\u0445 production-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. MlOps \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430\u043c \u0432\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0438\u0445 \u043a \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e raw-\u0434\u0430\u043d\u043d\u044b\u0445.\u00a0<\/p>\n<p>\u0420\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0447\u043b\u0435\u043d\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. <\/strong>\u041e\u0431\u0438\u043b\u0438\u0435 \u043b\u043e\u0433\u0438\u043d\u043e\u0432 \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0440\u0438\u0441\u043a\u0438 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0435\u0442\u0430\u0446\u0438\u0438 \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 SSO, \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u0441\u0447\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0437\u0430 \u0441\u0447\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043c\u043d\u043e\u0433\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u043e\u0439 \u0434\u043b\u044f SSO-\u0441\u0438\u0441\u0442\u0435\u043c, \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0449\u0438\u0442\u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 ML-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0412\u043d\u0435\u0434\u0440\u044f\u0435\u043c SSO<\/h3>\n<p>\u041d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c SSO \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u0427\u0442\u043e\u0431\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes \u043d\u0430 \u0431\u0430\u0437\u0435 Nova Container Platform. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 StarVault OIDC-provider \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;some_provider&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443.<\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0434\u043b\u044f MLflow<\/strong><\/p>\n<p>MLflow \u2014 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f. \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u0438 \u0438\u0445 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435. \u041d\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e.<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0432 MLFlow \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/mlflow-oidc\/mlflow-oidc-auth\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u0430 mlflow-oidc-auth<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e basic-auth. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b mlflow-oidc-auth \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f 2 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 PostgreSQL (\u0432 \u043d\u0438\u0445 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439). \u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 OpenID Connect (OIDC).<\/p>\n<p>\u041d\u0430\u0434\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0437\u0435 MLflow. \u0418 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f SSO-\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 Dockerfile:<\/p>\n<pre><code>```Dockerfile FROM python:3.13.4 AS foundation LABEL maintainer=\"OrionSoft\" WORKDIR \/mlflow-build\/ COPY pyproject.toml poetry.toml poetry.lock LICENSE README.md .\/ COPY mlflowstack .\/mlflowstack  RUN ln -s \/usr\/bin\/dpkg-split \/usr\/sbin\/dpkg-split \\ &amp;&amp; ln -s \/usr\/bin\/dpkg-deb \/usr\/sbin\/dpkg-deb \\ &amp;&amp; ln -s \/bin\/rm \/usr\/sbin\/rm \\ &amp;&amp; ln -s \/bin\/tar \/usr\/sbin\/tar  RUN apt-get update &amp;&amp; \\ apt-get install -y --no-install-recommends \\ make \\ build-essential \\ libssl-dev \\ zlib1g-dev \\ libbz2-dev \\ libreadline-dev \\ libsqlite3-dev \\ wget \\ curl \\ libncursesw5-dev \\ xz-utils \\ tk-dev \\ libxml2-dev \\ libxmlsec1-dev \\ libffi-dev \\ liblzma-dev &amp;&amp; \\ apt-get clean &amp;&amp; \\ rm -rf \/var\/lib\/apt\/lists\/* \/var\/cache\/* \/var\/log\/* \/tmp\/* \/var\/tmp\/*   RUN python -m pip install --upgrade pip --no-cache-dir &amp;&amp; \\ pip install poetry wheel --no-cache-dir RUN poetry build WORKDIR \/mlflow\/ RUN python -m venv .venv &amp;&amp; \\ . .venv\/bin\/activate &amp;&amp; \\ pip install \/mlflow-build\/dist\/mlflowstack-1.0-py3-none-any.whl FROM python:3.13.4-slim LABEL maintainer=\"OrionSoft\"  RUN groupadd -r -g 1001 mlflow &amp;&amp; useradd -r -u 1001 -g mlflow -m -d \/home\/mlflow mlflow WORKDIR \/mlflow\/ RUN chown -R mlflow:mlflow \/mlflow  COPY --from=foundation --chown=mlflow:mlflow \/mlflow\/.venv \/mlflow\/.venv ENV PATH=\/mlflow\/.venv\/bin:$PATH ENV PYTHONUNBUFFERED=1  USER mlflow  CMD [\"mlflow\", \"server\", \"--backend-store-uri\", \"sqlite:\/\/\/mlflow.sqlite\", \"--default- artifact-root\", \".\/mlruns\", \"--host=0.0.0.0\", \"--port=5000\"] ```<\/code><\/pre>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 pyproject.toml \u0431\u044b\u043b\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 &#171;mlflow- oidc-auth (==5.0.1)&#187; \u0438 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u043e\u0431\u0440\u0430\u0437 MLflow \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 OIDC.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 MLflow \u0438 StarVault. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 StarVault \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c client application \u0434\u043b\u044f MLflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0438\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c OIDC, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u043d\u0435\u043c \u043f\u043e\u043b\u044f Redirect URI \u0438 Assigments.<\/p>\n<pre><code>```bash   $ starvault write identity\/oidc\/client\/mlflow \\ redirect_uris=\"https:\/\/mlflow.example.com\" \\ assignments=\"allow_all\" Success! Data written to: identity\/oidc\/client\/mlflow $ starvault read identity\/oidc\/client\/mlflow KeyValue  access_token_ttl24h assignments[allow_all] client_idhmXyMbH4tIResWptajk2QwgX5Fd6R7dk client_secret hvo_secret_mWDcX0C91i2H8wGGMnq7n8t4s5NXpILDu1t8irSTE5EGauiwhkCaP 8Ics38CNMvM client_typeconfidential id_token_ttl24h keydefault redirect_uris[https:\/\/mlflow.example.com]  ```<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 OIDC-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 scope: groups, email \u0438 name. \u0418 \u0435\u0441\u043b\u0438 scope groups \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0430\u0448\u0435 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0432\u0430 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 OIDC-\u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f MLflow \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0438\u0445 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0447\u0442\u044b \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u0432 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.<\/p>\n<pre><code>```\u0427\u0430\u0441\u0442\u044c Python \u043a\u043e\u0434\u0430 oidc \u043f\u043b\u0430\u0433\u0438\u043d\u0430 def handle_user_and_group_management(token) -&gt; list[str]: \"\"\"Handle user and group management based on the token. Returns list of error messages or empty list.\"\"\" errors = [] email = token[\"userinfo\"].get(\"email\") or token[\"userinfo\"].get(\"preferred_username\") display_name = token[\"userinfo\"].get(\"name\") if not email: errors.append(\"User profile error: No email provided in OIDC userinfo.\") if not display_name: errors.append(\"User profile error: No display name provided in OIDC userinfo.\") if errors: return errors ... ```<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 MLflow. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c ConfigMap \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a StarVault.\u00a0 \u042d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0430 \u0441 MLflow.<\/p>\n<pre><code>```yaml apiVersion: v1 kind: ConfigMap metadata: name: mlflow-env-configmap namespace: mlflow labels: app: mlflow data: OIDC_REDIRECT_URI: \"https:\/\/mlflow.example.com\/callback\" OIDC_PROVIDER_TYPE: \"oidc\" OIDC_PROVIDER_DISPLAY_NAME: \"sso\" # \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0432 \u0432\u0435\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 OIDC_SCOPE: \"openid email name groups\" OIDC_GROUP_NAME: \"mlflow-access\" OIDC_ADMIN_GROUP_NAME: \"mlflow-admins\" DEFAULT_MLFLOW_PERMISSION: \"MANAGE\" LOG_LEVEL: \"INFO\" OIDC_USERS_DB_URI: \"postgresql:\/\/admin:admin@psql- cls.postgresql.svc:5432\/mlflow_users\" # \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 SECRET_KEY: \"dbAtlCg3GNY3lIjebcYM7QpsNJMEIJrH\" OIDC_DISCOVERY_URL: \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/.well-known\/ openid-configuration\" OIDC_CLIENT_SECRET: \"hvo_secret_mWDcX0C91i2H8wGGMnq7n8t4s5NXpILDu1t8irSTE5EGauiwhkCa P8Ics38CNMvM\" OIDC_CLIENT_ID: \"hmXyMbH4tIResWptajk2QwgX5Fd6R7dk\" ```<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0445\u043e\u0434\u0430 \u0432 \u0432\u0435\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 MLflow \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ea4\/654\/2f5\/ea46542f53ebf2a674e5a026d680c825.png\" width=\"1063\" height=\"619\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ea4\/654\/2f5\/ea46542f53ebf2a674e5a026d680c825.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ea4\/654\/2f5\/ea46542f53ebf2a674e5a026d680c825.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u0442\u0435 \u043d\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 MLflow.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/775\/ff8\/95b\/775ff895be5b99be30dbb5756b63e8a2.png\" width=\"1061\" height=\"636\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/775\/ff8\/95b\/775ff895be5b99be30dbb5756b63e8a2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/775\/ff8\/95b\/775ff895be5b99be30dbb5756b63e8a2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Mlflow \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0441\u0442\u0438 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u00abCreate\u00a0<\/p>\n<p>\u0414\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Mlflow \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0438\u043d\u0433\u0430 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u00abCreate access key\u00bb, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u043e\u0440\u043c\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/20c\/769\/80f\/20c76980fe09ecb496eefd0e444bb1b3.png\" width=\"1051\" height=\"401\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/20c\/769\/80f\/20c76980fe09ecb496eefd0e444bb1b3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/20c\/769\/80f\/20c76980fe09ecb496eefd0e444bb1b3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0441\u0435! \u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Mlflow \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e!<\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0434\u043b\u044f Airflow<\/strong><\/p>\n<p>Airflow \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Flask AppBuilder (FAB) auth manager, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 OAuth, \u043d\u043e StarVault \u0438 OIDC \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u043d\u0435\u043c \u043d\u0435\u0442. \u041d\u043e \u0437\u0430\u0442\u043e Airflow \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 FabAirflowSecurityManagerOverride.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Airflow \u043b\u0435\u0433\u0447\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 StarVault \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f client application \u0434\u043b\u044f Airflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 OIDC \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c. \u0412 \u043d\u0435\u043c \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f, \u043a\u0430\u043a Redirect URI \u0438 Assigments.<\/p>\n<pre><code>$ starvault write identity\/oidc\/client\/airflow redirect_uris=\"https:\/\/airflow.example.com\/oauth-authorized\/sso\" assignments=\"allow_all\" Success! Data written to: identity\/oidc\/client\/airflow  $ starvault read identity\/oidc\/client\/airflow KeyValue  access_token_ttl24h assignments[allow_all] client_idHC53gCO2rob89DrpvrJi32mPJlefkNza client_secret hvo_secret_7J8DMIxBijR0E1WVJYwl1y9UcnnxJVrohRPvJh4Lg1JqeBYcrS7XAm vP456ya84p client_typeconfidential id_token_ttl24h   keydefault redirect_uris[https:\/\/airflow.example.com\/oauth-authorized\/sso]<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Airflow \u0432 \u043d\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c ConfigMap \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043d\u0435\u043c \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043d\u0443\u0436\u043d\u0443\u044e \u043d\u0430\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>\u0412\u0430\u0436\u043d\u043e! \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043c\u0435\u043d\u0438 \u0432 \u043f\u043e\u043b\u0435 &#171;name&#187; \u0443 OAuth \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0435\u0433\u043c\u0435\u043d\u0442 \u043f\u0443\u0442\u0438 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#171;sso&#187;) \u043f\u043e\u0441\u043b\u0435 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430 &#171;oauth-authorized&#187;, \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u043f\u043e\u043b\u0435 Redirect URI.<\/p>\n<pre><code>```yaml apiVersion: v1 kind: ConfigMap metadata:  name: airflow-webserver-config  namespace: airflow  labels:  app: airflow  instance: webserver data:  webserver_config.ctmpl: |- from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride from flask_appbuilder.security.manager import AUTH_OAUTH from typing import Any, List, Union import requests AUTH_TYPE = AUTH_OAUTH # \u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e AUTH_ROLES_SYNC_AT_LOGIN = True AUTH_USER_REGISTRATION = True # \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u0432 \u0411\u0414 FAB, \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f # \u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0440\u043e\u043b\u044f\u043c\u0438, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 FAB AUTH_ROLES_MAPPING = { \"Viewer\": [\"Viewer\"], \"Admin\": [\"Admin\"], } # \u0417\u0430\u0434\u0430\u043d\u0438\u0435 StarVault \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 OAuth \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u043f\u043e\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/.well-known\/ openid-configuration\". OAUTH_PROVIDERS = [ {  \"name\": \"sso\",  \"icon\": \"fa-sign-in\",  \"token_key\": \"access_token\",  \"remote_app\": {  \"client_id\": \"HC53gCO2rob89DrpvrJi32mPJlefkNza\",  \"client_secret\": \"hvo_secret_7J8DMIxBijR0E1WVJYwl1y9UcnnxJVrohRPvJh4Lg1JqeBYcrS7XAm vP456ya84p\",  \"client_kwargs\": {  \"scope\": \"openid email groups\",  \"token_endpoint_auth_method\": \"client_secret_post\",  },  \"server_metadata_url\": \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/.well-known\/ openid-configuration\",  \"api_base_url\": \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\",  \"access_token_url\": \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/token\",  \"authorize_url\": \"https:\/\/starvault.example.com\/ui\/vault\/identity\/oidc\/provider\/some_provider\/authorize\",  \"jwks_uri\": None,  }, }, ] # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 class StarVaultSecurityManager(FabAirflowSecurityManagerOverride): def get_oauth_user_info(self, provider: str, resp: Any) -&gt; dict[str, Union[str, list[str]]]:  if provider == \"sso\":  remote = self.appbuilder.sm.oauth_remotes[provider]  # \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 StarVault  access_token = resp.get('access_token')  # \u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 URL \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435  userinfo_url = f\"{remote.api_base_url}\/userinfo\"  headers = {  \"Authorization\": f\"Bearer {access_token}\",  \"Accept\": \"application\/json\"  }  # \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435  response = requests.get(userinfo_url, headers=headers)  data = response.json()  # \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u043e\u0447\u0442\u0443 \u0438 \u0440\u043e\u043b\u044c (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u043e\u043b\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u044b)  return {  \"email\": data.get(\"email\", \"\"),  \"role_keys\": data.get(\"groups\", []),  }   # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 SECURITY_MANAGER_CLASS = VaultSecurityManager ```<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 pod \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0443\u0442\u044c &#171;\/opt\/airflow\/webserver_<a href=\"http:\/\/config.py\" rel=\"noopener noreferrer nofollow\">config.py<\/a>&#171;.\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b \u043f\u0440\u0438 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u043e\u043c\u043e\u0432), \u0442\u043e \u0432 \u0444\u0430\u0439\u043b\u0435 &#171;airflow.cfg&#187; \u0432 \u043f\u043e\u043b\u0435 &#171;[webserver]&#187; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u043c \u043f\u0443\u0442\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 &#171;config_file =\/opt\/airflow\/webserver\/webserver_<a href=\"http:\/\/config.py\" rel=\"noopener noreferrer nofollow\">config.py<\/a>&#171;.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0442\u043e \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u043d\u0430 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Airflow \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/45c\/a83\/ae7\/45ca83ae7e58902886fd3ab08e71c0f7.png\" width=\"1056\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/45c\/a83\/ae7\/45ca83ae7e58902886fd3ab08e71c0f7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/45c\/a83\/ae7\/45ca83ae7e58902886fd3ab08e71c0f7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ab0\/842\/bb9\/ab0842bb9e0394c516a80fead2cab558.png\" width=\"1061\" height=\"618\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ab0\/842\/bb9\/ab0842bb9e0394c516a80fead2cab558.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ab0\/842\/bb9\/ab0842bb9e0394c516a80fead2cab558.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Airflow \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430!<\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0434\u043b\u044f Jupyterhub<\/strong><\/p>\n<p>Jupyterhub \u2013 \u044d\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Jupyter Notebooks \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u0414\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Jupyterhub \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c oauthenticator, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043a\u0430\u043a \u0434\u043b\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, GitLab \u0438\u043b\u0438 Google), \u0442\u0430\u043a \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GenericAuthenticator, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043b\u044e\u0431\u043e\u043c\u0443 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0443.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Jupyterhub \u0432 StarVault \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c client application \u0434\u043b\u044f Jupyterhub, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c OIDC, \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u043d\u0435\u043c \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043a\u0430\u043a Redirect URI \u0438 Assigments.<\/p>\n<pre><code>```bash $ starvault write identity\/oidc\/client\/jupyterhub redirect_uris=\"https:\/\/jupyterhub.example.com\/hub\/oauth_callback\" assignments=\"allow_all\" Success! Data written to: identity\/oidc\/client\/jupyterhub $ starvault read identity\/oidc\/client\/jupyterhub Key Value --- ----- access_token_ttl 24h assignments [allow_all] client_id vuuYyveqysCc5BqmbfFiUJ9naGs2M4kc client_secret hvo_secret_qod6qYjwy16oeYZcvz0fbU1B2pTJ0skPR9dCWZ45ZNG1ib1BeGUNK AmCQeTFfQR1 client_type confidential id_token_ttl 24h key default redirect_uris [https:\/\/jupyterhub.example.com\/hub\/oauth_callback] ```<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Jupyterhub \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0444\u0430\u0439\u043b jupyterhub_config.py \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:  <\/p>\n<pre><code>```yaml # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 c.JupyterHub.authenticator_class = \"generic-oauth\" # \u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 \u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0435 OIDC c.GenericOAuthenticator.client_id = \"vuuYyveqysCc5BqmbfFiUJ9naGs2M4kc\" c.GenericOAuthenticator.client_secret = \"hvo_secret_qod6qYjwy16oeYZcvz0fbU1B2pTJ0skPR9dCWZ45ZNG1ib1BeGUN KAmCQeTFfQR1\" # \u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0435. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/.well-known\/ openid-configuration\". c.GenericOAuthenticator.authorize_url = \"https:\/\/starvault.example.com\/ui\/vault\/identity\/oidc\/provider\/some_provider\/authorize\" c.GenericOAuthenticator.token_url = \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/token\" c.GenericOAuthenticator.userdata_url = \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/userinfo\" # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 c.GenericOAuthenticator.scope = [\"openid\", \"email\", \"groups\"] # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 username \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c email c.GenericOAuthenticator.username_claim = \"email\" # \u0417\u0430\u0434\u0430\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044f\u043c\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f c.GenericOAuthenticator.auth_state_groups_key = \"oauth_user.groups\" # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 c.GenericOAuthenticator.allowed_groups = {\"jupyterhub_users\"} c.GenericOAuthenticator.admin_groups = {\"jupyterhub_admins\"} ```<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0445\u043e\u0434\u0430 \u0432 \u0432\u0435\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Jupyterhub \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/27e\/165\/873\/27e16587368a90ecaf6588a983df34fd.png\" width=\"1057\" height=\"641\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/27e\/165\/873\/27e16587368a90ecaf6588a983df34fd.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/27e\/165\/873\/27e16587368a90ecaf6588a983df34fd.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/634\/9c2\/2a4\/6349c22a4e96c2657c873a24a640225a.png\" width=\"1057\" height=\"627\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/634\/9c2\/2a4\/6349c22a4e96c2657c873a24a640225a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/634\/9c2\/2a4\/6349c22a4e96c2657c873a24a640225a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0440\u0435\u043c\u044f \u043f\u043e\u0434\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0442\u043e\u0433\u0438. \u0427\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438:\u00a0<\/p>\n<p>1. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 ML \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u0438 \u0436\u0438\u0437\u043d\u044c ML-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430\u043c.<\/p>\n<p>2. \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Vault.\u00a0<\/p>\n<p>3. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043d\u0430 \u0431\u0430\u0437\u0435 StarVault \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0438\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043e\u043f\u044b\u0442 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f SSO \u0432 ML, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u2013 \u043e\u0431\u0441\u0443\u0434\u0438\u043c \u044d\u0442\u043e \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. \u0422\u0430\u043a\u0436\u0435 \u043f\u0438\u0448\u0438\u0442\u0435, \u043d\u0430 \u043a\u0430\u043a\u0443\u044e \u0442\u0435\u043c\u0443 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 ML\/AI \ud83d\ude42<\/p>\n<p>\u0411\u043e\u0434\u0440\u043e\u0439 \u0432\u0441\u0435\u043c \u043d\u0430\u043c SSO-\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/940592\/\"> https:\/\/habr.com\/ru\/articles\/940592\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f (ML)\u00a0 \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0412 \u0438\u0445 \u0441\u043e\u0441\u0442\u0430\u0432 \u0432\u0445\u043e\u0434\u0438\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u2014 \u043e\u0442 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e \u0441\u0438\u0441\u0442\u0435\u043c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u0410 \u043f\u043e \u043c\u0435\u0440\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430 \u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u043b\u0430\u043d \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u044e. \u0420\u0435\u0448\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e, \u0432\u043d\u0435\u0434\u0440\u0438\u0432 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e Single Sign-On (SSO), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0441\u0440\u0430\u0437\u0443 \u043a\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.\u00a0<\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041c\u0430\u0442\u0443\u0448\u043a\u0438\u043d, \u044f \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b <a href=\"https:\/\/www.orionsoft.ru\/nova\" rel=\"noopener noreferrer nofollow\">Nova Container Platfrom<\/a> \u0432 Orion soft. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <a href=\"https:\/\/www.orionsoft.ru\/starvault\" rel=\"noopener noreferrer nofollow\">StarVault <\/a>(\u0430\u043d\u0430\u043b\u043e\u0433 HashiCorp Vault, \u043d\u043e \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0442\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432 Vault) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 OpenID Connect (OIDC) \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0435\u0434\u0438\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 ML-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: MLflow, Airflow \u0438 JupyterHub.\u00a0\u00a0\u00a0<\/p>\n<p>\u0412\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 Nova Container Platform, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0437\u0430 10 \u043c\u0438\u043d\u0443\u0442. \u0422\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0432 StarVault \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d OIDC provider, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;some_provider&#187;.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e SSO?<\/h3>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c c \u0418\u0418-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438 \u0431\u0435\u0437 SSO \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e? \u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u041f\u0443\u0442\u0430\u043d\u0438\u0446\u0430 \u0438 \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438. <\/strong>SSO \u0434\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0421\u0440\u0435\u0434\u044b \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434 \u2013 \u0431\u0435\u0437 SSO \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0445 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0443\u0442\u0430\u043d\u0438\u0446\u0435 \u0438\u0437-\u0437\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430. \u0418, \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435, \u043a \u0432\u044b\u0442\u0435\u043a\u0430\u044e\u0449\u0438\u043c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0440\u0438\u0441\u043a\u0430\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430. <\/strong>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u043b\u043e\u0441\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0443\u0447\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 SSO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0445 \u0438\u0437 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430\u043c \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b Data Scientist \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b, \u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442 \u043d\u0438\u0445 production-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. MlOps \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430\u043c \u0432\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0438\u0445 \u043a \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e raw-\u0434\u0430\u043d\u043d\u044b\u0445.\u00a0<\/p>\n<p>\u0420\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0447\u043b\u0435\u043d\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. <\/strong>\u041e\u0431\u0438\u043b\u0438\u0435 \u043b\u043e\u0433\u0438\u043d\u043e\u0432 \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0440\u0438\u0441\u043a\u0438 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0435\u0442\u0430\u0446\u0438\u0438 \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 SSO, \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u0441\u0447\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0437\u0430 \u0441\u0447\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043c\u043d\u043e\u0433\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u043e\u0439 \u0434\u043b\u044f SSO-\u0441\u0438\u0441\u0442\u0435\u043c, \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0449\u0438\u0442\u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 ML-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0412\u043d\u0435\u0434\u0440\u044f\u0435\u043c SSO<\/h3>\n<p>\u041d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c SSO \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u0427\u0442\u043e\u0431\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes \u043d\u0430 \u0431\u0430\u0437\u0435 Nova Container Platform. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 StarVault OIDC-provider \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;some_provider&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443.<\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0434\u043b\u044f MLflow<\/strong><\/p>\n<p>MLflow \u2014 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f. \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u0438 \u0438\u0445 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435. \u041d\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e.<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0432 MLFlow \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/mlflow-oidc\/mlflow-oidc-auth\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u0430 mlflow-oidc-auth<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e \u043b\u043e\u0433\u0438\u043d\u0443 \u0438 \u043f\u0430\u0440\u043e\u043b\u044e basic-auth. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b mlflow-oidc-auth \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f 2 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 PostgreSQL (\u0432 \u043d\u0438\u0445 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439). \u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 OpenID Connect (OIDC).<\/p>\n<p>\u041d\u0430\u0434\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0437\u0435 MLflow. \u0418 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f SSO-\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 Dockerfile:<\/p>\n<pre><code>```Dockerfile FROM python:3.13.4 AS foundation LABEL maintainer=\"OrionSoft\" WORKDIR \/mlflow-build\/ COPY pyproject.toml poetry.toml poetry.lock LICENSE README.md .\/ COPY mlflowstack .\/mlflowstack  RUN ln -s \/usr\/bin\/dpkg-split \/usr\/sbin\/dpkg-split \\ &amp;&amp; ln -s \/usr\/bin\/dpkg-deb \/usr\/sbin\/dpkg-deb \\ &amp;&amp; ln -s \/bin\/rm \/usr\/sbin\/rm \\ &amp;&amp; ln -s \/bin\/tar \/usr\/sbin\/tar  RUN apt-get update &amp;&amp; \\ apt-get install -y --no-install-recommends \\ make \\ build-essential \\ libssl-dev \\ zlib1g-dev \\ libbz2-dev \\ libreadline-dev \\ libsqlite3-dev \\ wget \\ curl \\ libncursesw5-dev \\ xz-utils \\ tk-dev \\ libxml2-dev \\ libxmlsec1-dev \\ libffi-dev \\ liblzma-dev &amp;&amp; \\ apt-get clean &amp;&amp; \\ rm -rf \/var\/lib\/apt\/lists\/* \/var\/cache\/* \/var\/log\/* \/tmp\/* \/var\/tmp\/*   RUN python -m pip install --upgrade pip --no-cache-dir &amp;&amp; \\ pip install poetry wheel --no-cache-dir RUN poetry build WORKDIR \/mlflow\/ RUN python -m venv .venv &amp;&amp; \\ . .venv\/bin\/activate &amp;&amp; \\ pip install \/mlflow-build\/dist\/mlflowstack-1.0-py3-none-any.whl FROM python:3.13.4-slim LABEL maintainer=\"OrionSoft\"  RUN groupadd -r -g 1001 mlflow &amp;&amp; useradd -r -u 1001 -g mlflow -m -d \/home\/mlflow mlflow WORKDIR \/mlflow\/ RUN chown -R mlflow:mlflow \/mlflow  COPY --from=foundation --chown=mlflow:mlflow \/mlflow\/.venv \/mlflow\/.venv ENV PATH=\/mlflow\/.venv\/bin:$PATH ENV PYTHONUNBUFFERED=1  USER mlflow  CMD [\"mlflow\", \"server\", \"--backend-store-uri\", \"sqlite:\/\/\/mlflow.sqlite\", \"--default- artifact-root\", \".\/mlruns\", \"--host=0.0.0.0\", \"--port=5000\"] ```<\/code><\/pre>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 pyproject.toml \u0431\u044b\u043b\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 &#171;mlflow- oidc-auth (==5.0.1)&#187; \u0438 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u043e\u0431\u0440\u0430\u0437 MLflow \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 OIDC.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 MLflow \u0438 StarVault. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 StarVault \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c client application \u0434\u043b\u044f MLflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0438\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c OIDC, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u043d\u0435\u043c \u043f\u043e\u043b\u044f Redirect URI \u0438 Assigments.<\/p>\n<pre><code>```bash   $ starvault write identity\/oidc\/client\/mlflow \\ redirect_uris=\"https:\/\/mlflow.example.com\" \\ assignments=\"allow_all\" Success! Data written to: identity\/oidc\/client\/mlflow $ starvault read identity\/oidc\/client\/mlflow KeyValue  access_token_ttl24h assignments[allow_all] client_idhmXyMbH4tIResWptajk2QwgX5Fd6R7dk client_secret hvo_secret_mWDcX0C91i2H8wGGMnq7n8t4s5NXpILDu1t8irSTE5EGauiwhkCaP 8Ics38CNMvM client_typeconfidential id_token_ttl24h keydefault redirect_uris[https:\/\/mlflow.example.com]  ```<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 OIDC-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 scope: groups, email \u0438 name. \u0418 \u0435\u0441\u043b\u0438 scope groups \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0430\u0448\u0435 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0432\u0430 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 OIDC-\u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f MLflow \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0438\u0445 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0447\u0442\u044b \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u0432 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.<\/p>\n<pre><code>```\u0427\u0430\u0441\u0442\u044c Python \u043a\u043e\u0434\u0430 oidc \u043f\u043b\u0430\u0433\u0438\u043d\u0430 def handle_user_and_group_management(token) -&gt; list[str]: \"\"\"Handle user and group management based on the token. Returns list of error messages or empty list.\"\"\" errors = [] email = token[\"userinfo\"].get(\"email\") or token[\"userinfo\"].get(\"preferred_username\") display_name = token[\"userinfo\"].get(\"name\") if not email: errors.append(\"User profile error: No email provided in OIDC userinfo.\") if not display_name: errors.append(\"User profile error: No display name provided in OIDC userinfo.\") if errors: return errors ... ```<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 MLflow. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c ConfigMap \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a StarVault.\u00a0 \u042d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0430 \u0441 MLflow.<\/p>\n<pre><code>```yaml apiVersion: v1 kind: ConfigMap metadata: name: mlflow-env-configmap namespace: mlflow labels: app: mlflow data: OIDC_REDIRECT_URI: \"https:\/\/mlflow.example.com\/callback\" OIDC_PROVIDER_TYPE: \"oidc\" OIDC_PROVIDER_DISPLAY_NAME: \"sso\" # \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0432 \u0432\u0435\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 OIDC_SCOPE: \"openid email name groups\" OIDC_GROUP_NAME: \"mlflow-access\" OIDC_ADMIN_GROUP_NAME: \"mlflow-admins\" DEFAULT_MLFLOW_PERMISSION: \"MANAGE\" LOG_LEVEL: \"INFO\" OIDC_USERS_DB_URI: \"postgresql:\/\/admin:admin@psql- cls.postgresql.svc:5432\/mlflow_users\" # \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 SECRET_KEY: \"dbAtlCg3GNY3lIjebcYM7QpsNJMEIJrH\" OIDC_DISCOVERY_URL: \"https:\/\/starvault.example.com\/v1\/identity\/oidc\/provider\/some_provider\/.well-known\/ openid-configuration\" OIDC_CLIENT_SECRET: \"hvo_secret_mWDcX0C91i2H8wGGMnq7n8t4s5NXpILDu1t8irSTE5EGauiwhkCa P8Ics38CNMvM\" OIDC_CLIENT_ID: \"hmXyMbH4tIResWptajk2QwgX5Fd6R7dk\" ```<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0445\u043e\u0434\u0430 \u0432 \u0432\u0435\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 MLflow \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0410 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u0442\u0435 \u043d\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 MLflow.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Mlflow \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0441\u0442\u0438 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u00abCreate\u00a0<\/p>\n<p>\u0414\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Mlflow \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0438\u043d\u0433\u0430 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u00abCreate access key\u00bb, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u043e\u0440\u043c\u0430:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412\u0441\u0435! \u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Mlflow \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e!<\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SSO \u0434\u043b\u044f Airflow<\/strong><\/p>\n<p>Airflow \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Flask AppBuilder (FAB) auth manager, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 OAuth, \u043d\u043e StarVault \u0438 OIDC \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u043d\u0435\u043c \u043d\u0435\u0442. \u041d\u043e \u0437\u0430\u0442\u043e Airflow \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 FabAirflowSecurityManagerOverride.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 StarVault \u0438 Airflow \u043b\u0435\u0433\u0447\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 StarVault \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f client application \u0434\u043b\u044f Airflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 OIDC \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c. \u0412 \u043d\u0435\u043c \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f, \u043a\u0430\u043a Redirect URI \u0438 Assigments.<\/p>\n<pre><code>$ starvault write identity\/oidc\/client\/airflow redirect_uris=\"https:\/\/airflow.example.com\/oauth-authorized\/sso\" assignments=\"allow_all\" Success! Data written to: identity\/oidc\/client\/airflow  $ starvault read<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-472173","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=472173"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472173\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=472173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=472173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=472173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}