Задать вопрос
  • Как отправить POST запрос в Python с использованием сертификата p12?

    @alexandrsemen4ukk Автор вопроса
    Юрий, смотри,
    1. cert_file и key_file - атрибуты метода (имхо), в них мы передаем распакованные сертификат и ключ. Для того, чтобы извлечь сертификат и ключ я навоял PKCS12Manager. Просто для того, чтобы из .p12 извлечь cert и key файлы (по сути публичный и приватный сертификаты, которые в запрос передаются).
    2. Без него можно обойтись, если сможешь извлечь файлы любым другим способом.

    Код на коленке собрал, могут быть опечатки, это усложненный вариант для понимания, того как это работает.

    import base64
    import http.client
    import random
    import ssl
    
    from utils.PKCS12Manager import PKCS12Manager
    
    
    def generate_basic_auth(client_id, client_secret):
        credentials = f'{client_id}:{client_secret}'
        encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
        auth_header = f'Basic {encoded_credentials}'
        return auth_header
    
    
    def getSslContext():
    # Отключаем проверку SSL 
        context = ssl.SSLContext()  # add SSL context
        context.verify_mode = ssl.CERT_NONE  # disable verification
        return context
    
    
    def generate_RqUID():
    # Рандоманый UID для записи сбера, позволяют помечать запросы 
        pattern = "([0-9]|[a-f]|[A-F]){32}"
        chars = "0123456789abcdefABCDEF"
        random_string = ""
    
        for _ in range(32):
            random_string += random.choice(chars)
    
        return random_string
    
    
    def requestToken():
    # Пример запроса 
    
        headers = {
            'Authorization': auth,
            'RqUID': generate_RqUID(),
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        }
    
        payload = 'grant_type=client_credentials&scope=https://api.sberbank.ru/escrow'
        path = '/prod/tokens/v3/oauth'
        ssl_context = getSslContext()
        connection = http.client.HTTPSConnection(
            host="mc.api.sberbank.ru",
            port=443,
            context=ssl_context,
            cert_file=certificate_manager.certFile,
            key_file=certificate_manager.keyfile
        )
        connection.request(method='POST', url=path, headers=headers, body=payload)
        response = connection.getresponse()
        return response
    
    
    cert = "/some/dir/my_cert.p12"
    passphrase = "" # Пароль от сертификата p12
    certificate_manager = PKCS12Manager(p12file=cert, passphrase=passphrase)
    client_id = ""
    client_secret = ""
    auth = generate_basic_auth(client_id, client_secret)  #
    token_response = requestToken()  # Вызываем запрос получения токена, который в последствии используется для выполнения запросов.
    Написано
  • Как отправить POST запрос в Python с использованием сертификата p12?

    @alexandrsemen4ukk Автор вопроса
    Юрий, Да, описывал решение чуть выше. Если вкратце, то я написал обертку для работы с p12, создаю временную дерикторию в которую кладу cert.pem и key.pem
    import os
    import shutil
    from OpenSSL import crypto
    from configs import TEMP_DIR
    
    class PKCS12Manager:
        def __init__(self, p12file, passphrase):
            self.p12file = p12file
            self.unlock = passphrase
            self.cert_storage_dir = ''
            self.keyfile = ''
            self.certFile = ''
    
            # Get filename without extension
            ext = os.path.splitext(p12file)
            self.filebasename = os.path.basename(ext[0])
    
            self.createPrivateCertStore()
            self.p12toPem()
    
        def getKey(self):
            return self.keyfile
    
        def getCert(self):
            return self.certFile
    
        def createPrivateCertStore(self):
            home = os.path.dirname(os.path.abspath(__file__))
            # home = os.path.expanduser('~')
            temp = TEMP_DIR
            if not os.path.exists(temp):
                os.mkdir(temp)
            os.chmod(temp, 0o700)
            self.cert_storage_dir = temp
    
        def p12toPem(self):
            p12 = crypto.load_pkcs12(open(self.p12file, 'rb').read(), bytes(self.unlock, 'utf-8'))
    
            # PEM formatted private key
            key = crypto.dump_privatekey(crypto.FILETYPE_PEM, p12.get_privatekey())
    
            self.keyfile = os.path.join(self.cert_storage_dir, self.filebasename + ".key.pem")
            open(self.keyfile, 'a').close()
            os.chmod(self.keyfile, 0o600)
            with open(self.keyfile, 'wb') as f:
                f.write(key)
    
            # PEM formatted certificate
            cert = crypto.dump_certificate(crypto.FILETYPE_PEM, p12.get_certificate())
    
            self.certFile = os.path.join(self.cert_storage_dir, self.filebasename + ".crt.pem")
            open(self.certFile, 'a').close()
            os.chmod(self.certFile, 0o644)
            with open(self.certFile, 'wb') as f:
                f.write(cert)
    
        def removeCertStorage(self):
            shutil.rmtree(self.cert_storage_dir)
            self.cert_storage_dir = ''


    После создаю SSL контекст без проверки и для запроса использую извлеченные из p12 cert и key
    context = ssl.SSLContext()
    context.verify_mode = ssl.CERT_NONE
    
    conn = http.client.HTTPSConnection("mc.api.sberbank.ru", 443, context=context, cert_file=cert, key_file=key)


    Для работы PKCS12Manager использую pyOpenSSL=23.2.0

    Решение не очень красивое, но рабочее)
    Написано
  • Как настроить Apache2 под два типа авторизации?

    @alexandrsemen4ukk Автор вопроса
    Сергей Горностаев, вот их не много на самом деле, есть одно старое и частично рабочее я его довел до ума путем написания собственного бэка для авторизации, но это не решает проблему того, что хромиум навязывает мне форму авторизации, которую у него не просят. Я даже на апаче запртил любую другую авторизацию кроме Kerberos, а он мне всё равно говорит: "вводи давай, это бесполезно, но вводи"
    Написано
  • Как настроить Apache2 под два типа авторизации?

    @alexandrsemen4ukk Автор вопроса
    Сергей Горностаев, вообще вся проблема в том, что браузеры на хромиум при неуспешной авторизации через Kerberos предлагают пользователю использовать базовую аутентификацию из-за чего у меня появляется две формы авторизации: первая от браузера (которая ни на что не влияет просто решает, что пользователя нужно авторизовать через base), вторая уже от самого Kerberos если я указываю параметр KrbMethodK5Passwd on и от этого все беды. Т.к. если я выключу KrbMethodK5Passwd off, то не смогу дать возможность выполнять авторизацию вне домена, а если включу, то пользователи должны будут вводить авторизационные данные дважды и никакие правила редиректа на срабатывают, т.к. первую форму авторизации инициирует браузер до того как выполнится редирект, а мне всего-то нужно, чтобы при входе на сайт, если пользователя через kerberos не автризовало, чтобы его отправляло на страницу /login, где можно выполнить авторизацию по логину и паролю
    Написано
  • Как настроить Apache2 под два типа авторизации?

    @alexandrsemen4ukk Автор вопроса
    Сергей Горностаев, спасибо за ответ! Да вот я бы с радостью, но сквозная авторизация Kerberos достигается на уровне апача. Если сквозную авторизацию можно реализовать каким-то другим способом это было бы сказкой, особенно если можно было бы сделать это на Nginx. Как я понимаю сам джанго не может выполнять аутентификацию через домен, это делает apache через Kerberos
    Написано
  • Как заставить Django и Active Directory работать "правильно" с Kerberos?

    @alexandrsemen4ukk Автор вопроса
    Ах да, буду очень признателен, если кто-то подскажет как сделать так, чтобы если авторизация из Kerberos не удалась (заходим на сайт находясь не в домене), то чтобы открывалась стандартная страница авторизации из Django /login/. Потому что там уже настроена LDAP авторизация через AD с синхронизацией пользовательских данных.
  • Как решить проблему с LDAP аутентификацией в Django?

    @alexandrsemen4ukk Автор вопроса
    Да, я же говорю, что тестовый скрипт, не интеграция с Джанго успешно подключается (выше код). А именно когда используется django-ldap-auth, то пишет что не может найти сервер. Думаю что дело может быть в этом, потому что на этапе установки pip один из пакетов не хотел ставить, т.к. официального пакета не было под Виндоус, но на сайте автора пакета была ссылка на неофициальную компиляцию пакета под виндовс (и на многих формах по проблеме с этим пакетом его рекомендовали ставить), в общем он стал и я забыл, а сейчас склонен понимать что скорее всего дело в нем. Потому что на Линукс сервер этот конфиг Джанго работает
  • Как решить проблему с LDAP аутентификацией в Django?

    @alexandrsemen4ukk Автор вопроса
    Drno, я просто не вкурил зачем туннелирование, поэтому спросил) по ssh PyCharm только на лицензии Professional работает, а такой нет, да и купить проблематично
  • Как решить проблему с LDAP аутентификацией в Django?

    @alexandrsemen4ukk Автор вопроса
    Drno, а в каких целях putty+ssh? Тип примонтировать папку проекта в Винду и писать из ide на винде?
  • Как решить проблему с LDAP аутентификацией в Django?

    @alexandrsemen4ukk Автор вопроса
    Drno, эх... Боль работы через виртуалку...
  • Как решить проблему с LDAP аутентификацией в Django?

    @alexandrsemen4ukk Автор вопроса
    Роман Безруков, да, порты проверял. Ну и я говорю, что если тестовое подключение делать не через Джанго, а просто скриптом, то он выполняется. Выполняется авторизация и поиск. Скорее всего человек из первого комментария прав и все дело наверняка в виндовс
  • Как создать задачу в планировщике задач windows, чтобы она выполнялась на всех пользователях?

    @alexandrsemen4ukk Автор вопроса
    Спасибо тебе, добрый человек! Я почему-то думал что система будет подхватывать пользователя из "$env:USERNAME" при входе в систему (почему так думал не готов ответить :D ), а нужно было просто указать SID группы пользователей
  • Как отправить POST запрос в Python с использованием сертификата p12?

    @alexandrsemen4ukk Автор вопроса
    Даниил Рыжов, спасибо, мне нужны эскроу-счета, а не сбер-пэй)
  • Как отправить POST запрос в Python с использованием сертификата p12?

    @alexandrsemen4ukk Автор вопроса
    Justa Gain, спасибо за ответы! Разобрался.

    В любом случае p12 приходится разбивать на pem, если использовать request, то verify=Falsе - помогает, если http.client.HTTPSConnection, то нужно создать контекст и передать его
    context = ssl.SSLContext()
    context.verify_mode = ssl.CERT_NONE
    
    conn = http.client.HTTPSConnection("mc.api.sberbank.ru", 443, context=context, cert_file=cert, key_file=key)
  • Как отправить POST запрос в Python с использованием сертификата p12?

    @alexandrsemen4ukk Автор вопроса
    Justa Gain, а где взять сертификат CA умеющий подтверждать сберовский? и как его установить? verifiy=False - вообще же отключает ssl сертификат, который я отправляю или отправляемый сертификат просто не будет проходить проверку в системе, но в сбер от отправится?
  • Почему не отображается заполнитель и иконка инпута даты в bootstrap на мобильных устройствах?

    @alexandrsemen4ukk Автор вопроса
    В такой реализации не очень удобно то, что нужно кликнуть сначала на инпут, который является текстом, после клика он изменится на инпут дату и нужно будет ещё раз на него жать, чтобы открыть датапикер. В общем как по мне не очень, для себя можно сделать, а для продакшена - не прокатит.
  • Почему не отображается заполнитель и иконка инпута даты в bootstrap на мобильных устройствах?

    @alexandrsemen4ukk Автор вопроса
    Sergey В., да я его и не передаю в явном виде, я устанавливаю минимальную дату и максимальную, в том формате, который javascript отдаёт из Date() и привожу его к ISOString удаляя ненужное из строки. Вот так:
    $(document).ready(function() {
        var date = new Date();
        // var today = date.toISOString().slice(0, 10);
        var minInput = new Date(date.setDate(date.getDate() + 3)).toISOString().slice(0, 10);
        var maxInput = new Date(date.setDate(date.getDate() + 7)).toISOString().slice(0, 10);
    
        $("#checkDate").attr('min', minInput);
        $("#checkDate").attr('max', maxInput);
    
        $('.phonenumb').inputmask("+7 (999) 999-99-99"); 
    });

    В таком варианте для меня является удобным то, что автоматически подставляется текущий месяц и год, который нельзя поменять, а вот день остаётся не заполненным
  • Как работать с содержимым iCal в Python?

    @alexandrsemen4ukk Автор вопроса
    Спасибо, попробую!