Настройка IAM#

Примечание

Может использоваться ПО с открытым исходным кодом Keycloak или аналогичная IAM-система.

В IAM для каждого тенанта создается отдельный клиент (OAuth client). Для клиента создается типовая ролевая модель и выполняется настройка маппинга привилегий на access-токен.

В рамках тенанта предоставляется возможность назначать роли для пользователей этого тенанта.

При обращении к DS Lab проверяется, была ли создана для пользователя сессия. Если нет, то он перенаправляется в Keycloak, где открывается форма аутентификации.

После прохождения аутентификации и авторизации Keycloak передает в DS Lab access-токен, содержащий список привилегий пользователя в разрезе доступных ему тенантов. Возможность работы пользователя в тенанте определяется наличием у него какой-либо привилегии в этом тенанте.

Пример содержимого jwt access token:

{
  "exp": 1702289908,
  "iat": 1702289608,
  "jti": "70c26f8a-7be1-4964-a06d-670f244f1b4d",
  "iss": "http://localhost:8080/realms/MyRealm",
  "aud": [
    "ds-lab",
    "dslb#tenant1",
    "account"
  ],
  "sub": "52279d99-d188-4133-8832-d79cc47b8a15",
  "typ": "Bearer",
  "azp": "ds-lab",
  "session_state": "df80cd2a-50de-447b-88e0-c845ff66fb0d",
  "acr": "1",
  "allowed-origins": [
    "http://ds-lab.apps.sbt.ru",
    "http://localhost:3000"
  ],
  "realm_access": {
    "roles": [
      "default-roles-ds-lab",
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "dslb#tenant1": {
      "roles": [
        "data-edit",
        "ModelDeveloper",
        "model-list",
        "data-query",
        "data-endpoints",
        "data-dictionary"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid dslab profile email",
  "sid": "df80cd2a-50de-447b-88e0-c845ff66fb0d",
  "email_verified": false,
  "preferred_username": "testuser",
  "given_name": "",
  "family_name": ""
}

В блоке кода выше:

  • iss — сконфигурированное имя issuer — URL сервера IAM;

  • aud — сконфигурированное имя приложения-клиента (например, ds-lab) должно быть в списке в claim aud;

  • scope — должен присутствовать, или проверять claim typ: Bearer (проверка для того, чтобы подтвердить, что это именно access token);

  • resource_access — перечислены тенанты каждый со своим набором привилегий (и/или ролей — для удобства пользователя).

Имя для клиента IAM, представляющего тенант, рекомендуется составлять из фиксированного префикса и названия тенанта. Выбранный способ именования клиента необходимо соблюдать для всех тенантов.

Примечание

В Keycloak присутствуют клиенты, не относящиеся к тенантам. DS Lab позволяет исключить из обработки таких клиентов либо по заданному списку имен, либо по отсутствию префикса.

Для указания префикса клиентов-тенантов используется настройка DS Lab check.jwt.tenant.prefixToChoose. Для указания списка имен клиентов, исключаемых из тенантов, используется настройка DS Lab check.jwt.tenant.excludeTenants.

Возможность выполнения тех или иных действий с проектами в DS Lab определяется наличием у пользователя соответствующих привилегий. Пользователь получает привилегии путем назначения ему ролей, агрегирующих привилегии.

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

Пример настройки интеграции c внешней IAM-системой (Keycloak)#

В данном разделе описывается настройка DS Lab в режиме интеграции с внешней IAM-системой на примере ПО с открытым исходным кодом Keycloak.

Инструкция описана для Keycloak версии 22.0.3. Для других версий интерфейс может отличаться, но принцип взаимодействия остается тем же.

Установка и конфигурирование Keycloak для DS Lab#

Необходимо выполнить следующие действия:

  1. Установить и настроить сервис Keycloak согласно эксплуатационной документации данного ПО.

  2. Создать Realm для инсталляции DS Lab. Для этого:

    1. Открыть UI установленного в п.1 сервиса Keycloak и войти с правами администратора.

    2. В левом верхнем углу раскрыть список доступных Realm (по умолчанию «из коробки» доступен только «realm master») и нажать на кнопку Create Realm.

    3. В открывшемся окне ввести наименование в поле Realm name (на рисунке это — «ds-lab») и нажать Create.

    Все последующие действия будут производиться в Realm «ds-lab».

  3. Создать Client (клиента) для приложения DS Lab.

    Для создания клиента, под которым DS Lab будет обращаться к Keycloak, необходимо:

    1. Перейти на вкладку Clients и нажать Create client.

    2. Ввести имя клиента (на рисунке это — «ds-lab») и нажать Next.

    3. На следующей странице нажать Next.

    4. На следующей странице в полях Valid Redirect URIs и Web Origins прописать адрес сервиса DS Lab. Проверить, что пункт Standard flow* выбран.

    5. Нажать Save. В списке клиентов должен появиться созданный клиент. Перейти на страницу клиента.

  4. Настроить формирование claim aud для access-токена.

    1. Создать дополнительный client scope. Перейти на страницу Client scopes и нажать кнопку Create client scope.

    2. В открывшемся окне ввести имя нового client scope, на рисунке это — «dslab». Нажать Save.

    3. В созданном client scope перейти во вкладку Mappers и выбрать Configure a new mapper.

    4. Во всплывающем окне выбрать Audience.

    5. В открывшемся окне задать имя mapper. Выбрать клиента DS Lab (на рисунке это — «ds-lab»). Выставить флаг Add to ID token. Нажать Save.

    Перейти на страницу Clients, выбрать клиента «ds-lab». Перейти на вкладку Client scopes. Нажать Add client scope.

    Во всплывающем окне выбрать созданный client scope ds-lab. Нажать Add -> Default.

Конфигурирование DS Lab для работы с Realm Keycloak#

Необходимо выполнить следующие действия:

  1. Выгрузить значения JWKS для соответствующего Realm, сделав HTTP-запрос по адресу вида {адрес keycloak}/auth/realms/MyRealm/protocol/openid-connect/certs.

  2. В DS Lab задать URL IAM, Realm и Client, указав в настройке check.iam.info соответствующую JSON-структуру (например, { "url": "", "realm": "{value}", "clientId": "{value}" }).

  3. Указать полученный в п.1 JWKS в настройке check.jwt.jwks.

После выполнения перечисленных действий пользователи UI DS Lab перед началом работы будут переадресовываться для аутентификации на страницу Keycloak IAM, создавая необходимую для работы с DS Lab JWT-сессию.

Создание нового тенанта#

В этом примере создание тенанта включает в себя:

  • создание клиента (client) в Keycloak;

  • создание предопределенного набора привилегий DS Lab (в виде набора ролей первого уровня);

  • создание списка ролей пользователей (в виде композитных ролей).

В примере тенант создается путем импорта из файла, созданного по шаблону client-roles-template.json. В шаблоне вместо имени фактического тенанта указана метка-заполнитель «${tenantName}».

Пример создания тенанта с именем «dslb#tenant1»:

  1. Подготовить файл импорта. Для этого:

    1. Открыть файл-шаблона client-roles-template.json.

    2. Заменить все вхождения строки «${tenantName}» на имя создаваемого тенанта «dslb#tenant1».

    3. Сохранить файл с новым именем. Должен получиться файл со следующим содержимым:

    {
      "roles": {
        "client": {
          "dslb#tenant1": [
            {"name": "model-config-view","composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-import",     "composite": false,"clientRole": true,"attributes": {}},
            {"name": "data-query",       "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-deploy",     "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-edit",       "composite": false,"clientRole": true,"attributes": {}},
            {"name": "data-endpoints",   "composite": false,"clientRole": true,"attributes": {}},
            {"name": "security-edit",    "composite": false,"clientRole": true,"attributes": {}},
            {"name": "data-dictionary",  "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-export",     "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-config-edit","composite": false,"clientRole": true,"attributes": {}},
            {"name": "data-edit",        "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-create",     "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-delete",     "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-list",       "composite": false,"clientRole": true,"attributes": {}},
            {"name": "model-view",       "composite": false,"clientRole": true,"attributes": {}},
            {"name": "security-view",    "composite": false,"clientRole": true,"attributes": {}},
            {
              "name": "ModelAdmin",
              "description": "model-create, model-deploy, model-delete, model-config-view, model-config-edit, model-list",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","model-create","model-config-view","model-config-edit","model-deploy","model-delete"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "ModelDeveloper",
              "description": "model-list, data-query, data-edit, data-endpoints, data-dictionary",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","data-endpoints", "data-edit","data-query","data-dictionary"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "ModelSecurityViewer",
              "description": "security-view, model-list",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","security-view"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "ModelSecurityEditor",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","security-view","security-edit"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "TenantOperator",
              "description": "model-import, model-export, model-view, model-deploy, model-config-view, data-endpoints, model-list, data-dictionary",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list", "model-view", "model-config-view","model-import","data-endpoints", "model-deploy", "data-dictionary", "model-export"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "ModelViewer",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","model-view"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "DataQuery",
              "description": "model-list, data-query",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","data-query"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "ModelEditor",
              "composite": true,"composites": {"client": {"dslb#tenant1": ["model-list","model-view","model-edit","model-create","model-import"]}},
              "clientRole": true,"attributes": {}
            },
            {
              "name": "Tenant Admin",
              "composite": true,"composites": {"client": {"dslb#tenant1": []}},
              "clientRole": true,"attributes": {}
            }
          ]
        }
      },
      "clients": [
        {
          "clientId": "dslb#tenant1",
          "enabled": true,
          "protocol": "openid-connect",
          "publicClient": true,
          "fullScopeAllowed": true,
          "standardFlowEnabled": true,
          "implicitFlowEnabled": false,
          "directAccessGrantsEnabled": false,
          "serviceAccountsEnabled": false
        }
      ]
    }
    
  2. Импортировать файл тенанта в realm. Для этого:

    1. Перейти на страницу Realm settings, раскрыть меню Action и выбрать Partial import.

    2. Во всплывающем окне выбрать подготовленный на шаге 1 файл импорта (на рисунке ниже — 1).

    3. В окне отображения содержимого файла убедиться, что используется нужное имя клиента-тенанта (на рисунке ниже — 2).

    4. Выбрать импорт клиента и ролей (на рисунке ниже — 3).

    5. Выбрать действие, применяемое при существовании импортируемого объекта (рекомендуемое значение — «skip») (на рисунке ниже — 4). Нажать Import (на рисунке ниже — 5).

      Должно появиться окно, аналогичное представленному ниже.

    6. Перейти на страницу соответствующего клиента-тенанта во вкладку Roles и убедиться, что привилегии и базовые роли успешно импортировались.

  3. При необходимости можно вручную добавить дополнительные роли, назначив им необходимые привилегии или скорректировать импортированные роли:

    1. Для создания роли нажать Create.

    2. В открывшемся окне указать наименование роли.

    3. Привязать нужные привилегии к созданной роли. Для этого:

    4. Нажать Action и выбрать Add associated roles.

    5. Во всплывающем окне необходимо переключить фильтр на фильтрацию по ролям клиентов, а не realm (на рисунке ниже — 1).

    6. Дополнительно можно задать фильтр по имени роли или тенанта (на рисунке ниже — 2).

    7. Выбрать необходимые привилегии (на рисунке ниже — 3) и нажать Assign (на рисунке ниже — 4).

    Примечание

    Создание клиента и ролей можно выполнить вручную, но привилегии рекомендуется всегда импортировать из файла.

Ручное создание тенанта#

Создание клиента-тенанта аналогично созданию клиента «ds-lab» с тем отличием, что не указываются URL (т.к. обращений к Keycloak под этими клиентами не предусматривается).

Для примера создадим клиент-тенант «dslb#tenant1»:

На странице клиента-тенанта не должно быть вкладки Credentials.

Назначение пользователям ролей#

Для назначения пользователю ролей необходимо выполнить следующие действия:

  1. При необходимости добавить в realm нового пользователя:

    1. Перейти на страницу Users и добавить нового пользователя «testuser».

    2. На вкладке Credentials задать пользователю пароль (временный или постоянный):

  2. Назначить пользователю роли:

    1. Перейти на страницу Users, открыть вкладку Role mappings и нажать Assign role.

    2. В фильтре выбрать Filter by client, выделить нужные роли (в примере — роль «ModelDeveloper»).

    3. Сняв флаг Hide inherited roles, можно увидеть полный перечень привилегий, назначенных пользователю.

Проверка настройки#

Для проверки настройки необходимо просмотреть состав формируемого пользователю access-токена. Для этого:

  1. Перейти на страницу Clients (на рисунке ниже — 1), выбрать клиента «ds-lab».

  2. Далее перейти на вкладку Client Scopes (на рисунке ниже — 2) и выбрать нужного пользователя из выпадающего списка (на рисунке ниже — 3).

  3. Выбрать Generated access token (на рисунке ниже — 4). Перечень ролей и привилегий пользователя в разрезе доступных тенантов будет приведен в claim resource_access.

    Внимание!

    Нужно убедиться, что в claim aud присутствует ds-lab, если же нет — проверить, что действия по созданию client scopes для клиента ds-lab выполнены в полном объеме.

Интеграция с IAM-Proxy#

IAM-Proxy выступает в роли граничного прокси, координирующего фронтальную аутентификацию и авторизацию. Может использоваться как единая точка входа. Предварительно необходимо убедиться, что должным образом сконфигурирован proxy-сервер. Для настройки proxy-сервера рекомендуется ознакомиться с документацией компонента IAM Proxy (AUTH) продукта Platform V IAM (IAM).

В DS Lab предусмотрены параметры, обеспечивающие работу в связке с proxy-сервером. Необходимо внести изменения в конфигурацию приложения в секцию overrideProperties:

  • dslb.integration.iamProxy.enable. Возможные значения:

    • true — интеграция с IAM-Proxy включена. В данном случае работа по обогащению jwt-токена значениями для авторизации будет происходить с участием сконфигурированного внешнего proxy-сервера.

    • false — интеграция отключена.

    Важно отметить, что для корректной работы интеграции необходимо наличие значения параметра jwks в секции настроек системы разграничения прав check.jwt.jwks. За счет этого выполняется условие проверки jwt-токена, полученного от прокси во время перенаправления.

  • dslb.integration.iamProxy.urlPrefix — позволяет задать пользовательский префикс для url, участвующий в формировании ссылки на веб интерфейс DS Lab.

    Например, urlPrefix: /test/tools приведет к формированию ссылки вида: http://{ingress.host}/test/tools/service/dataspace. Данный параметр также работает и при выключенной интеграции с iam.