Ограничение доступа ТУЗ

KeyStack поддерживает возможность запрета доступа для ТУЗ с публичного эндпоинта. Для этого используются модули Lua в HAProxy, которые значительно расширяют его функциональность. В контексте OpenStack это позволяет создавать динамические правила для балансировки нагрузки между сервисами и реализовывать сложные сценарии управления трафиком, недоступные стандартными средствами.

Для работы с запросами служит скрипт lib-json.lua, который поставляется как часть сборки.

Для включения модуля Lua выполните следующие действия:

  1. Добавьте указанные переменные в globals.yml:

    haproxy_tag: "ks2024.2.5-sberlinux-haproxy"
    keystone_external_frontend_http_extra:
      - "option http-buffer-request"
      - "acl is_post method POST"
      - "http-request set-var(txn.body) req.body if is_post"
      - "http-request deny if { lua.is_forbidden_project_name -m bool }"
    
  2. Создайте файл config/haproxy/lua.d/keystone.lua (можно использовать любое имя файла с расширением .lua) со следующим содержанием:

    package.preload['lib-json']=loadfile('/etc/haproxy/scripts/lib-json.lua')
    local json = require('lib-json')
    
    function is_forbidden_project_name(txn)
        local req_body = txn.get_var(txn, "txn.body")
        if req_body == nil then
            return false
        end
    
        local success, data = pcall(json.decode, req_body)
        if success == false then
            return false -- We cannot decode the body of this request. So it's not our problem.
        end
    
        -- Trying to grab the value we needed. If we fail, then we continue
        local success, project_name = pcall(function()
            return data.auth.scope.project.name
        end)
    
        if success == true then
            if project_name == 'service' then
                return true
            end
        end
    
        -- Trying to grab the value we needed. If we fail, then we continue
        local success, project_id = pcall(function()
            return data.auth.scope.project.id
        end)
    
        if success == true then
            if project_id == '{{ keystone_service_project_id }}' then
                return true
            end
        end
    
        return false
    end
    
    core.register_fetches("is_forbidden_project_name", is_forbidden_project_name)