Записи с темой: python (список заголовков)
20:59 

И, о важности корректной обработки исключений и индикации ошибок

Задача была простая. Нет, правда - простая. Сдернуть с корпоративной адресной книги на шарике список людей, фильтрануть их по должностям и заменить почти паре сотен неудачников пароли. Паре сотен плюс-минус, да. Т.е. руками еще наверное можно, но уже оч-чень не хочется.
Ок. Python, requests, берем, парсим, python_ldap, биндимся к домену, ищем УЗП, генерируем пароли по требованиям политики безопасности, пишем в csv'шку, меняем...
Не, ну процедура смены там страшная шозвиздец, без поллитры и мануаля никак - но с мануалем соорудить список кортежей для modify_s вполне можно. Сооружаем, пихаем - не выходит каменный цветок, на выходе:
"{'info': '0000001F: SvcErr: DSID-031A12D2, problem 5003 (WILL_NOT_PERFORM), data 0\n', 'desc': 'Server is unwilling to perform'}"
Гм. Ну да, правда - когда оно с первого раза работало? NOT PERFORM - похоже, пароль не соответствует требованиям, что там у нас? 8 символов, большие+маленькие+спецсимволы, пожалуй однострочник из random.sample('abc...ABC12...9!@#$@', 8) в качестве генератора паролей мог оказаться излишне оптимистичным, о! Чтоб не думать - засуну в бесконечный цикл и пихну break по успеху, за пару-тройку проходов точно чего-нибудь да сгенерит! Оп-па. Повис в усмерть. Т.е. генерит-сгенерить не может. А ну-ка, ручками? Гарантированно живой пароль? Хрена? Фигасе...
По хорошему в этот самый момент надо было выгружать фильтрованный список в csv и powershell'ом менять пароль - но а) мы легких путей не ищем! б) если у вас есть молоток - все вопросы начинают казаться гвоздями! и в) хорошая мысля приходит СИЛЬНО опосля.
А как он там его хранит-то? Мож, base64 какой? Охтыежты! UTF-16 да еще little endian? Не, ну тоже можно... encode('utf-16-le';) - хрена? Ошибка другая? Ой-ё. Ему еще кавычки нужны! Т.е. AD как раз не нужны, а вот openldap'у, оберткой к которому является python ldap очень даже. Ну, ок. Генерякаем UTF-16, ставим кавычки... Тот же 5003. Блина. Может ему не python'овская строка нужна, а что-то типа bytes из python3? Мало ли чего они там с юникодом навертели?
Туда. Сюда. Обратно. Два. Долбанных. Часа. После. Окончания. Рабочего. Времени. Проведенных. С wireshark'ом, ADExplorer'ом и openldap'ом. Не считая собственно python'а. С google'ем, как же без него?
И только опосля, deep inside в недрах технета нахожу... ЧТО ПАРОЛЬ НЕЛЬЗЯ МЕНЯТЬ ПОДКЛЮЧАЯСЬ К AD ПО LDAP!!! Только ldapS, только, мать её, бизопасТность, только хардкор! Меняем строку подключения - и все like a charm.
Ну овть нельзя было дать более осмысленное описание ошибки? Обработать исключение как следует на стороне хоть пихоновской обертки, хоть openldap'а?! Повбывав бы.

@темы: Python

14:12 

Ударим автопробегом по!

Помните старый анекдот про математиков?
"Два математика в ресторане поспорили, насколько хорошо знают математику большинство людей. Один (пессимист) утверждал, что большинство ее вообше не знает, а другой (оптимист) - что хоть и не много, но знают. Когда пессимист отошел в туалет, оптимист подозвал симпатичную официантку-блондинку и говорит:
- Когда мой коллега вернется, я задам вам вопрос. Суть не важна. Все, что вы должны сделать - это сказать "Треть икс куб".
- Как-как? Третий скуп? - переспрашивает официантка?
- Да нет, Треть Икс Куб, Понятно?
- А-а! Третик скуп? - повторяет официантка.
- Да, да. Это все о чем я вас прошу.
Официантка уходит твердя про себя как заклинание фразу "Третик скуп". Тут возвращается пессимист. Оптимист говорит - давай спросим у нашей официантки чему равен какой-нибудь простенький интеграл. Пессимист, со смехом соглашается. Оптимист вызывает официантку и спрашивает:
- Извините, вы не помните чему равен интеграл от x^2 по dх?
- Треть икс куб... - отвечает официантка.
Пессимист сильно удивлен, оптимист весело смеется. Официантка отходит на несколько шагов, и обернувшись через плечо добавляет:
- ...Плюс константа."(C)

Почувствовал себя персонажем анекдота: Заходит к нам в комнату бухгалтер, начинает злобно жаловаться на жизнь - мол, опять наше правительство что-то там "недомудрило" - тут в табличке все в рублях, там в копейках, дальше - в рублях с копейками, ниже не указано, по логике - писать надо в рублях, "на самом деле" - в копейках, а программа... Ленк! - задушевно говорю я - а давай я тебе про unicode расскажу? В базе данных у меня cp1251, kinterbasdb в connection понимает 1251 но результат отдает один черт, в unicode'е, да в добавок, python'а у меня ажно целых две версии - новая default'овская arch'а (3.1) + старая, с которой работает kinterbasdb (2.7), и с unicode'ом они работают СИЛЬНО по разному, а целевая платформа будет вообще под freebsd с koi8-r... Поговорили, в общем, о работе :). Ленка разворачивается и, уходя, бросает - "Unicode, unicode подумаешь - еще один байт..."
Мнда. Пора бы прекращать удивляться.

Слайды!

@темы: Python, Жизнь, Работа

12:26 

Нет, "утиная типизация"...

... и прочий разный по-ли-мо-физм, эт, кнечно, аффигеть, как хорошо просто и приятно, но когда внезапно!замечаешь, что анальное огораживание ручной контроль типов и обработка исключений начинают занимать больше места, чем собственно "полезный" код - начинаешь всерьёз задумываться об "ADA'е"...

@темы: Python, Работа

20:59 

Возвращаясь к...

... напечатанному - нарисовал таки я могутный скрЫпт на puthon'е, реализующий вышеуказанную функциональность, затестил, воткнул в cron - а потом чуть не родил, пытаясь понять, почему же он, сАбака, от user'а работает как положено (Приводит resolv.conf к виду
search (список доменов)
nameserver 127.0.0.1
И auto_forward.conf к состоянию
forwarders {
список адресов из resolv.conf'а;
};
forward first;
), а от root'а полностью убивает все линки в auto_forward.conf'е и выпиливает инструкцию nameserver из resolv.conf'а.
Ларчик, как водится, открылся просто:
целей отладки для я воткнул в свой скрипт не subprocess.Popen(['/usr/sbin/rndc', 'reload']), а subprocess.Popen(['/etc/rc.d/named', 'restart']) оставив named_auto_forward="YES" из rc.conf'а в неприкосновенности. В результате, вместо "мягкой" перезагрузки BIND'а происходил его рестарт родным скриптом, ожидающим, хе-хе! соответствующего содержимого resolv.conf'a и правящим auto_forward.conf под себя...
Мораль сей басни выводите сами )

@темы: FreeBSD, Python

15:32 

Еще один элегантный способ...

... отстрелить себе ногу.

Сижу, дописываю очередной скрипт на питоне, для разнообразия - версии 2.5 (Об этом как-нибудь еще будет - много и матерно). В зависимости от опций командной строки вывод должен идти либо на экран, либо в файл. По причине редкостной ублюдочности старого python'овского (До версии 2.6, ага) print'а, а так же нежелания плодить дублирующиеся фрагменты кода решаю сделать "финт ушами":
f = sys.stdout
if opt.verbose > 1:
f = open('бла-бла-бла','w')
ну и в коде, соответственно:
f.write('бла-бла-бла')
уже не заботясь о том, куда именно пишу. Для того, чтобы обеспечить гарантированное (Ибо нефиг!) закрытие файла в случае падения скрипта (Ну ма-ааало ли...) заворачиваю всю конструкцию (А вот нету в 2.5 менеджера контекста!) в
try:
...
finally:
f.close()
и запускаю. Оно, собственно, работает. Оно даже очень хорошо работает - вот только результат у sys.stdout.close() оказывается м-мммм... вполне предсказуемым, но в данном контексте весьма неожиданным ))))). Если бы работал не в screen'е - было бы совсем забавно, но и так - доставило ).

@темы: FreeBSD, Python

16:57 

Крик души

/Открывая документацию к SQLalchemy/ Почему, ну почему вещи, которые должны УПРОЩАТЬ жизнь настолько сложны?!

@темы: Python, Жизнь

14:58 

В процессе переноса скрипта...

... в рабочее окружение нашлись (Как водится, носом) очередные ГРАБЛИ:
LDAPObject.bind_s(<...>) проходит без ошибок, а
LDAPObject.search_s(<...>) говорит "In order to perform this operation a successful bind must be completed on the connection"
Бинд сделан, но бинд не сделан, ога. Такое ощущение что где-то внутрях модуля сэкономили на обработке исключений (Кстати, достаточно часто случается), ага.

Краткое (Минут 20 - действительно краткое) расследование показало, что всей разницы - в тестовой среде я для снижения нагрузки на контроллер домена передавал base DN для поиска в явном виде, а в рабочей среде в этом качестве используется domain root. Ага.
Использование асинхронного поиска и, на всякий случай - задание таймаута к успеху не привело. Затык-с.
Два часа копошения с помощью уже не python_ldap'а, а ADSIedit'а и openldap client'а, показало, что с неизвестного бодунища при поиске от корня домена MS AD первыми выдает REFFERAL's-сылки на forestdnszones, domaindnszones и пэ-рэ, на попытках проследовать по которым python_ldap и обламывается. Причем, обламывается действительно на попытке сделать _анонимный_ bind на ссылку, т.е. сообщение об ошибке было абсолютно правильным!

Трабла понятна, а вот что с ней делать... на ум приходят три варианта:
- лезть внутрь модуля (Да ну его нафиг!)
- задавать base DN для поиска (Вполне кошерно, но не всегда удобно)
- или - "Тадам!" нафиг отключить эти самые REFFERALS, что делается при помощи ldap.set_option(ldap.OPT_REFERRALS, 0) до выполнения ldap.open().

С чувством выполненного долга иду домой, чего и вам желаю.

@темы: Python

14:06 

... и закопал стюардессу!

Читаем шаблон в utf16. Made by notepad's defaults, надо бы пересохранить )
Преобразуем его в ASCII. Патамучта для unicod'а в питоне до версии 3.0 использовался отдельный тип данных, а модуль python_ldap жаждет получить на входе str или хотя бы list. Был бы utf8 оно бы и хрен с ним, а с utf16 - упс!
Ответ получаем в utf8. Ну, так он в MS AD хранится.
И записываем в cp1251. Ибо - meta http-equiv=Content-Type content="text/html; charset=windows-1251"
Вам еще не надоело? Мне вот уже!

@темы: Python

20:19 

... Вот квадратами они и стучат!(С)

Предыстория: понадобилось тут мне MS AD из питоновского скрипта кой о чем поспрошать: мол, "Подай-ка мне, о Великая, информацию во-о-оон о том сукином сынепользователе!", а чтоб знала, с-сссобака, кто тебя спрашивает - вот тебе мое каноническое имя в качестве параметра скрипта, да не просто -u 'CN=user,<...>', пользователя по имени "user", члена группы "Domain guests" с соответствующими правами, а то самое, полноценное.
Крикнул - а в ответ, натурально, тишина. User'у безродному, сталбыть, отвечает, а мне - не хочет.

Смотрим внутрь скрипта - ага, понятно. CN у меня фамилия с именем на русском языке - почти наверняка проблема с кодировками. Что там использует родной виндовый cmd.exe по умолчанию?
c:\chcp
'Текущая кодовая страница: 866'
ОК. Декодируем, преобразуем в юникод, спрашиваем домен, выводим на экран результат в той же 866... упс! И еще раз упс! И еще.
Пока я, готовясь уже завыть на луну не набил случайно <>.decode('cp151') - вуаля! Сработало.

Смотрим, что происходит:

Откуда взялись эти квадраты мне лично решительно непонятно - объясните люди добрые, кто тут дурак, а? А то ведь так и помру от любопытства, MS во всех смертных грехах обвиняя...

@темы: Python

Танец-с-саблями на граблях

главная