Настройки шлюза безопасности#

С помощью Blitz Identity Provider можно осуществлять контроль доступа при вызове приложениями защищаемых сервисов.

Обеспечение авторизации при вызове приложениями сервисов основано на спецификациях OAuth 2.0. Перед использованием сервисов приложение должно получить у Blitz Identity Provider маркер доступа (access_token). Для получения маркера доступа приложению доступны различные способы взаимодействия (см. Руководство по интеграции). При этом маркер доступа может быть получен:

  • в контексте входа пользователя – маркер будет включать информацию о пользователе и наборе согласий (разрешений), предоставленных пользователем приложению;

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

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

  • внутри каждого сервиса необходимо будет реализовывать собственную логику авторизации – проверять предоставленный маркер доступа, извлекать из него информацию о пользователе и предоставленных согласиях(разрешениях) и анализировать, достаточно ли их для выполнения сервиса или нет. Осуществлять протоколирование принятого решения по доступу.

  • приложение будет использовать единый маркер доступа для вызова различных сервисов. Маркер доступа в таком случае может содержать больше информации о пользователе и больший набор согласий (разрешений), чем нужно конкретному вызванному сервису. Это будет нарушать принцип наименьших привилегий – сервис получит больше прав доступа, чем ему необходимо для выполнения своей задачи.

Чтобы решить вышеописанные сложности в Blitz Identity Provider предусмотрено специальное приложение – шлюз безопасности (blitz-keeper). Это приложение представляет собой специализированный прокси-сервер, используемый при вызове защищаемых сервисов – приложение вызывает сервисы не напрямую, а через шлюз безопасности. При этом шлюз безопасности берет на себя выполнение следующих задач:

  • Проверяет включенный в вызов сервиса заголовок авторизации, извлекает из заголовка маркер доступа и, во взаимодействии с сервисом авторизации (blitz-idp) выполняет проверку, действителен ли маркер доступа, а также, достаточно ли у пользователя и приложения прав для вызова защищаемого сервиса.

  • Во взаимодействии с сервисом авторизации (blitz-idp) заменяет маркер доступа таким образом, чтобы передаваемый от шлюза безопасности к защищаемому сервису маркер безопасности содержал только тот набор сведений о пользователе и разрешений, который необходим для работы защищаемого сервиса. При этом из маркера безопасности могут быть как изъяты излишние разрешения и сведения о пользователе, так и наоборот, добавлены в маркер доступа дополнительные разрешения и сведения, если такое установлено политикой безопасности.

  • Протоколирует в журнале событий безопасности Blitz Identity Provider события успешной и неуспешной проверки прав доступа.

Взаимодействие шлюза безопасности с сервисом авторизации осуществляется на основе спецификации OAuth 2.0 Token Exchange. Иллюстрация взаимодействия приведена на схеме.

:size=80%

Схема взаимодействия при вызове приложением защищаемого сервиса#

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

  • Настройка Blitz Keeper.

  • Создание правил доступа к сервисам.

  • Регистрация правил обмена маркеров доступа в blitz.conf.

Настройка Blitz Keeper#

Настройка шлюза безопасности Blitz Keeper осуществляется путем редактирования конфигурационного файла blitz-keeper.conf, расположенного в каталоге /etc/blitz-keeper. Пример конфигурационного файла:

{
  "authenticators": {
    "prod-auth": {
      "type": "token-exchange",
      "te": "https://blitz-host/blitz/oauth/te",
    },
  },
  "services" : {
    "api-1":{
      "display-name" : "secured services",
      "host": "service-host.com",
      "locations": {
        "/api/service1/**": {
          "methods" : ["GET","POST"],
          "authenticator": "prod-auth",
          "required-scopes": ["scope1","scope2"]
        },
        "/path/api/user/*/getdata/**": {
          "methods" : ["GET","PUT"],
          "authenticator": "prod-auth",
          "required-scopes": ["scope3"]
        }
      }
    }
  }
}

В блоке authenticators нужно зарегистрировать все используемые сервисы авторизации blitz-idp. Обычно достаточно использовать один единственный сервис авторизации для защиты сервисов, и тогда нужно заполнить только один блок как в примере (в примере зарегистрирован один сервис авторизации с именем prod-auth). Если в системе используется несколько раздельных установок Blitz Identity Provider (например, ПРОД- и ТЕСТ-среда или внутренний контур для сотрудников и внешний контур для клиентов), то можно использовать общий шлюз безопасности, который будет взаимодействовать с несколькими разными сервисами авторизации – тогда нужно в блоке authenticators задать настройки нескольких сервисов авторизации. Для каждого сервиса авторизации задается имя (в примере использован prod-auth, но можно задать любое имя). В блоке настроек сервиса авторизации задается тип взаимодействия (type) в значении token-exchange (пока это единственный поддерживаемый тип взаимодействия) и адрес (te) вызова обработчика Token Endpoint сервиса авторизации. Если blitz-keeper развернут на отдельных серверах, то рекомендуется задать адрес обработчика с https и доменным именем. Если приложение blitz keeper развернуто на том же сервере что сервис авторизации blitz-idp, то рекомендуется задать в te локальное имя, например, http://localhost:9000/blitz/oauth/te.

В блоке services нужно зарегистрировать защищаемые сервисы. Для всех защищаемых сервисов можно создать общий блок настроек или несколько отдельных блоков. Каждый блок имеет имя (в примере, api-1). Внутри блока задаются настройки:

  • display-name – текстовое описание сервиса (любой комментарий или описание);

  • host – адрес сервера защищаемого сервиса;

  • locations – допустимые пути и операции вызова сервиса.

В блоке locations указываются настройки всех путей сервиса и разрешенных методов. В качестве имени каждого вложенного блока указывается адрес сервиса. Допустимо в адресе использовать звездочку (*), чтобы указать на пропуск отдельного компонента в адресе пути сервиса и допустимо использовать двойную звездочку (**), чтобы указать, что вся оставшаяся часть пути сервиса может быть любая. Внутри вложенного блока с адресом сервиса можно опционально перечислить разрешенные методы сервиса (настройка methods), указать имя используемого сервиса авторизации (настройка authenticator) и перечень разрешений (настройка required-scopes) для целевого маркера доступа, которые будут включены в маркер доступа, передаваемый в защищаемый сервис.

После изменения настроек в blitz-keeper.conf необходимо перезапустить шлюз безопасности.

Создание правил доступа к сервисам#

Правила доступа к сервисам создаются в директории /usr/share/identityblitz/blitz-config/token-exchange/rules/. Каждое правило создается как отдельный текстовый файл без расширения.

Пример файла с правилом доступа:

{
    "name": "rule-name",
    "type": "specialize",
    "desc": "",
    "subjectTokenCond": {
        "clientRights": [],
        "userRights": [],
        "scopes": ["openid"],
        "userClaims": {},
        "userGroups": []
    },
    "issue": {
        "ttlInSec": 3600,
        "allowedScopes": ["openid","profile"],
        "allowedClaims": ["sub","global_role","org_id","rights"],
        "addingScopes": [],
        "addingClaims": []
    }
}

Нужно заполнить следующие атрибуты правила доступа:

  • name – имя правила, которое должно совпадать с именем файла с правилом доступа;

  • type – тип правила. Пока поддерживается один тип правил – specialize;

  • desc – описание правила. Можно ввести любую текстовую информацию;

  • subjectTokenCond – условия выполнения правила. Если все указанные в правиле условия будут выполняться, то правило считается выполненным. Если хотя бы одно из условий в правиле не будет выполнено, то все правило считается невыполненным. Условия выполнения правил могут быть следующие:

    • clientRights – проверка наличия у приложения указанных прав доступа;

    Пример правила:

    "clientRights": [
    {
        "rights": ["right1"],
        "target": {
        "type": "its",
        "name": "app1"
        }
    }
    ]
    

    В указанном примере проверяется наличие у вызывающего приложения права доступа right1 в отношении другого приложения (app1). Параметр its в настройке target указывает тип объекта, в отношении которого проверяется наличие права доступа. Возможные значения: its – право на приложение; grps – право на группу доступа; отсутствие type – право на учетную запись пользователя.

    • userRights – проверка наличия у пользователя указанных прав доступа.

    Пример 1 правила:

    "userRights": [
    {
        "rights": ["right2"],
        "target": {
        "type": "grps",
        "name": "org1",
        "ext": "orgs"
        }
    }
    ]
    

    В указанном примере проверяется наличие у пользователя права доступа right2 в отношении группы пользователей (org1). В случае типа объекта группы доступа указывается дополнительный параметр ext, определяющий профиль группы доступа (см. Группы пользователей).

    Пример 2 правила:

    "userRights": [
    {
        "rights": ["security_administrator"],
        "target": {
        "type": "grps",
        "name": "${org_id}",
        "ext": "orgs"
        }
    }
    ]
    

    В указанном правиле проверяется наличие у пользователя права доступа security_administrator в отношении группы пользователей из профиля orgs, имеющей идентификатор, совпадающий со значением атрибута org_id из состава исходного маркера доступа. В отличии от примера 1 в данном примере иллюстрируется возможность в качестве имени объекта права доступа указывать не конкретное значение объекта, а ссылаться на объект на основе значений из присланного маркера доступа ($org_id).

    Пример 3 правила:

    "userRights": [
    {
        "rights": ["right3"],
        "target": {
        "type": "its",
        "name": "app1"
        }
    }
    ]
    

    В данном примере проверяется наличие у пользователя права доступа right3 в отношении приложения app1.

    Пример правила:

    "scopes": ["scope1"]
    

    В данном примере проверяется наличие в исходном маркере доступа разрешения с именем scope1.

    • userClaims – проверка, что у учетной записи пользователя атрибуты имеют указанные значения.

    Пример правила:

    "userClaims": {"role":"FIN"}
    

    В данном примере проверяется наличие у пользователя в учетной записи атрибута role с заполненным значением FIN. Допустимо использовать только атрибуты с типом String.

    • userGroups – проверка, что учетная запись пользователя входит в указанные группы доступа.

    Пример правила:

    "userGroups": [
    {
        "name": "admin",
        "profile": "roles"
    }
    ]
    

    В данном примере проверяется, что пользователь входит в группу доступа admin с профилем roles.

  • issue – правила выпуска нового маркера доступа, применяемые в случае, если правило было успешно выполнено. Правила выпуска нового маркера доступа состоят из:

    • ttlInSec – время жизни (в секундах) выпускаемого маркера доступа;

    • allowedScopes – разрешения, которые можно оставить в выпускаемом маркере доступа;

    • allowedClaims – атрибуты пользователя, которые можно оставить в выпускаемом маркере доступа;

    • addingScopes – добавляемые в маркер доступа разрешения;

    • addingClaims – добавляемые в маркер доступа атрибуты пользователя.

Настройка правил обмена маркеров доступа#

Чтобы определить, для каких защищаемых сервисов какие должны применяться правила доступа, необходимо в конфигурационном файле blitz.conf добавить блок настроек blitz.prod.local.idp.token-exchange следующего вида:

"token-exchange" : {
  "resources" : [
    {
      "rules" : [
        "rule1", "rule2"
      ],
      "audience" : "secured-api",
      "uri" : http://secured_service_host/api/service1,
      "methods" : ["GET","POST"]
    },
    {
      "rules" : [
        "rule3"
      ],
      "uri" : http://secured_service_host/api/service2
    },
    …
  ]
}

В блоке resources нужно для каждого сервиса заполнить настройки:

  • rules – перечислить имена правил доступа к сервису. Каждому правилу соответствует свой файл настроек. Доступ к сервису разрешается, если хотя бы одно из правил из этого списка будет выполненным. Если все перечисленные правила не будут выполнены, то тогда доступ к сервису будет запрещен;

  • uri – адрес защищаемого сервиса. В задании адреса сервиса допустимо использовать звездочку (*) для пропуска одного компонента пути адреса и двойную звездочку (**) для пропуска оставшейся части пути адреса сервиса;

  • audience – необязательный параметр, может задавать логическое имя вызываемого сервиса. Данное значение будет включено в выпущенный новый маркер доступа в атрибут aud;

  • methods – необязательный параметр, указывает перечень HTTP-методов вызываемого сервиса.